diff --git a/.config/lychee.toml b/.config/lychee.toml index 733b77ec0cff9e616ecc0f851d9a3ed5e8574636..1de9fcd559dd9ea14fb603b7740efebcb893ed93 100644 --- a/.config/lychee.toml +++ b/.config/lychee.toml @@ -32,12 +32,10 @@ exclude = [ "https://github.com/paritytech/polkadot-sdk/substrate/frame/timestamp", "https://github.com/paritytech/substrate/frame/fast-unstake", "https://github.com/zkcrypto/bls12_381/blob/e224ad4ea1babfc582ccd751c2bf128611d10936/src/test-data/mod.rs", + "https://polkadot-try-runtime-node.parity-chains.parity.io/", "https://polkadot.network/the-path-of-a-parachain-block/", - "https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results", "https://research.web3.foundation/en/latest/polkadot/NPoS/3.%20Balancing.html", "https://research.web3.foundation/en/latest/polkadot/Token%20Economics.html#inflation-model", - "https://research.web3.foundation/en/latest/polkadot/block-production/Babe.html", - "https://research.web3.foundation/en/latest/polkadot/block-production/Babe.html#-6.-practical-results", "https://research.web3.foundation/en/latest/polkadot/networking/3-avail-valid.html#topology", "https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html", "https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html#inflation-model", @@ -53,5 +51,6 @@ exclude = [ "https://www.reddit.com/r/rust/comments/3spfh1/does_collect_allocate_more_than_once_while/", # 403 rate limited: "https://etherscan.io/block/11090290", + "https://subscan.io/", "https://substrate.stackexchange.com/.*", ] diff --git a/.config/zepter.yaml b/.config/zepter.yaml index f701392d16b15aab8351b730efa13f3abffe2406..9b3bd9d618c14e41f1dbf420aff3fee1677e2830 100644 --- a/.config/zepter.yaml +++ b/.config/zepter.yaml @@ -25,9 +25,13 @@ workflows: '--show-path', '--quiet', ] - # Same as `check`, but with the `--fix` flag. + # The umbrella crate uses more features, so we to check those too: + check_umbrella: + - [ $check.0, '--features=serde,experimental,with-tracing,tuples-96,with-tracing', '-p=polkadot-sdk' ] + # Same as `check_*`, but with the `--fix` flag. default: - [ $check.0, '--fix' ] + - [ $check_umbrella.0, '--fix' ] # Will be displayed when any workflow fails: help: diff --git a/.forklift/config.toml b/.forklift/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..ab3b2729a46d4e54dc77df1175d4ebe79eda46d0 --- /dev/null +++ b/.forklift/config.toml @@ -0,0 +1,33 @@ +[compression] +type = "zstd" + +[compression.zstd] +compressionLevel = 3 + +[general] +jobNameVariable = "CI_JOB_NAME" +jobsBlackList = [] +logLevel = "warn" +threadsCount = 6 + +[cache] +extraEnv = ["RUNTIME_METADATA_HASH"] + +[metrics] +enabled = true +pushEndpoint = "placeholder" + +[metrics.extraLabels] +environment = "production" +job_name = "$CI_JOB_NAME" +project_name = "$CI_PROJECT_PATH" + +[storage] +type = "s3" + +[storage.s3] +accessKeyId = "placeholder" +bucketName = "placeholder" +concurrency = 10 +endpointUrl = "placeholder" +secretAccessKey = "placeholder" diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 0000000000000000000000000000000000000000..ceceb9e63654ce83c942571dea79cae29f15d851 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,9 @@ +coverage: + precision: 2 + round: down + range: "1...100" + status: + project: + default: + target: 1.0 + threshold: 2.0 \ No newline at end of file diff --git a/.github/env b/.github/env new file mode 100644 index 0000000000000000000000000000000000000000..162ce8af7c0ddbc1534b7d1ffb09cff4be012fc7 --- /dev/null +++ b/.github/env @@ -0,0 +1 @@ +IMAGE="docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v20240408" \ No newline at end of file diff --git a/.github/scripts/deny-git-deps.py b/.github/scripts/deny-git-deps.py new file mode 100644 index 0000000000000000000000000000000000000000..4b831c9347f75bdc3c74c80d3af652c37e7ae459 --- /dev/null +++ b/.github/scripts/deny-git-deps.py @@ -0,0 +1,40 @@ +""" +Script to deny Git dependencies in the Cargo workspace. Can be passed one optional argument for the +root folder. If not provided, it will use the cwd. + +## Usage + python3 .github/scripts/deny-git-deps.py polkadot-sdk +""" + +import os +import sys + +from cargo_workspace import Workspace, DependencyLocation + +KNOWN_BAD_GIT_DEPS = { + 'simple-mermaid': ['xcm-docs'], + # Fix in + 'bandersnatch_vrfs': ['sp-core'], +} + +root = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() +workspace = Workspace.from_path(root) + +def check_dep(dep, used_by): + if dep.location != DependencyLocation.GIT: + return + + if used_by in KNOWN_BAD_GIT_DEPS.get(dep.name, []): + print(f'🤨 Ignoring git dependency {dep.name} in {used_by}') + else: + print(f'🚫 Found git dependency {dep.name} in {used_by}') + sys.exit(1) + +# Check the workspace dependencies that can be inherited: +for dep in workspace.dependencies: + check_dep(dep, "workspace") + +# And the dependencies of each crate: +for crate in workspace.crates: + for dep in crate.dependencies: + check_dep(dep, crate.name) diff --git a/.github/workflows/check-changed-files.yml b/.github/workflows/check-changed-files.yml new file mode 100644 index 0000000000000000000000000000000000000000..657c05cd047db40af642886eb2710e7324dd40ce --- /dev/null +++ b/.github/workflows/check-changed-files.yml @@ -0,0 +1,57 @@ +# Reusable workflow to perform checks and generate conditions for other workflows. +# Currently it checks if any Rust (build-related) file is changed +# and if the current (caller) workflow file is changed. +# Example: +# +# jobs: +# changes: +# permissions: +# pull-requests: read +# uses: ./.github/workflows/check-changed-files.yml +# some-job: +# needs: changes +# if: ${{ needs.changes.outputs.rust }} +# ....... + +name: Check changes files + +on: + workflow_call: + # Map the workflow outputs to job outputs + outputs: + rust: + value: ${{ jobs.changes.outputs.rust }} + description: 'true if any of the build-related OR current (caller) workflow files have changed' + current-workflow: + value: ${{ jobs.changes.outputs.current-workflow }} + description: 'true if current (caller) workflow file has changed' + +jobs: + changes: + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + # true if current workflow (caller) file is changed + rust: ${{ steps.filter.outputs.rust == 'true' || steps.filter.outputs.current-workflow == 'true' }} + current-workflow: ${{ steps.filter.outputs.current-workflow }} + steps: + - id: current-file + run: echo "current-workflow-file=$(echo ${{ github.workflow_ref }} | sed -nE "s/.*(\.github\/workflows\/[a-zA-Z0-9_-]*\.y[a]?ml)@refs.*/\1/p")" >> $GITHUB_OUTPUT + - run: echo "${{ steps.current-file.outputs.current-workflow-file }}" + # For pull requests it's not necessary to checkout the code + - id: filter + uses: dorny/paths-filter@v3 + with: + predicate-quantifier: 'every' + # current-workflow - check if the current (caller) workflow file is changed + # rust - check if any Rust (build-related) file is changed + filters: | + current-workflow: + - '${{ steps.current-file.outputs.current-workflow-file }}' + rust: + - '**/*' + - '!.github/**/*' + - '!prdoc/**/*' + - '!docs/**/*' + # \ No newline at end of file diff --git a/.github/workflows/check-features.yml b/.github/workflows/check-features.yml index 53d6ac6b4dbfd7e3ccf1ca09ad9e1e70a49a9ff9..d34b3d52c5332b61d9a90dc03de938f154de5c7e 100644 --- a/.github/workflows/check-features.yml +++ b/.github/workflows/check-features.yml @@ -13,7 +13,7 @@ jobs: - name: Check uses: hack-ink/cargo-featalign-action@bea88a864d6ca7d0c53c26f1391ce1d431dc7f34 # v0.1.1 with: - crate: substrate/bin/node/runtime + crate: templates/parachain/runtime/ features: std,runtime-benchmarks,try-runtime ignore: sc-executor default-std: true diff --git a/.github/workflows/check-licenses.yml b/.github/workflows/check-licenses.yml index c32b6fcf89e06bb56cefc0517e1dcab1d1ef0f37..3bc95305f7467ebbede90526eadb156b89b1e7f9 100644 --- a/.github/workflows/check-licenses.yml +++ b/.github/workflows/check-licenses.yml @@ -10,6 +10,7 @@ permissions: jobs: check-licenses: runs-on: ubuntu-latest + timeout-minutes: 10 env: LICENSES: "'Apache-2.0' 'GPL-3.0-only' 'GPL-3.0-or-later WITH Classpath-exception-2.0'" NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml deleted file mode 100644 index 2b8a66db35b3adacea4f131a881103d48e3704ae..0000000000000000000000000000000000000000 --- a/.github/workflows/check-markdown.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Check Markdown - -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - merge_group: - -permissions: - packages: read - -jobs: - lint-markdown: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - uses: actions/setup-node@v4.0.1 - with: - node-version: "18.x" - registry-url: "https://npm.pkg.github.com" - scope: "@paritytech" - - - name: Install tooling - run: | - npm install -g markdownlint-cli - markdownlint --version - - - name: Check Markdown - env: - CONFIG: .github/.markdownlint.yaml - run: | - echo "Checking markdown formatting. More info: docs/contributor/markdown_linting.md" - markdownlint --config "$CONFIG" --ignore target . diff --git a/.github/workflows/check-runtime-migration.yml b/.github/workflows/check-runtime-migration.yml new file mode 100644 index 0000000000000000000000000000000000000000..984e264d0d1d1d9c8ac1730c51950194cce56276 --- /dev/null +++ b/.github/workflows/check-runtime-migration.yml @@ -0,0 +1,122 @@ +name: check-runtime-migration + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + merge_group: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + FORKLIFT_storage_s3_bucketName: ${{ secrets.FORKLIFT_storage_s3_bucketName }} + FORKLIFT_storage_s3_accessKeyId: ${{ secrets.FORKLIFT_storage_s3_accessKeyId }} + FORKLIFT_storage_s3_secretAccessKey: ${{ secrets.FORKLIFT_storage_s3_secretAccessKey }} + FORKLIFT_storage_s3_endpointUrl: ${{ secrets.FORKLIFT_storage_s3_endpointUrl }} + FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }} + +jobs: + set-image: + # GitHub Actions allows using 'env' in a container context. + # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322 + # This workaround sets the container image for each job using 'set-image' job output. + runs-on: ubuntu-latest + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + # rococo and westend are disabled for now (no access to parity-chains.parity.io) + check-runtime-migration: + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + strategy: + fail-fast: false + matrix: + network: [ + # westend, + # rococo, + asset-hub-westend, + asset-hub-rococo, + bridge-hub-westend, + bridge-hub-rococo, + contracts-rococo, + collectives-westend, + coretime-rococo, + ] + include: + # - network: westend + # package: westend-runtime + # wasm: westend_runtime.compact.compressed.wasm + # uri: "wss://westend-try-runtime-node.parity-chains.parity.io:443" + # subcommand_extra_args: "--no-weight-warnings" + # command_extra_args: "" + # - network: rococo + # package: rococo-runtime + # wasm: rococo_runtime.compact.compressed.wasm + # uri: "wss://rococo-try-runtime-node.parity-chains.parity.io:443" + # subcommand_extra_args: "--no-weight-warnings" + # command_extra_args: "" + - network: asset-hub-westend + package: asset-hub-westend-runtime + wasm: asset_hub_westend_runtime.compact.compressed.wasm + uri: "wss://westend-asset-hub-rpc.polkadot.io:443" + subcommand_extra_args: "" + command_extra_args: "" + - network: "asset-hub-rococo" + package: "asset-hub-rococo-runtime" + wasm: "asset_hub_rococo_runtime.compact.compressed.wasm" + uri: "wss://rococo-asset-hub-rpc.polkadot.io:443" + subcommand_extra_args: "" + command_extra_args: "" + - network: "bridge-hub-westend" + package: "bridge-hub-westend-runtime" + wasm: "bridge_hub_westend_runtime.compact.compressed.wasm" + uri: "wss://westend-bridge-hub-rpc.polkadot.io:443" + - network: "bridge-hub-rococo" + package: "bridge-hub-rococo-runtime" + wasm: "bridge_hub_rococo_runtime.compact.compressed.wasm" + uri: "wss://rococo-bridge-hub-rpc.polkadot.io:443" + - network: "contracts-rococo" + package: "contracts-rococo-runtime" + wasm: "contracts_rococo_runtime.compact.compressed.wasm" + uri: "wss://rococo-contracts-rpc.polkadot.io:443" + - network: "collectives-westend" + package: "collectives-westend-runtime" + wasm: "collectives_westend_runtime.compact.compressed.wasm" + uri: "wss://westend-collectives-rpc.polkadot.io:443" + command_extra_args: "--disable-spec-name-check" + - network: "coretime-rococo" + package: "coretime-rococo-runtime" + wasm: "coretime_rococo_runtime.compact.compressed.wasm" + uri: "wss://rococo-coretime-rpc.polkadot.io:443" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: | + echo "Running ${{ matrix.network }} runtime migration check" + export RUST_LOG=remote-ext=debug,runtime=debug + + echo "---------- Downloading try-runtime CLI ----------" + curl -sL https://github.com/paritytech/try-runtime-cli/releases/download/v0.5.4/try-runtime-x86_64-unknown-linux-musl -o try-runtime + chmod +x ./try-runtime + echo "Using try-runtime-cli version:" + ./try-runtime --version + + echo "---------- Building ${{ matrix.package }} runtime ----------" + time forklift cargo build --release --locked -p ${{ matrix.package }} --features try-runtime + + echo "---------- Executing on-runtime-upgrade for ${{ matrix.network }} ----------" + time ./try-runtime ${{ matrix.command_extra_args }} \ + --runtime ./target/release/wbuild/${{ matrix.package }}/${{ matrix.wasm }} \ + on-runtime-upgrade --disable-spec-version-check --checks=all ${{ matrix.subcommand_extra_args }} live --uri ${{ matrix.uri }} + sleep 5 diff --git a/.github/workflows/check-semver.yml b/.github/workflows/check-semver.yml new file mode 100644 index 0000000000000000000000000000000000000000..04c63f4192b29ca1773d1018698b2abe6a666e1c --- /dev/null +++ b/.github/workflows/check-semver.yml @@ -0,0 +1,56 @@ +name: Check semver + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - prdoc/*.prdoc + +jobs: + check-semver: + runs-on: ubuntu-latest + container: + image: docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v20240408 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Rust Cache + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + with: + cache-on-failure: true + + - name: Rust compilation prerequisites + run: | + rustup default nightly-2024-03-01 + rustup target add wasm32-unknown-unknown --toolchain nightly-2024-03-01 + rustup component add rust-src --toolchain nightly-2024-03-01 + + - name: install parity-publish + run: cargo install parity-publish@0.5.1 + + - name: extra git setup + run: | + git config --global --add safe.directory '*' + git fetch --no-tags --no-recurse-submodules --depth=1 origin master + git branch old origin/master + + - name: check semver + run: | + export CARGO_TARGET_DIR=target + export RUSTFLAGS='-A warnings -A missing_docs' + export SKIP_WASM_BUILD=1 + if ! parity-publish --color always prdoc --since old --validate prdoc/pr_$PR.prdoc --toolchain nightly-2024-03-01 -v; then + cat < - python3 .github/scripts/check-workspace.py . - --exclude - "substrate/frame/contracts/fixtures/build" - "substrate/frame/contracts/fixtures/contracts/common" diff --git a/.github/workflows/checks-quick.yml b/.github/workflows/checks-quick.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd9baf0d1bc24bf866e89f9ce542b24e49086486 --- /dev/null +++ b/.github/workflows/checks-quick.yml @@ -0,0 +1,150 @@ +# Checks that doesn't require heavy lifting, like formatting, linting, etc. +name: quick-checks + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + merge_group: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + set-image: + # GitHub Actions allows using 'env' in a container context. + # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322 + # This workaround sets the container image for each job using 'set-image' job output. + runs-on: ubuntu-latest + timeout-minutes: 10 + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + fmt: + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Cargo fmt + run: cargo +nightly fmt --all -- --check + check-dependency-rules: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: check dependency rules + run: | + cd substrate/ + ../.gitlab/ensure-deps.sh + check-rust-feature-propagation: + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: run zepter + run: zepter run check + test-rust-features: + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: run rust features + run: bash .gitlab/rust-features.sh . + check-toml-format: + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: check toml format + run: | + taplo format --check --config .config/taplo.toml + echo "Please run `taplo format --config .config/taplo.toml` to fix any toml formatting issues" + check-workspace: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.0 (22. Sep 2023) + - name: install python deps + run: | + sudo apt-get update && sudo apt-get install -y python3-pip python3 + pip3 install toml "cargo-workspace>=1.2.6" + - name: check integrity + run: > + python3 .github/scripts/check-workspace.py . + --exclude + "substrate/frame/contracts/fixtures/build" + "substrate/frame/contracts/fixtures/contracts/common" + - name: deny git deps + run: python3 .github/scripts/deny-git-deps.py . + check-markdown: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout sources + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup Node.js + uses: actions/setup-node@v4.0.1 + with: + node-version: "18.x" + registry-url: "https://npm.pkg.github.com" + scope: "@paritytech" + - name: Install tooling + run: | + npm install -g markdownlint-cli + markdownlint --version + - name: Check Markdown + env: + CONFIG: .github/.markdownlint.yaml + run: | + echo "Checking markdown formatting. More info: docs/contributor/markdown_linting.md" + markdownlint --config "$CONFIG" --ignore target . + check-umbrella: + runs-on: arc-runners-polkadot-sdk + timeout-minutes: 10 + needs: [set-image] + container: + image: ${{ needs.set-image.outputs.IMAGE }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.0 (22. Sep 2023) + - name: install python deps + run: | + sudo apt-get update && sudo apt-get install -y python3-pip python3 + pip3 install "cargo-workspace>=1.2.4" toml + - name: check umbrella correctness + run: | + python3 scripts/generate-umbrella.py --sdk . --version 0.1.0 + cargo +nightly fmt --all + if [ -n "$(git status --porcelain)" ]; then + cat < Cargo.temp mv Cargo.temp ./templates/${{ matrix.template }}/Cargo.toml - - toml get Cargo.toml 'workspace.lints' --output-toml >> ./templates/${{ matrix.template }}/Cargo.toml - - toml get Cargo.toml 'workspace.dependencies' --output-toml >> ./templates/${{ matrix.template }}/Cargo.toml working-directory: polkadot-sdk - name: Print the result Cargo.tomls for debugging if: runner.debug == '1' @@ -120,6 +116,18 @@ jobs: - name: Copy over the new changes run: | cp -r polkadot-sdk/templates/${{ matrix.template }}/* "${{ env.template-path }}/" + - name: Copy over required workspace dependencies + run: | + echo -e "\n[workspace.dependencies]" >> Cargo.toml + set +e + # If a workspace dependency is required.. + while cargo tree --depth 1 --prefix none --no-dedupe 2>&1 | grep 'was not found in `workspace.dependencies`'; do + # Get its name.. + missing_dep=$(cargo tree --depth 1 --prefix none --no-dedupe 2>&1 | grep 'was not found in `workspace.dependencies`' | sed -E 's/(.*)`dependency.(.*)` was not found in `workspace.dependencies`/\2/') + # And copy the dependency from the monorepo. + toml get ../polkadot-sdk/Cargo.toml 'workspace.dependencies' --output-toml | grep "^${missing_dep} = " >> Cargo.toml + done; + working-directory: "${{ env.template-path }}" # 3. Verify the build. Push the changes or create a PR. @@ -148,12 +156,12 @@ jobs: token: ${{ steps.app_token.outputs.token }} add-paths: | ./* - title: "[Don't merge] Update the ${{ matrix.template }} template" + title: "[Don't merge] Update the ${{ matrix.template }} template to ${{ github.event.inputs.crate_release_version }}" body: "The template has NOT been successfully built and needs to be inspected." - branch: "update-template/${{ github.event_name }}" + branch: "update-template/${{ github.event.inputs.crate_release_version }}" - name: Push changes run: | git add -A . - git commit --allow-empty -m "Update template triggered by ${{ github.event_name }}" + git commit --allow-empty -m "Update to ${{ github.event.inputs.crate_release_version }} triggered by ${{ github.event_name }}" git push working-directory: "${{ env.template-path }}" diff --git a/.github/workflows/check-publish.yml b/.github/workflows/publish-check-crates.yml similarity index 81% rename from .github/workflows/check-publish.yml rename to .github/workflows/publish-check-crates.yml index b16b3d4e5c5c5061741e7ae698ff0a0e9e0c5084..9b5b89e34475699ccbcaeca34cd290882ee45a9a 100644 --- a/.github/workflows/check-publish.yml +++ b/.github/workflows/publish-check-crates.yml @@ -20,7 +20,7 @@ jobs: cache-on-failure: true - name: install parity-publish - run: cargo install parity-publish@0.3.0 + run: cargo install parity-publish@0.5.1 - name: parity-publish check - run: parity-publish check --allow-unpublished + run: parity-publish --color always check --allow-unpublished diff --git a/.github/workflows/claim-crates.yml b/.github/workflows/publish-claim-crates.yml similarity index 85% rename from .github/workflows/claim-crates.yml rename to .github/workflows/publish-claim-crates.yml index f3df0bce72d501ed22c66b9792e032becdd4da93..9643361d9d318f84d64a212358a825a8e0b5aa20 100644 --- a/.github/workflows/claim-crates.yml +++ b/.github/workflows/publish-claim-crates.yml @@ -18,9 +18,9 @@ jobs: cache-on-failure: true - name: install parity-publish - run: cargo install parity-publish@0.3.0 + run: cargo install parity-publish@0.5.1 - name: parity-publish claim env: PARITY_PUBLISH_CRATESIO_TOKEN: ${{ secrets.CRATESIO_PUBLISH_CLAIM_TOKEN }} - run: parity-publish claim + run: parity-publish --color always claim diff --git a/.github/workflows/subsystem-benchmarks.yml b/.github/workflows/publish-subsystem-benchmarks.yml similarity index 100% rename from .github/workflows/subsystem-benchmarks.yml rename to .github/workflows/publish-subsystem-benchmarks.yml diff --git a/.github/workflows/release-30_publish_release_draft.yml b/.github/workflows/release-30_publish_release_draft.yml index 430b1e26646758ef40218760fbd20f3a448f45f3..f39eb4c1716ebea4fb3207ea1a2ecc8227037448 100644 --- a/.github/workflows/release-30_publish_release_draft.yml +++ b/.github/workflows/release-30_publish_release_draft.yml @@ -23,13 +23,44 @@ jobs: echo "stable=$RUST_STABLE_VERSION" >> $GITHUB_OUTPUT build-runtimes: - uses: "./.github/workflows/srtool.yml" + uses: "./.github/workflows/release-srtool.yml" with: excluded_runtimes: "substrate-test bp cumulus-test kitchensink minimal-template parachain-template penpal polkadot-test seedling shell frame-try sp solochain-template" + build-binaries: + runs-on: ubuntu-latest + strategy: + matrix: + binary: [ frame-omni-bencher, chain-spec-builder ] + steps: + - name: Checkout sources + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Install protobuf-compiler + run: | + sudo apt update + sudo apt install -y protobuf-compiler + + - name: Build ${{ matrix.binary }} binary + run: | + if [[ ${{ matrix.binary }} =~ chain-spec-builder ]]; then + cargo build --locked --profile=production -p staging-${{ matrix.binary }} --bin ${{ matrix.binary }} + target/production/${{ matrix.binary }} -h + else + cargo build --locked --profile=production -p ${{ matrix.binary }} + target/production/${{ matrix.binary }} --version + fi + + - name: Upload ${{ matrix.binary }} binary + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: ${{ matrix.binary }} + path: target/production/${{ matrix.binary }} + + publish-release-draft: runs-on: ubuntu-latest - needs: [get-rust-versions, build-runtimes] + needs: [ get-rust-versions, build-runtimes ] outputs: release_url: ${{ steps.create-release.outputs.html_url }} asset_upload_url: ${{ steps.create-release.outputs.upload_url }} @@ -37,15 +68,15 @@ jobs: - name: Checkout uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + - name: Download artifacts + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + - name: Prepare tooling run: | URL=https://github.com/chevdor/tera-cli/releases/download/v0.2.4/tera-cli_linux_amd64.deb wget $URL -O tera.deb sudo dpkg -i tera.deb - - name: Download artifacts - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - - name: Prepare draft id: draft env: @@ -129,9 +160,34 @@ jobs: asset_name: ${{ matrix.chain }}_runtime-v${{ env.SPEC }}.compact.compressed.wasm asset_content_type: application/wasm + publish-binaries: + needs: [ publish-release-draft, build-binaries ] + continue-on-error: true + runs-on: ubuntu-latest + strategy: + matrix: + binary: [frame-omni-bencher, chain-spec-builder] + + steps: + - name: Download artifacts + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + name: ${{ matrix.binary }} + + - name: Upload ${{ matrix.binary }} binary + uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 #v1.0.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.publish-release-draft.outputs.asset_upload_url }} + asset_path: ${{ github.workspace}}/${{ matrix.binary }} + asset_name: ${{ matrix.binary }} + asset_content_type: application/octet-stream + post_to_matrix: runs-on: ubuntu-latest needs: publish-release-draft + environment: release strategy: matrix: channel: diff --git a/.github/workflows/release-99_notif-published.yml b/.github/workflows/release-99_notif-published.yml index 05c9d6a47f551860c51e318b01b495ca662e902e..b5b2ed38e845ea158d1c45c5da0e7d3358e77302 100644 --- a/.github/workflows/release-99_notif-published.yml +++ b/.github/workflows/release-99_notif-published.yml @@ -48,5 +48,3 @@ jobs: Release version: [${{github.event.release.tag_name}}](${{github.event.release.html_url}}) ----- - - ${{github.event.release.body}} diff --git a/.github/workflows/build-and-attach-release-runtimes.yml b/.github/workflows/release-build-and-attach-runtimes.yml similarity index 100% rename from .github/workflows/build-and-attach-release-runtimes.yml rename to .github/workflows/release-build-and-attach-runtimes.yml diff --git a/.github/workflows/check-runtimes.yml b/.github/workflows/release-check-runtimes.yml similarity index 100% rename from .github/workflows/check-runtimes.yml rename to .github/workflows/release-check-runtimes.yml diff --git a/.github/workflows/srtool.yml b/.github/workflows/release-srtool.yml similarity index 100% rename from .github/workflows/srtool.yml rename to .github/workflows/release-srtool.yml diff --git a/.github/workflows/test-github-actions.yml b/.github/workflows/test-github-actions.yml deleted file mode 100644 index c8ce49cb462b07b135d33158408958aa88a2aa21..0000000000000000000000000000000000000000 --- a/.github/workflows/test-github-actions.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: test-github-actions - -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - merge_group: -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_NET_GIT_FETCH_WITH_CLI: true - -jobs: - test-linux-stable-int: - runs-on: arc-runners-polkadot-sdk - timeout-minutes: 30 - container: - image: "docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v20240408" - env: - RUSTFLAGS: "-C debug-assertions -D warnings" - RUST_BACKTRACE: 1 - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" - # Ensure we run the UI tests. - RUN_UI_TESTS: 1 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: script - run: WASM_BUILD_NO_COLOR=1 time cargo test -p staging-node-cli --release --locked -- --ignored - quick-benchmarks: - runs-on: arc-runners-polkadot-sdk - timeout-minutes: 30 - container: - image: "docker.io/paritytech/ci-unified:bullseye-1.77.0-2024-04-10-v20240408" - env: - RUSTFLAGS: "-C debug-assertions -D warnings" - RUST_BACKTRACE: "full" - WASM_BUILD_NO_COLOR: 1 - WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: script - run: time cargo run --locked --release -p staging-node-cli --bin substrate-node --features runtime-benchmarks --quiet -- benchmark pallet --chain dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 --quiet diff --git a/.github/workflows/tests-linux-stable.yml b/.github/workflows/tests-linux-stable.yml new file mode 100644 index 0000000000000000000000000000000000000000..5fdfabc437fe721339af817f12aea1a58a6c0346 --- /dev/null +++ b/.github/workflows/tests-linux-stable.yml @@ -0,0 +1,81 @@ +# GHA for test-linux-stable-int, test-linux-stable, test-linux-stable-oldkernel +name: tests linux stable + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + merge_group: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + FORKLIFT_storage_s3_bucketName: ${{ secrets.FORKLIFT_storage_s3_bucketName }} + FORKLIFT_storage_s3_accessKeyId: ${{ secrets.FORKLIFT_storage_s3_accessKeyId }} + FORKLIFT_storage_s3_secretAccessKey: ${{ secrets.FORKLIFT_storage_s3_secretAccessKey }} + FORKLIFT_storage_s3_endpointUrl: ${{ secrets.FORKLIFT_storage_s3_endpointUrl }} + FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }} + +jobs: + + changes: + permissions: + pull-requests: read + uses: ./.github/workflows/check-changed-files.yml + + set-image: + # GitHub Actions allows using 'env' in a container context. + # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322 + # This workaround sets the container image for each job using 'set-image' job output. + needs: changes + if: ${{ needs.changes.outputs.rust }} + runs-on: ubuntu-latest + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + + test-linux-stable-int: + needs: [set-image, changes] + if: ${{ needs.changes.outputs.rust }} + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + container: + image: ${{ needs.set-image.outputs.IMAGE }} + env: + RUSTFLAGS: "-C debug-assertions -D warnings" + RUST_BACKTRACE: 1 + WASM_BUILD_NO_COLOR: 1 + WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" + # Ensure we run the UI tests. + RUN_UI_TESTS: 1 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: WASM_BUILD_NO_COLOR=1 time forklift cargo test -p staging-node-cli --release --locked -- --ignored + + # https://github.com/paritytech/ci_cd/issues/864 + test-linux-stable-runtime-benchmarks: + needs: [set-image, changes] + if: ${{ needs.changes.outputs.rust }} + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + container: + image: ${{ needs.set-image.outputs.IMAGE }} + env: + RUST_TOOLCHAIN: stable + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: time forklift cargo nextest run --workspace --features runtime-benchmarks benchmark --locked --cargo-profile testnet diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..293acadc4e6a892fea9aa7fa3686cd821606992a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,98 @@ +name: tests + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + merge_group: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + FORKLIFT_storage_s3_bucketName: ${{ secrets.FORKLIFT_storage_s3_bucketName }} + FORKLIFT_storage_s3_accessKeyId: ${{ secrets.FORKLIFT_storage_s3_accessKeyId }} + FORKLIFT_storage_s3_secretAccessKey: ${{ secrets.FORKLIFT_storage_s3_secretAccessKey }} + FORKLIFT_storage_s3_endpointUrl: ${{ secrets.FORKLIFT_storage_s3_endpointUrl }} + FORKLIFT_metrics_pushEndpoint: ${{ secrets.FORKLIFT_metrics_pushEndpoint }} + +jobs: + + changes: + permissions: + pull-requests: read + uses: ./.github/workflows/check-changed-files.yml + + set-image: + # GitHub Actions allows using 'env' in a container context. + # However, env variables don't work for forks: https://github.com/orgs/community/discussions/44322 + # This workaround sets the container image for each job using 'set-image' job output. + runs-on: ubuntu-latest + outputs: + IMAGE: ${{ steps.set_image.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - id: set_image + run: cat .github/env >> $GITHUB_OUTPUT + + quick-benchmarks: + needs: [set-image, changes] + if: ${{ needs.changes.outputs.rust }} + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + container: + image: ${{ needs.set-image.outputs.IMAGE }} + env: + RUSTFLAGS: "-C debug-assertions -D warnings" + RUST_BACKTRACE: "full" + WASM_BUILD_NO_COLOR: 1 + WASM_BUILD_RUSTFLAGS: "-C debug-assertions -D warnings" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: time forklift cargo run --locked --release -p staging-node-cli --bin substrate-node --features runtime-benchmarks -- benchmark pallet --chain dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1 --quiet + + # cf https://github.com/paritytech/polkadot-sdk/issues/1652 + test-syscalls: + needs: [set-image, changes] + if: ${{ needs.changes.outputs.rust }} + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + container: + image: ${{ needs.set-image.outputs.IMAGE }} + continue-on-error: true # this rarely triggers in practice + env: + SKIP_WASM_BUILD: 1 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: | + forklift cargo build --locked --profile production --target x86_64-unknown-linux-musl --bin polkadot-execute-worker --bin polkadot-prepare-worker + cd polkadot/scripts/list-syscalls + ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-execute-worker --only-used-syscalls | diff -u execute-worker-syscalls - + ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-prepare-worker --only-used-syscalls | diff -u prepare-worker-syscalls - + # todo: + # after_script: + # - if [[ "$CI_JOB_STATUS" == "failed" ]]; then + # printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n"; + # fi + + cargo-check-all-benches: + needs: [set-image, changes] + if: ${{ needs.changes.outputs.rust }} + runs-on: arc-runners-polkadot-sdk-beefy + timeout-minutes: 30 + container: + image: ${{ needs.set-image.outputs.IMAGE }} + env: + SKIP_WASM_BUILD: 1 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: script + run: time forklift cargo check --all --benches diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5e57dd86f14166e695f1c64b6b5aee56529a4781..73a8c52c448f72d12e510d65b2f7ff38469856f0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -120,7 +120,7 @@ default: .forklift-cache: before_script: - mkdir ~/.forklift - - cp $FL_FORKLIFT_CONFIG ~/.forklift/config.toml + - cp .forklift/config.toml ~/.forklift/config.toml - > if [ "$FORKLIFT_BYPASS" != "true" ]; then echo "FORKLIFT_BYPASS not set"; diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml index 6fb8a97fe95821886c416d97224fb21fd0f2897b..5c1a667a313ce391f0c790881d87f48ebd79d073 100644 --- a/.gitlab/pipeline/check.yml +++ b/.gitlab/pipeline/check.yml @@ -146,96 +146,6 @@ check-runtime-migration-rococo: URI: "wss://rococo-try-runtime-node.parity-chains.parity.io:443" SUBCOMMAND_EXTRA_ARGS: "--no-weight-warnings" -# Check runtime migrations for Parity managed asset hub chains -check-runtime-migration-asset-hub-westend: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "asset-hub-westend" - PACKAGE: "asset-hub-westend-runtime" - WASM: "asset_hub_westend_runtime.compact.compressed.wasm" - URI: "wss://westend-asset-hub-rpc.polkadot.io:443" - -check-runtime-migration-asset-hub-rococo: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "asset-hub-rococo" - PACKAGE: "asset-hub-rococo-runtime" - WASM: "asset_hub_rococo_runtime.compact.compressed.wasm" - URI: "wss://rococo-asset-hub-rpc.polkadot.io:443" - -# Check runtime migrations for Parity managed bridge hub chains -check-runtime-migration-bridge-hub-westend: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "bridge-hub-westend" - PACKAGE: "bridge-hub-westend-runtime" - WASM: "bridge_hub_westend_runtime.compact.compressed.wasm" - URI: "wss://westend-bridge-hub-rpc.polkadot.io:443" - -check-runtime-migration-bridge-hub-rococo: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "bridge-hub-rococo" - PACKAGE: "bridge-hub-rococo-runtime" - WASM: "bridge_hub_rococo_runtime.compact.compressed.wasm" - URI: "wss://rococo-bridge-hub-rpc.polkadot.io:443" - -# Check runtime migrations for Parity managed contract chains -check-runtime-migration-contracts-rococo: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "contracts-rococo" - PACKAGE: "contracts-rococo-runtime" - WASM: "contracts_rococo_runtime.compact.compressed.wasm" - URI: "wss://rococo-contracts-rpc.polkadot.io:443" - -# Check runtime migrations for Parity managed collectives chains -check-runtime-migration-collectives-westend: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "collectives-westend" - PACKAGE: "collectives-westend-runtime" - WASM: "collectives_westend_runtime.compact.compressed.wasm" - URI: "wss://westend-collectives-rpc.polkadot.io:443" - COMMAND_EXTRA_ARGS: "--disable-spec-name-check" - -# Check runtime migrations for Parity managed coretime chain -check-runtime-migration-coretime-rococo: - stage: check - extends: - - .docker-env - - .test-pr-refs - - .check-runtime-migration - variables: - NETWORK: "coretime-rococo" - PACKAGE: "coretime-rococo-runtime" - WASM: "coretime_rococo_runtime.compact.compressed.wasm" - URI: "wss://rococo-coretime-rpc.polkadot.io:443" - find-fail-ci-phrase: stage: check variables: diff --git a/.gitlab/pipeline/publish.yml b/.gitlab/pipeline/publish.yml index 68712610ad2361601af3763485d1ab3e6c158682..44cd1933a9cfa0b3cbff384ff4184a36bf864021 100644 --- a/.gitlab/pipeline/publish.yml +++ b/.gitlab/pipeline/publish.yml @@ -76,6 +76,8 @@ publish-subsystem-benchmarks: artifacts: true - job: subsystem-benchmark-approval-voting artifacts: true + - job: subsystem-benchmark-statement-distribution + artifacts: true - job: publish-rustdoc artifacts: false script: @@ -119,6 +121,8 @@ trigger_workflow: artifacts: true - job: subsystem-benchmark-approval-voting artifacts: true + - job: subsystem-benchmark-statement-distribution + artifacts: true script: - echo "Triggering workflow" - > @@ -129,7 +133,7 @@ trigger_workflow: curl -q -X POST \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token $GITHUB_TOKEN" \ - https://api.github.com/repos/paritytech/${CI_PROJECT_NAME}/actions/workflows/subsystem-benchmarks.yml/dispatches \ + https://api.github.com/repos/paritytech/${CI_PROJECT_NAME}/actions/workflows/publish-subsystem-benchmarks.yml/dispatches \ -d "{\"ref\":\"refs/heads/master\",\"inputs\":{\"benchmark-data-dir-path\":\"$benchmark_dir\",\"output-file-path\":\"$benchmark_name\"}}"; sleep 300; done diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index c17a3ce35eaf54896e7d96e6cfefbb7edf53ced7..d171a8a19426c959f776aa0780f4373c4b23b4e6 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -5,6 +5,113 @@ - job: job-starter artifacts: false +# +# +# +.codecov-check: + script: + - > + if command -v codecovcli -h >/dev/null 2>&1; then + codecovcli --version; + else + echo "downloading codecovcli"; + curl -s -o codecovcli https://cli.codecov.io/latest/linux/codecov; + chmod +x codecovcli; + mv codecovcli /usr/local/bin/codecovcli; + fi + # + - codecovcli --version + +# +# +# +codecov-start: + stage: test + when: manual + allow_failure: false + extends: + - .kubernetes-env + - .common-refs + - .pipeline-stopper-artifacts + - .run-immediately + script: + - !reference [.codecov-check, script] + - > + if [ "$CI_COMMIT_REF_NAME" != "master" ]; then + codecovcli -v create-commit -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --pr ${CI_COMMIT_REF_NAME} --git-service github; + codecovcli -v create-report -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --pr ${CI_COMMIT_REF_NAME} --git-service github; + else + codecovcli -v create-commit -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --git-service github; + codecovcli -v create-report -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --git-service github; + fi + +# +# +# +codecov-finish: + stage: test + extends: + - .kubernetes-env + - .common-refs + - .pipeline-stopper-artifacts + needs: + - test-linux-stable-codecov + script: + - !reference [.codecov-check, script] + - codecovcli -v create-report-results -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github + - codecovcli -v get-report-results -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github + - codecovcli -v send-notifications -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --git-service github + +# +# +# +test-linux-stable-codecov: + stage: test + needs: + - codecov-start + extends: + - .docker-env + - .common-refs + - .pipeline-stopper-artifacts + variables: + CI_IMAGE: europe-docker.pkg.dev/parity-build/ci-images/ci-unified:bullseye-1.77.0 + RUST_TOOLCHAIN: stable + RUSTFLAGS: "-Cdebug-assertions=y -Cinstrument-coverage" + LLVM_PROFILE_FILE: "target/coverage/cargo-test-${CI_NODE_INDEX}-%p-%m.profraw" + CARGO_INCREMENTAL: 0 + FORKLIFT_BYPASS: "true" + parallel: 2 + script: + # tools + - !reference [.codecov-check, script] + - rustup component add llvm-tools-preview + - mkdir -p target/coverage/result/ + # Place real test call here + - > + time cargo nextest run -p polkadot \ + --locked \ + --release \ + --no-fail-fast \ + --partition count:${CI_NODE_INDEX}/${CI_NODE_TOTAL} + # generate and upload reports + - > + grcov \ + target/coverage/ \ + --binary-path ./target/release/ \ + -s . \ + -t lcov \ + --branch \ + -o target/coverage/result/report-${CI_NODE_INDEX}.lcov + - ls -l target/coverage/result/ + - > + if [ "$CI_COMMIT_REF_NAME" != "master" ]; then + codecovcli -v do-upload -f target/coverage/result/report-${CI_NODE_INDEX}.lcov --disable-search -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --pr ${CI_COMMIT_REF_NAME} --git-service github; + else + codecovcli -v do-upload -f target/coverage/result/report-${CI_NODE_INDEX}.lcov --disable-search -t ${CODECOV_TOKEN} -r paritytech/polkadot-sdk --commit-sha ${CI_COMMIT_SHA} --fail-on-error --git-service github; + fi + + # + test-linux-stable: stage: test extends: @@ -21,8 +128,6 @@ test-linux-stable: script: # Build all but only execute 'runtime' tests. - echo "Node index - ${CI_NODE_INDEX}. Total amount - ${CI_NODE_TOTAL}" - # add experimental to features after https://github.com/paritytech/substrate/pull/14502 is merged - # "upgrade_version_checks_should_work" is currently failing - > time cargo nextest run \ --workspace \ @@ -147,18 +252,6 @@ test-rustdoc: script: - time cargo doc --workspace --all-features --no-deps -cargo-check-all-benches: - stage: test - extends: - - .docker-env - - .common-refs - # DAG - needs: - - job: cargo-hfuzz - artifacts: false - script: - - time cargo check --all --benches - test-node-metrics: stage: test extends: @@ -398,6 +491,17 @@ check-tracing: - time cargo test --locked --manifest-path ./substrate/primitives/tracing/Cargo.toml --no-default-features - time cargo test --locked --manifest-path ./substrate/primitives/tracing/Cargo.toml --no-default-features --features=with-tracing +# Check that `westend-runtime` compiles with the `metadata-hash` feature enabled. +check-metadata-hash: + stage: test + extends: + - .docker-env + - .common-refs + - .run-immediately + - .pipeline-stopper-artifacts + script: + - time cargo build --locked -p westend-runtime --features metadata-hash + # more information about this job can be found here: # https://github.com/paritytech/substrate/pull/3778 test-full-crypto-feature: @@ -491,26 +595,6 @@ cargo-hfuzz: - for target in $(cargo read-manifest | jq -r '.targets | .[] | .name'); do cargo hfuzz run "$target" || { printf "fuzzing failure for %s\n" "$target"; exit 1; }; done -# cf https://github.com/paritytech/polkadot-sdk/issues/1652 -test-syscalls: - stage: test - extends: - - .docker-env - - .common-refs - - .run-immediately - variables: - SKIP_WASM_BUILD: 1 - script: - - cargo build --locked --profile production --target x86_64-unknown-linux-musl --bin polkadot-execute-worker --bin polkadot-prepare-worker - - cd polkadot/scripts/list-syscalls - - ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-execute-worker --only-used-syscalls | diff -u execute-worker-syscalls - - - ./list-syscalls.rb ../../../target/x86_64-unknown-linux-musl/production/polkadot-prepare-worker --only-used-syscalls | diff -u prepare-worker-syscalls - - after_script: - - if [[ "$CI_JOB_STATUS" == "failed" ]]; then - printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n"; - fi - allow_failure: false # this rarely triggers in practice - .subsystem-benchmark-template: stage: test artifacts: @@ -546,3 +630,10 @@ subsystem-benchmark-approval-voting: script: - cargo bench -p polkadot-node-core-approval-voting --bench approval-voting-regression-bench --features subsystem-benchmarks allow_failure: true + +subsystem-benchmark-statement-distribution: + extends: + - .subsystem-benchmark-template + script: + - cargo bench -p polkadot-statement-distribution --bench statement-distribution-regression-bench --features subsystem-benchmarks + allow_failure: true diff --git a/.gitlab/pipeline/zombienet.yml b/.gitlab/pipeline/zombienet.yml index 52948e1eb719d9f8669523d9762f5662fd1b6e96..7897e55e291bd3cae1f3df42d1fcf5c811ff52f2 100644 --- a/.gitlab/pipeline/zombienet.yml +++ b/.gitlab/pipeline/zombienet.yml @@ -1,8 +1,9 @@ .zombienet-refs: extends: .build-refs variables: - ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.99" + ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.105" PUSHGATEWAY_URL: "http://zombienet-prometheus-pushgateway.managed-monitoring:9091/metrics/job/zombie-metrics" + DEBUG: "zombie,zombie::network-node,zombie::kube::client::logs" include: # substrate tests diff --git a/.gitlab/pipeline/zombienet/cumulus.yml b/.gitlab/pipeline/zombienet/cumulus.yml index 746c77ee7cf350aaabfe66f71ae219d0bdd35e78..1f44ffc88fabce82a4b4563e02f974431f3d4e0b 100644 --- a/.gitlab/pipeline/zombienet/cumulus.yml +++ b/.gitlab/pipeline/zombienet/cumulus.yml @@ -15,7 +15,6 @@ - echo "${COL_IMAGE}" - echo "${GH_DIR}" - echo "${LOCAL_DIR}" - - export DEBUG=zombie - export RELAY_IMAGE=${POLKADOT_IMAGE} - export COL_IMAGE=${COL_IMAGE} diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 6b72075c513b73c075d1dc10c90d0461bf0e1a82..b158cbe0b5aa3a50d490129dab87c9e7d6769b35 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -10,7 +10,6 @@ - if [[ $CI_COMMIT_REF_NAME == *"gh-readonly-queue"* ]]; then export DOCKER_IMAGES_VERSION="${CI_COMMIT_SHORT_SHA}"; fi - export PIPELINE_IMAGE_TAG=${DOCKER_IMAGES_VERSION} - export BUILD_RELEASE_VERSION="$(cat ./artifacts/BUILD_RELEASE_VERSION)" # from build-linux-stable job - - export DEBUG=zombie,zombie::network-node - export ZOMBIENET_INTEGRATION_TEST_IMAGE="${POLKADOT_IMAGE}":${PIPELINE_IMAGE_TAG} - export COL_IMAGE="${COLANDER_IMAGE}":${PIPELINE_IMAGE_TAG} - export CUMULUS_IMAGE="docker.io/paritypr/polkadot-parachain-debug:${DOCKER_IMAGES_VERSION}" @@ -176,6 +175,30 @@ zombienet-polkadot-elastic-scaling-0002-elastic-scaling-doesnt-break-parachains: --local-dir="${LOCAL_DIR}/elastic_scaling" --test="0002-elastic-scaling-doesnt-break-parachains.zndsl" +zombienet-polkadot-functional-0012-spam-statement-distribution-requests: + extends: + - .zombienet-polkadot-common + script: + - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh + --local-dir="${LOCAL_DIR}/functional" + --test="0012-spam-statement-distribution-requests.zndsl" + +zombienet-polkadot-functional-0013-systematic-chunk-recovery: + extends: + - .zombienet-polkadot-common + script: + - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh + --local-dir="${LOCAL_DIR}/functional" + --test="0013-systematic-chunk-recovery.zndsl" + +zombienet-polkadot-functional-0014-chunk-fetching-network-compatibility: + extends: + - .zombienet-polkadot-common + script: + - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh + --local-dir="${LOCAL_DIR}/functional" + --test="0014-chunk-fetching-network-compatibility.zndsl" + zombienet-polkadot-smoke-0001-parachains-smoke-test: extends: - .zombienet-polkadot-common diff --git a/.gitlab/pipeline/zombienet/substrate.yml b/.gitlab/pipeline/zombienet/substrate.yml index 8a627c454f9f3853f04694827e1484571f5444a9..2013ffd571cf388ba154f3965c166765f40baaf6 100644 --- a/.gitlab/pipeline/zombienet/substrate.yml +++ b/.gitlab/pipeline/zombienet/substrate.yml @@ -13,7 +13,6 @@ - echo "${ZOMBIENET_IMAGE}" - echo "${GH_DIR}" - echo "${LOCAL_DIR}" - - export DEBUG=zombie,zombie::network-node - export ZOMBIENET_INTEGRATION_TEST_IMAGE="${SUBSTRATE_IMAGE}":${SUBSTRATE_IMAGE_TAG} - echo "${ZOMBIENET_INTEGRATION_TEST_IMAGE}" stage: zombienet diff --git a/Cargo.lock b/Cargo.lock index 7ccbc5ff62c5804c9363aed80b457a384fb6d827..73f07469be05f787f44f4dfbca3998bfe3b23e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,9 +157,9 @@ dependencies = [ "dunce", "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", "syn-solidity", "tiny-keccak", ] @@ -275,20 +275,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "aquamarine" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da02abba9f9063d786eab1509833ebb2fac0f966862ca59439c76b9c566760" -dependencies = [ - "include_dir", - "itertools 0.10.5", - "proc-macro-error", - "proc-macro2 1.0.75", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "aquamarine" version = "0.5.0" @@ -298,9 +284,9 @@ dependencies = [ "include_dir", "itertools 0.10.5", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -529,7 +515,7 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -631,7 +617,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -672,15 +658,9 @@ dependencies = [ [[package]] name = "array-bytes" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" - -[[package]] -name = "array-bytes" -version = "6.1.0" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" +checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" [[package]] name = "arrayref" @@ -725,7 +705,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", "synstructure", @@ -737,7 +717,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -828,6 +808,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -850,7 +831,6 @@ dependencies = [ "pallet-nfts-runtime-api", "pallet-proxy", "pallet-session", - "pallet-state-trie-migration", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -887,6 +867,7 @@ dependencies = [ "staging-xcm-executor", "substrate-wasm-builder", "testnet-parachains-constants", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -914,22 +895,29 @@ dependencies = [ "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", "emulated-integration-tests-common", + "frame-metadata-hash-extension", "frame-support", + "frame-system", "pallet-asset-conversion", + "pallet-asset-tx-payment", "pallet-assets", "pallet-balances", "pallet-message-queue", + "pallet-transaction-payment", "pallet-treasury", "pallet-xcm", "parachains-common", "parity-scale-codec", "penpal-runtime", "polkadot-runtime-common", + "sp-core", + "sp-keyring", "sp-runtime", "staging-xcm", "staging-xcm-executor", "westend-runtime", "westend-system-emulated-network", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -953,6 +941,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -975,6 +964,7 @@ dependencies = [ "pallet-nfts-runtime-api", "pallet-proxy", "pallet-session", + "pallet-state-trie-migration", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -1009,6 +999,7 @@ dependencies = [ "substrate-wasm-builder", "testnet-parachains-constants", "westend-runtime-constants", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -1080,7 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener 2.5.3", + "event-listener", "futures-core", ] @@ -1090,7 +1081,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" dependencies = [ - "async-lock 2.8.0", + "async-lock", "async-task", "concurrent-queue", "fastrand 1.9.0", @@ -1104,7 +1095,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock 2.8.0", + "async-lock", "autocfg", "blocking", "futures-lite", @@ -1119,7 +1110,7 @@ dependencies = [ "async-channel", "async-executor", "async-io", - "async-lock 2.8.0", + "async-lock", "blocking", "futures-lite", "once_cell", @@ -1131,7 +1122,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock 2.8.0", + "async-lock", "autocfg", "cfg-if", "concurrent-queue", @@ -1151,18 +1142,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" -dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy", - "pin-project-lite 0.2.12", + "event-listener", ] [[package]] @@ -1184,11 +1164,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" dependencies = [ "async-io", - "async-lock 2.8.0", + "async-lock", "autocfg", "blocking", "cfg-if", - "event-listener 2.5.3", + "event-listener", "futures-lite", "rustix 0.37.23", "signal-hook", @@ -1205,7 +1185,7 @@ dependencies = [ "async-channel", "async-global-executor", "async-io", - "async-lock 2.8.0", + "async-lock", "crossbeam-utils", "futures-channel", "futures-core", @@ -1239,9 +1219,9 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -1256,9 +1236,9 @@ version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -1304,7 +1284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -1358,7 +1338,7 @@ dependencies = [ "rand_chacha 0.3.1", "rand_core 0.6.4", "ring 0.1.0", - "sha2 0.10.7", + "sha2 0.10.8", "sp-ark-bls12-381", "sp-ark-ed-on-bls12-381-bandersnatch", "zeroize", @@ -1416,7 +1396,7 @@ dependencies = [ name = "binary-merkle-tree" version = "13.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "env_logger 0.11.3", "hash-db", "log", @@ -1446,12 +1426,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease 0.2.12", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "regex", "rustc-hash", "shlex", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -1618,7 +1598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" dependencies = [ "async-channel", - "async-lock 2.8.0", + "async-lock", "async-task", "atomic-waker", "fastrand 1.9.0", @@ -1919,7 +1899,7 @@ dependencies = [ "bp-parachains", "bp-polkadot-core", "bp-runtime", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "finality-grandpa", "parity-scale-codec", "sp-application-crypto", @@ -2386,9 +2366,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bzip2-sys" @@ -2717,7 +2697,7 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -2729,9 +2709,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ "heck 0.5.0", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -2854,6 +2834,7 @@ dependencies = [ "pallet-salary", "pallet-scheduler", "pallet-session", + "pallet-state-trie-migration", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -2918,7 +2899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d51beaa537d73d2d1ff34ee70bc095f170420ab2ec5d687ecd3ec2b0d092514b" dependencies = [ "nom", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -3463,34 +3444,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap 3.2.25", - "criterion-plot", - "futures", - "itertools 0.10.5", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "tokio", - "walkdir", -] - [[package]] name = "criterion" version = "0.5.1" @@ -3988,6 +3941,7 @@ dependencies = [ "sp-trie", "sp-version", "staging-xcm", + "staging-xcm-builder", "trie-db", "trie-standardmap", ] @@ -3996,10 +3950,10 @@ dependencies = [ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.6.0" dependencies = [ - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4243,7 +4197,7 @@ dependencies = [ name = "cumulus-relay-chain-minimal-node" version = "0.7.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", @@ -4415,7 +4369,7 @@ version = "0.1.0" dependencies = [ "async-trait", "clap 4.5.3", - "criterion 0.5.1", + "criterion", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", @@ -4556,9 +4510,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4595,10 +4549,10 @@ dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "scratch", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4613,9 +4567,9 @@ version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50c49547d73ba8dcfd4ad7325d64c6d5391ff4224d498fc39a6f3f49825a530d" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4702,7 +4656,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -4713,7 +4667,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -4724,9 +4678,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4736,7 +4690,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "rustc_version 0.4.0", "syn 1.0.109", @@ -4832,9 +4786,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -4892,10 +4846,10 @@ dependencies = [ "common-path", "derive-syn-parse 0.2.0", "once_cell", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "regex", - "syn 2.0.53", + "syn 2.0.61", "termcolor", "toml 0.8.8", "walkdir", @@ -4941,7 +4895,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -5002,33 +4956,19 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek 4.1.2", "ed25519 2.2.2", "rand_core 0.6.4", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "subtle 2.5.0", "zeroize", ] -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek 3.2.0", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "ed25519-zebra" version = "4.0.3" @@ -5040,7 +4980,7 @@ dependencies = [ "hashbrown 0.14.3", "hex", "rand_core 0.6.4", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -5124,7 +5064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -5136,9 +5076,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -5156,9 +5096,9 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -5167,9 +5107,9 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -5192,6 +5132,19 @@ dependencies = [ "regex", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.10.1" @@ -5332,27 +5285,6 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite 0.2.12", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite 0.2.12", -] - [[package]] name = "exit-future" version = "0.2.0" @@ -5362,18 +5294,6 @@ dependencies = [ "futures", ] -[[package]] -name = "expander" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a718c0675c555c5f976fff4ea9e2c150fa06cefa201cadef87cfbf9324075881" -dependencies = [ - "blake3", - "fs-err", - "proc-macro2 1.0.75", - "quote 1.0.35", -] - [[package]] name = "expander" version = "2.0.0" @@ -5382,9 +5302,9 @@ checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" dependencies = [ "blake2 0.10.6", "fs-err", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -5420,9 +5340,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -5437,9 +5357,9 @@ dependencies = [ [[package]] name = "fatality" -version = "0.0.6" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad875162843b0d046276327afe0136e9ed3a23d5a754210fb6f1f33610d39ab" +checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019" dependencies = [ "fatality-proc-macro", "thiserror", @@ -5447,17 +5367,16 @@ dependencies = [ [[package]] name = "fatality-proc-macro" -version = "0.0.6" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" +checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" dependencies = [ - "expander 0.0.4", - "indexmap 1.9.3", - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "expander", + "indexmap 2.2.3", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 1.0.109", - "thiserror", + "syn 2.0.61", ] [[package]] @@ -5656,6 +5575,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forwarded-header-value" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" +dependencies = [ + "nonempty", + "thiserror", +] + [[package]] name = "fraction" version = "0.13.1" @@ -5676,7 +5605,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" name = "frame-benchmarking" version = "28.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "frame-support", "frame-support-procedural", "frame-system", @@ -5704,7 +5633,7 @@ name = "frame-benchmarking-cli" version = "32.0.0" dependencies = [ "Inflector", - "array-bytes 6.1.0", + "array-bytes", "chrono", "clap 4.5.3", "comfy-table", @@ -5713,7 +5642,7 @@ dependencies = [ "frame-system", "gethostname", "handlebars", - "itertools 0.10.5", + "itertools 0.11.0", "lazy_static", "linked-hash-map", "log", @@ -5769,12 +5698,12 @@ dependencies = [ "frame-election-provider-support", "frame-support", "parity-scale-codec", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", "scale-info", "sp-arithmetic", - "syn 2.0.53", + "syn 2.0.61", "trybuild", ] @@ -5817,8 +5746,8 @@ dependencies = [ name = "frame-executive" version = "28.0.0" dependencies = [ - "aquamarine 0.3.3", - "array-bytes 6.1.0", + "aquamarine", + "array-bytes", "frame-support", "frame-system", "frame-try-runtime", @@ -5848,6 +5777,27 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-metadata-hash-extension" +version = "0.1.0" +dependencies = [ + "array-bytes", + "docify", + "frame-metadata", + "frame-support", + "frame-system", + "log", + "merkleized-metadata", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", + "sp-tracing 16.0.0", + "sp-transaction-pool", + "substrate-test-runtime-client", + "substrate-wasm-builder", +] + [[package]] name = "frame-omni-bencher" version = "0.1.0" @@ -5888,8 +5838,8 @@ dependencies = [ name = "frame-support" version = "28.0.0" dependencies = [ - "aquamarine 0.5.0", - "array-bytes 6.1.0", + "aquamarine", + "array-bytes", "assert_matches", "bitflags 1.3.2", "docify", @@ -5936,16 +5886,16 @@ dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse 0.2.0", - "expander 2.0.0", + "expander", "frame-support-procedural-tools", - "itertools 0.10.5", + "itertools 0.11.0", "macro_magic", "proc-macro-warning", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "regex", "sp-crypto-hashing", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -5953,19 +5903,19 @@ name = "frame-support-procedural-tools" version = "10.0.0" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "frame-support-procedural-tools-derive" version = "11.0.0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -6035,7 +5985,7 @@ name = "frame-system" version = "28.0.0" dependencies = [ "cfg-if", - "criterion 0.4.0", + "criterion", "docify", "frame-support", "log", @@ -6196,9 +6146,9 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -6226,9 +6176,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" @@ -6867,7 +6817,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -6887,7 +6837,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", ] @@ -7037,7 +6987,7 @@ dependencies = [ "curl", "curl-sys", "encoding_rs", - "event-listener 2.5.3", + "event-listener", "futures-lite", "http", "log", @@ -7113,9 +7063,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3ae45a64cfc0882934f963be9431b2a165d667f53140358181f262aca0702" +checksum = "cfdb12a2381ea5b2e68c3469ec604a007b367778cdb14d09612c8069ebd616ad" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -7129,9 +7079,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455fc882e56f58228df2aee36b88a1340eafd707c76af2fa68cf94b37d461131" +checksum = "4978087a58c3ab02efc5b07c5e5e2803024536106fd5506f558db172c889b3aa" dependencies = [ "futures-util", "http", @@ -7150,12 +7100,11 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75568f4f9696e3a47426e1985b548e1a9fcb13372a5e320372acaf04aca30d1" +checksum = "b4b257e1ec385e07b0255dde0b933f948b5c8b8c28d42afda9587c3a967b896d" dependencies = [ "anyhow", - "async-lock 3.3.0", "async-trait", "beef", "futures-timer", @@ -7176,9 +7125,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7a95e346f55df84fb167b7e06470e196e7d5b9488a21d69c5d9732043ba7ba" +checksum = "1ccf93fc4a0bfe05d851d37d7c32b7f370fe94336b52a2f0efc5f1981895c2e5" dependencies = [ "async-trait", "hyper", @@ -7196,22 +7145,22 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca066e73dd70294aebc5c2675d8ffae43be944af027c857ce0d4c51785f014" +checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0" dependencies = [ "heck 0.4.1", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "jsonrpsee-server" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e29c1bd1f9bba83c864977c73404e505f74f730fa0db89dd490ec174e36d7f0" +checksum = "12d8b6a9674422a8572e0b0abb12feeb3f2aeda86528c80d0350c2bd0923ab41" dependencies = [ "futures-util", "http", @@ -7233,9 +7182,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467fd35feeee179f71ab294516bdf3a81139e7aeebdd860e46897c12e1a3368" +checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" dependencies = [ "anyhow", "beef", @@ -7246,9 +7195,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.22.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca71e74983f624c0cb67828e480a981586074da8ad3a2f214c6a3f884edab9" +checksum = "58b9db2dfd5bb1194b0ce921504df9ceae210a345bc2f6c5a61432089bbab070" dependencies = [ "http", "jsonrpsee-client-transport", @@ -7268,7 +7217,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -7301,123 +7250,15 @@ checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" name = "kitchensink-runtime" version = "3.0.0-dev" dependencies = [ - "frame-benchmarking", - "frame-benchmarking-pallet-pov", - "frame-election-provider-support", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", "log", "node-primitives", - "pallet-alliance", - "pallet-asset-conversion", - "pallet-asset-conversion-ops", - "pallet-asset-conversion-tx-payment", - "pallet-asset-rate", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-authority-discovery", - "pallet-authorship", - "pallet-babe", - "pallet-bags-list", - "pallet-balances", - "pallet-beefy", - "pallet-beefy-mmr", - "pallet-bounties", - "pallet-broker", - "pallet-child-bounties", - "pallet-collective", - "pallet-contracts", - "pallet-conviction-voting", - "pallet-core-fellowship", - "pallet-democracy", - "pallet-election-provider-multi-phase", - "pallet-election-provider-support-benchmarking", - "pallet-elections-phragmen", "pallet-example-mbm", "pallet-example-tasks", - "pallet-fast-unstake", - "pallet-glutton", - "pallet-grandpa", - "pallet-identity", - "pallet-im-online", - "pallet-indices", - "pallet-insecure-randomness-collective-flip", - "pallet-lottery", - "pallet-membership", - "pallet-message-queue", - "pallet-migrations", - "pallet-mixnet", - "pallet-mmr", - "pallet-multisig", - "pallet-nft-fractionalization", - "pallet-nfts", - "pallet-nfts-runtime-api", - "pallet-nis", - "pallet-nomination-pools", - "pallet-nomination-pools-benchmarking", - "pallet-nomination-pools-runtime-api", - "pallet-offences", - "pallet-offences-benchmarking", - "pallet-parameters", - "pallet-preimage", - "pallet-proxy", - "pallet-ranked-collective", - "pallet-recovery", - "pallet-referenda", - "pallet-remark", - "pallet-root-testing", - "pallet-safe-mode", - "pallet-salary", - "pallet-scheduler", - "pallet-session", - "pallet-session-benchmarking", - "pallet-skip-feeless-payment", - "pallet-society", - "pallet-staking", - "pallet-staking-reward-curve", - "pallet-staking-runtime-api", - "pallet-state-trie-migration", - "pallet-statement", - "pallet-sudo", - "pallet-timestamp", - "pallet-tips", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-transaction-storage", - "pallet-treasury", - "pallet-tx-pause", - "pallet-uniques", - "pallet-utility", - "pallet-vesting", - "pallet-whitelist", "parity-scale-codec", + "polkadot-sdk", "primitive-types", "scale-info", "serde_json", - "sp-api", - "sp-authority-discovery", - "sp-block-builder", - "sp-consensus-babe", - "sp-consensus-beefy", - "sp-consensus-grandpa", - "sp-core", - "sp-genesis-builder", - "sp-inherents", - "sp-io", - "sp-mixnet", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-staking", - "sp-statement-store", - "sp-std 14.0.0", - "sp-storage 19.0.0", - "sp-transaction-pool", - "sp-version", "static_assertions", "substrate-wasm-builder", ] @@ -7693,13 +7534,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "bs58 0.4.0", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "log", "multiaddr", "multihash 0.17.0", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "zeroize", ] @@ -7724,7 +7565,7 @@ dependencies = [ "log", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "thiserror", "uint", @@ -7782,7 +7623,7 @@ dependencies = [ "once_cell", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "snow", "static_assertions", "thiserror", @@ -8116,8 +7957,9 @@ dependencies = [ [[package]] name = "litep2p" -version = "0.3.0" -source = "git+https://github.com/paritytech/litep2p?branch=master#b142c9eb611fb2fe78d2830266a3675b37299ceb" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f02542ae3a94b4c4ffa37dc56388c923e286afa3bf65452e3984b50b2a2f316" dependencies = [ "async-trait", "bs58 0.4.0", @@ -8129,7 +7971,7 @@ dependencies = [ "hex-literal", "indexmap 2.2.3", "libc", - "mockall", + "mockall 0.12.1", "multiaddr", "multihash 0.17.0", "network-interface", @@ -8137,14 +7979,14 @@ dependencies = [ "parking_lot 0.12.1", "pin-project", "prost 0.11.9", - "prost-build", + "prost-build 0.11.9", "quinn", "rand 0.8.5", "rcgen", "ring 0.16.20", "rustls 0.20.8", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "simple-dns", "smallvec", "snow", @@ -8154,7 +7996,7 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "tokio-util", "tracing", "trust-dns-resolver 0.23.2", @@ -8268,7 +8110,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -8280,9 +8122,9 @@ dependencies = [ "const-random", "derive-syn-parse 0.1.5", "macro_magic_core_macros", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -8291,9 +8133,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -8304,7 +8146,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -8386,15 +8228,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.8.0" @@ -8422,6 +8255,20 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merkleized-metadata" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +dependencies = [ + "array-bytes", + "blake3", + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", +] + [[package]] name = "merlin" version = "3.0.0" @@ -8485,7 +8332,7 @@ dependencies = [ "pallet-minimal-template", "polkadot-sdk-docs", "polkadot-sdk-frame", - "simple-mermaid", + "simple-mermaid 0.1.1", ] [[package]] @@ -8634,11 +8481,26 @@ dependencies = [ "downcast", "fragile", "lazy_static", - "mockall_derive", + "mockall_derive 0.11.4", "predicates 2.1.5", "predicates-tree", ] +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive 0.12.1", + "predicates 3.0.3", + "predicates-tree", +] + [[package]] name = "mockall_derive" version = "0.11.4" @@ -8646,11 +8508,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" dependencies = [ "cfg-if", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2 1.0.82", + "quote 1.0.35", + "syn 2.0.61", +] + [[package]] name = "multiaddr" version = "0.17.1" @@ -8693,7 +8567,7 @@ dependencies = [ "core2", "digest 0.10.7", "multihash-derive 0.8.0", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "unsigned-varint", ] @@ -8710,7 +8584,7 @@ dependencies = [ "core2", "digest 0.10.7", "multihash-derive 0.8.0", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "unsigned-varint", ] @@ -8740,7 +8614,7 @@ dependencies = [ "ripemd", "serde", "sha1", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "strobe-rs", ] @@ -8753,7 +8627,7 @@ checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", "synstructure", @@ -8778,7 +8652,7 @@ checksum = "d38685e08adb338659871ecfc6ee47ba9b22dcc8abcf6975d379cc49145c3040" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", "synstructure", @@ -8826,7 +8700,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -8945,19 +8819,18 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.7.1", - "pin-utils", "static_assertions", ] [[package]] name = "nix" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.4.0", "cfg-if", + "cfg_aliases", "libc", ] @@ -8977,7 +8850,7 @@ checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" name = "node-bench" version = "0.9.0-dev" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "clap 4.5.3", "derive_more", "fs_extra", @@ -9068,7 +8941,7 @@ dependencies = [ "flate2", "fs_extra", "glob", - "itertools 0.10.5", + "itertools 0.11.0", "tar", "tempfile", "toml_edit 0.19.15", @@ -9078,6 +8951,7 @@ dependencies = [ name = "node-testing" version = "3.0.0-dev" dependencies = [ + "frame-metadata-hash-extension", "frame-system", "fs_extra", "futures", @@ -9134,6 +9008,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + [[package]] name = "nonzero_ext" version = "0.3.0" @@ -9352,9 +9232,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -9393,9 +9273,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchestra" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2356622ffdfe72362a45a1e5e87bb113b8327e596e39b91f11f0ef4395c8da79" +checksum = "92829eef0328a3d1cd22a02c0e51deb92a5362df3e7d21a4e9bdc38934694e66" dependencies = [ "async-trait", "dyn-clonable", @@ -9410,16 +9290,16 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eedb646674596266dc9bb2b5c7eea7c36b32ecc7777eba0d510196972d72c4fd" +checksum = "1344346d5af32c95bbddea91b18a88cc83eac394192d20ef2fc4c40a74332355" dependencies = [ - "expander 2.0.0", + "expander", "indexmap 2.2.3", "itertools 0.11.0", "petgraph", - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -9455,7 +9335,7 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" name = "pallet-alliance" version = "27.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "frame-benchmarking", "frame-support", "frame-system", @@ -9685,7 +9565,7 @@ dependencies = [ name = "pallet-bags-list" version = "27.0.0" dependencies = [ - "aquamarine 0.5.0", + "aquamarine", "docify", "frame-benchmarking", "frame-election-provider-support", @@ -9781,7 +9661,7 @@ dependencies = [ name = "pallet-beefy-mmr" version = "28.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "binary-merkle-tree", "frame-support", "frame-system", @@ -10029,7 +9909,7 @@ dependencies = [ name = "pallet-contracts" version = "27.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "bitflags 1.3.2", "env_logger 0.11.3", @@ -10127,9 +10007,9 @@ dependencies = [ name = "pallet-contracts-proc-macro" version = "18.0.0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -10194,6 +10074,29 @@ dependencies = [ "sp-std 14.0.0", ] +[[package]] +name = "pallet-delegated-staking" +version = "1.0.0" +dependencies = [ + "frame-election-provider-support", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-nomination-pools", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std 14.0.0", + "sp-tracing 16.0.0", + "substrate-test-utils", +] + [[package]] name = "pallet-democracy" version = "28.0.0" @@ -10713,12 +10616,12 @@ dependencies = [ name = "pallet-mmr" version = "27.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "env_logger 0.11.3", "frame-benchmarking", "frame-support", "frame-system", - "itertools 0.10.5", + "itertools 0.11.0", "log", "parity-scale-codec", "scale-info", @@ -10853,6 +10756,7 @@ dependencies = [ "frame-system", "pallet-bags-list", "pallet-balances", + "pallet-delegated-staking", "pallet-nomination-pools", "pallet-staking", "pallet-staking-reward-curve", @@ -10893,7 +10797,32 @@ dependencies = [ ] [[package]] -name = "pallet-nomination-pools-test-staking" +name = "pallet-nomination-pools-test-delegate-stake" +version = "1.0.0" +dependencies = [ + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-bags-list", + "pallet-balances", + "pallet-delegated-staking", + "pallet-nomination-pools", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std 14.0.0", + "sp-tracing 16.0.0", +] + +[[package]] +name = "pallet-nomination-pools-test-transfer-stake" version = "1.0.0" dependencies = [ "frame-election-provider-support", @@ -11206,7 +11135,7 @@ dependencies = [ name = "pallet-sassafras" version = "0.3.5-dev" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "frame-benchmarking", "frame-support", "frame-system", @@ -11323,7 +11252,7 @@ dependencies = [ "log", "pallet-balances", "parity-scale-codec", - "rand_chacha 0.2.2", + "rand_chacha 0.3.1", "scale-info", "sp-arithmetic", "sp-core", @@ -11349,7 +11278,7 @@ dependencies = [ "pallet-staking-reward-curve", "pallet-timestamp", "parity-scale-codec", - "rand_chacha 0.2.2", + "rand_chacha 0.3.1", "scale-info", "serde", "sp-application-crypto", @@ -11367,11 +11296,11 @@ dependencies = [ name = "pallet-staking-reward-curve" version = "11.0.0" dependencies = [ - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", "sp-runtime", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -11551,7 +11480,7 @@ dependencies = [ name = "pallet-transaction-storage" version = "27.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "frame-benchmarking", "frame-support", "frame-system", @@ -11787,6 +11716,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-relay-chain-interface", + "docify", "frame-benchmarking", "frame-benchmarking-cli", "futures", @@ -11839,11 +11769,14 @@ dependencies = [ "cumulus-pallet-session-benchmarking", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", + "docify", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -11972,7 +11905,7 @@ checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ "bitcoin_hashes 0.13.0", "rand 0.8.5", - "rand_core 0.5.1", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -12005,9 +11938,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec 0.7.4", "bitvec", @@ -12020,12 +11953,12 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -12060,7 +11993,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "syn 1.0.109", "synstructure", ] @@ -12245,6 +12178,7 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -12481,9 +12415,9 @@ checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -12494,7 +12428,7 @@ checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -12522,9 +12456,9 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -12601,7 +12535,7 @@ version = "6.0.0" dependencies = [ "assert_cmd", "color-eyre", - "nix 0.26.2", + "nix 0.28.0", "polkadot-cli", "polkadot-core-primitives", "polkadot-node-core-pvf", @@ -12625,7 +12559,7 @@ dependencies = [ "env_logger 0.11.3", "futures", "futures-timer", - "itertools 0.10.5", + "itertools 0.11.0", "log", "polkadot-node-jaeger", "polkadot-node-metrics", @@ -12692,6 +12626,7 @@ dependencies = [ "polkadot-primitives-test-helpers", "polkadot-subsystem-bench", "rand 0.8.5", + "rstest", "sc-network", "schnellru", "sp-core", @@ -12708,7 +12643,6 @@ version = "7.0.0" dependencies = [ "assert_matches", "async-trait", - "env_logger 0.11.3", "fatality", "futures", "futures-timer", @@ -12724,16 +12658,28 @@ dependencies = [ "polkadot-primitives-test-helpers", "polkadot-subsystem-bench", "rand 0.8.5", + "rstest", "sc-network", "schnellru", "sp-application-crypto", "sp-core", "sp-keyring", + "sp-tracing 16.0.0", "thiserror", "tokio", "tracing-gum", ] +[[package]] +name = "polkadot-ckb-merkle-mountain-range" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b44320e5f7ce2c18227537a3032ae5b2c476a7e8eddba45333e1011fc31b92" +dependencies = [ + "cfg-if", + "itertools 0.10.5", +] + [[package]] name = "polkadot-cli" version = "7.0.0" @@ -12782,6 +12728,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "rstest", "sc-keystore", "sc-network", "sp-core", @@ -12841,10 +12788,11 @@ dependencies = [ name = "polkadot-erasure-coding" version = "7.0.0" dependencies = [ - "criterion 0.4.0", + "criterion", "parity-scale-codec", "polkadot-node-primitives", "polkadot-primitives", + "quickcheck", "reed-solomon-novelpoly", "sp-core", "sp-trie", @@ -12944,7 +12892,7 @@ dependencies = [ "env_logger 0.11.3", "futures", "futures-timer", - "itertools 0.10.5", + "itertools 0.11.0", "kvdb", "kvdb-memorydb", "log", @@ -13178,7 +13126,6 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", - "rstest", "sc-keystore", "sp-application-crypto", "sp-core", @@ -13215,11 +13162,11 @@ name = "polkadot-node-core-pvf" version = "7.0.0" dependencies = [ "always-assert", - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "blake3", "cfg-if", - "criterion 0.4.0", + "criterion", "futures", "futures-timer", "hex-literal", @@ -13285,7 +13232,7 @@ dependencies = [ "futures", "landlock", "libc", - "nix 0.27.1", + "nix 0.28.0", "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-primitives", @@ -13310,7 +13257,7 @@ dependencies = [ "cfg-if", "cpu-time", "libc", - "nix 0.27.1", + "nix 0.28.0", "parity-scale-codec", "polkadot-node-core-pvf-common", "polkadot-parachain-primitives", @@ -13324,9 +13271,9 @@ version = "7.0.0" dependencies = [ "blake3", "cfg-if", - "criterion 0.4.0", + "criterion", "libc", - "nix 0.27.1", + "nix 0.28.0", "parity-scale-codec", "polkadot-node-core-pvf-common", "polkadot-primitives", @@ -13492,6 +13439,7 @@ dependencies = [ "async-trait", "bitvec", "derive_more", + "fatality", "futures", "orchestra", "polkadot-node-jaeger", @@ -13524,7 +13472,7 @@ dependencies = [ "fatality", "futures", "futures-channel", - "itertools 0.10.5", + "itertools 0.11.0", "kvdb", "kvdb-memorydb", "kvdb-shared-tests", @@ -13534,6 +13482,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", "pin-project", + "polkadot-erasure-coding", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -13619,7 +13568,7 @@ dependencies = [ "hex-literal", "jsonrpsee", "log", - "nix 0.26.2", + "nix 0.28.0", "pallet-transaction-payment", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", @@ -13893,24 +13842,413 @@ dependencies = [ ] [[package]] -name = "polkadot-sdk-docs" -version = "0.0.1" +name = "polkadot-sdk" +version = "0.1.0" dependencies = [ + "asset-test-utils", + "assets-common", + "binary-merkle-tree", + "bp-asset-hub-rococo", + "bp-asset-hub-westend", + "bp-bridge-hub-cumulus", + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "bp-bridge-hub-rococo", + "bp-bridge-hub-westend", + "bp-header-chain", + "bp-kusama", + "bp-messages", + "bp-parachains", + "bp-polkadot", + "bp-polkadot-bulletin", + "bp-polkadot-core", + "bp-relayers", + "bp-rococo", + "bp-runtime", + "bp-test-utils", + "bp-westend", + "bp-xcm-bridge-hub", + "bp-xcm-bridge-hub-router", + "bridge-hub-common", + "bridge-hub-test-utils", + "bridge-runtime-common", + "cumulus-client-cli", + "cumulus-client-collator", + "cumulus-client-consensus-aura", + "cumulus-client-consensus-common", + "cumulus-client-consensus-proposer", + "cumulus-client-consensus-relay-chain", + "cumulus-client-network", + "cumulus-client-parachain-inherent", + "cumulus-client-pov-recovery", + "cumulus-client-service", "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", - "docify", + "cumulus-pallet-parachain-system-proc-macro", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-solo-to-para", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-ping", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-primitives-proof-size-hostfunction", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "cumulus-relay-chain-inprocess-interface", + "cumulus-relay-chain-interface", + "cumulus-relay-chain-minimal-node", + "cumulus-relay-chain-rpc-interface", + "cumulus-test-relay-sproof-builder", + "emulated-integration-tests-common", + "fork-tree", + "frame-benchmarking", + "frame-benchmarking-cli", + "frame-benchmarking-pallet-pov", + "frame-election-provider-solution-type", + "frame-election-provider-support", "frame-executive", + "frame-metadata-hash-extension", + "frame-remote-externalities", "frame-support", + "frame-support-procedural", + "frame-support-procedural-tools", + "frame-support-procedural-tools-derive", "frame-system", - "kitchensink-runtime", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "generate-bags", + "mmr-gadget", + "mmr-rpc", + "pallet-alliance", + "pallet-asset-conversion", + "pallet-asset-conversion-ops", + "pallet-asset-conversion-tx-payment", + "pallet-asset-rate", + "pallet-asset-tx-payment", "pallet-assets", + "pallet-atomic-swap", "pallet-aura", + "pallet-authority-discovery", "pallet-authorship", "pallet-babe", + "pallet-bags-list", "pallet-balances", + "pallet-beefy", + "pallet-beefy-mmr", + "pallet-bounties", + "pallet-bridge-grandpa", + "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-bridge-relayers", "pallet-broker", + "pallet-child-bounties", + "pallet-collator-selection", "pallet-collective", - "pallet-default-config-example", + "pallet-collective-content", + "pallet-contracts", + "pallet-contracts-mock-network", + "pallet-contracts-proc-macro", + "pallet-contracts-uapi", + "pallet-conviction-voting", + "pallet-core-fellowship", + "pallet-delegated-staking", + "pallet-democracy", + "pallet-dev-mode", + "pallet-election-provider-multi-phase", + "pallet-election-provider-support-benchmarking", + "pallet-elections-phragmen", + "pallet-fast-unstake", + "pallet-glutton", + "pallet-grandpa", + "pallet-identity", + "pallet-im-online", + "pallet-indices", + "pallet-insecure-randomness-collective-flip", + "pallet-lottery", + "pallet-membership", + "pallet-message-queue", + "pallet-migrations", + "pallet-mixnet", + "pallet-mmr", + "pallet-multisig", + "pallet-nft-fractionalization", + "pallet-nfts", + "pallet-nfts-runtime-api", + "pallet-nis", + "pallet-node-authorization", + "pallet-nomination-pools", + "pallet-nomination-pools-benchmarking", + "pallet-nomination-pools-runtime-api", + "pallet-offences", + "pallet-offences-benchmarking", + "pallet-paged-list", + "pallet-parameters", + "pallet-preimage", + "pallet-proxy", + "pallet-ranked-collective", + "pallet-recovery", + "pallet-referenda", + "pallet-remark", + "pallet-root-offences", + "pallet-root-testing", + "pallet-safe-mode", + "pallet-salary", + "pallet-scheduler", + "pallet-scored-pool", + "pallet-session", + "pallet-session-benchmarking", + "pallet-skip-feeless-payment", + "pallet-society", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-staking-reward-fn", + "pallet-staking-runtime-api", + "pallet-state-trie-migration", + "pallet-statement", + "pallet-sudo", + "pallet-timestamp", + "pallet-tips", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-transaction-storage", + "pallet-treasury", + "pallet-tx-pause", + "pallet-uniques", + "pallet-utility", + "pallet-vesting", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub", + "pallet-xcm-bridge-hub-router", + "parachains-common", + "parachains-runtimes-test-utils", + "polkadot-approval-distribution", + "polkadot-availability-bitfield-distribution", + "polkadot-availability-distribution", + "polkadot-availability-recovery", + "polkadot-cli", + "polkadot-collator-protocol", + "polkadot-core-primitives", + "polkadot-dispute-distribution", + "polkadot-erasure-coding", + "polkadot-gossip-support", + "polkadot-network-bridge", + "polkadot-node-collation-generation", + "polkadot-node-core-approval-voting", + "polkadot-node-core-av-store", + "polkadot-node-core-backing", + "polkadot-node-core-bitfield-signing", + "polkadot-node-core-candidate-validation", + "polkadot-node-core-chain-api", + "polkadot-node-core-chain-selection", + "polkadot-node-core-dispute-coordinator", + "polkadot-node-core-parachains-inherent", + "polkadot-node-core-prospective-parachains", + "polkadot-node-core-provisioner", + "polkadot-node-core-pvf", + "polkadot-node-core-pvf-checker", + "polkadot-node-core-pvf-common", + "polkadot-node-core-pvf-execute-worker", + "polkadot-node-core-pvf-prepare-worker", + "polkadot-node-core-runtime-api", + "polkadot-node-jaeger", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem", + "polkadot-node-subsystem-types", + "polkadot-node-subsystem-util", + "polkadot-overseer", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-rpc", + "polkadot-runtime-common", + "polkadot-runtime-metrics", + "polkadot-runtime-parachains", + "polkadot-sdk-frame", + "polkadot-service", + "polkadot-statement-distribution", + "polkadot-statement-table", + "rococo-runtime-constants", + "sc-allocator", + "sc-authority-discovery", + "sc-basic-authorship", + "sc-block-builder", + "sc-chain-spec", + "sc-chain-spec-derive", + "sc-cli", + "sc-client-api", + "sc-client-db", + "sc-consensus", + "sc-consensus-aura", + "sc-consensus-babe", + "sc-consensus-babe-rpc", + "sc-consensus-beefy", + "sc-consensus-beefy-rpc", + "sc-consensus-epochs", + "sc-consensus-grandpa", + "sc-consensus-grandpa-rpc", + "sc-consensus-manual-seal", + "sc-consensus-pow", + "sc-consensus-slots", + "sc-executor", + "sc-executor-common", + "sc-executor-polkavm", + "sc-executor-wasmtime", + "sc-informant", + "sc-keystore", + "sc-mixnet", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-network-light", + "sc-network-statement", + "sc-network-sync", + "sc-network-transactions", + "sc-network-types", + "sc-offchain", + "sc-proposer-metrics", + "sc-rpc", + "sc-rpc-api", + "sc-rpc-server", + "sc-rpc-spec-v2", + "sc-service", + "sc-state-db", + "sc-statement-store", + "sc-storage-monitor", + "sc-sync-state-rpc", + "sc-sysinfo", + "sc-telemetry", + "sc-tracing", + "sc-tracing-proc-macro", + "sc-transaction-pool", + "sc-transaction-pool-api", + "sc-utils", + "slot-range-helper", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "snowbridge-outbound-queue-merkle-tree", + "snowbridge-outbound-queue-runtime-api", + "snowbridge-pallet-ethereum-client", + "snowbridge-pallet-ethereum-client-fixtures", + "snowbridge-pallet-inbound-queue", + "snowbridge-pallet-inbound-queue-fixtures", + "snowbridge-pallet-outbound-queue", + "snowbridge-pallet-system", + "snowbridge-router-primitives", + "snowbridge-runtime-common", + "snowbridge-runtime-test-common", + "snowbridge-system-runtime-api", + "sp-api", + "sp-api-proc-macro", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-block-builder", + "sp-blockchain", + "sp-consensus", + "sp-consensus-aura", + "sp-consensus-babe", + "sp-consensus-beefy", + "sp-consensus-grandpa", + "sp-consensus-pow", + "sp-consensus-slots", + "sp-core", + "sp-core-hashing", + "sp-core-hashing-proc-macro", + "sp-crypto-ec-utils 0.10.0", + "sp-crypto-hashing", + "sp-crypto-hashing-proc-macro", + "sp-database", + "sp-debug-derive 14.0.0", + "sp-externalities 0.25.0", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-keyring", + "sp-keystore", + "sp-maybe-compressed-blob", + "sp-metadata-ir", + "sp-mixnet", + "sp-mmr-primitives", + "sp-npos-elections", + "sp-offchain", + "sp-panic-handler", + "sp-rpc", + "sp-runtime", + "sp-runtime-interface 24.0.0", + "sp-runtime-interface-proc-macro 17.0.0", + "sp-session", + "sp-staking", + "sp-state-machine", + "sp-statement-store", + "sp-std 14.0.0", + "sp-storage 19.0.0", + "sp-timestamp", + "sp-tracing 16.0.0", + "sp-transaction-pool", + "sp-transaction-storage-proof", + "sp-trie", + "sp-version", + "sp-version-proc-macro", + "sp-wasm-interface 20.0.0", + "sp-weights", + "staging-node-inspect", + "staging-parachain-info", + "staging-tracking-allocator", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "subkey", + "substrate-bip39", + "substrate-build-script-utils", + "substrate-frame-rpc-support", + "substrate-frame-rpc-system", + "substrate-prometheus-endpoint", + "substrate-rpc-client", + "substrate-state-trie-migration-rpc", + "substrate-wasm-builder", + "testnet-parachains-constants", + "tracing-gum", + "tracing-gum-proc-macro", + "westend-runtime-constants", + "xcm-emulator", + "xcm-fee-payment-runtime-api", + "xcm-procedural", + "xcm-simulator", +] + +[[package]] +name = "polkadot-sdk-docs" +version = "0.0.1" +dependencies = [ + "cumulus-client-service", + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-primitives-proof-size-hostfunction", + "cumulus-primitives-storage-weight-reclaim", + "docify", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "kitchensink-runtime", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-broker", + "pallet-collective", + "pallet-default-config-example", "pallet-democracy", "pallet-example-offchain-worker", "pallet-example-single-block-migrations", @@ -13926,6 +14264,7 @@ dependencies = [ "pallet-uniques", "pallet-utility", "parity-scale-codec", + "polkadot-sdk", "polkadot-sdk-frame", "sc-cli", "sc-client-db", @@ -13935,11 +14274,13 @@ dependencies = [ "sc-consensus-grandpa", "sc-consensus-manual-seal", "sc-consensus-pow", + "sc-executor", "sc-network", "sc-rpc", "sc-rpc-api", + "sc-service", "scale-info", - "simple-mermaid", + "simple-mermaid 0.1.1", "sp-api", "sp-arithmetic", "sp-core", @@ -13954,6 +14295,7 @@ dependencies = [ "staging-xcm", "subkey", "substrate-wasm-builder", + "xcm-docs", ] [[package]] @@ -13961,10 +14303,13 @@ name = "polkadot-sdk-frame" version = "0.1.0" dependencies = [ "docify", + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", + "frame-try-runtime", "log", "pallet-examples", "parity-scale-codec", @@ -13981,6 +14326,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-std 14.0.0", + "sp-storage 19.0.0", "sp-transaction-pool", "sp-version", ] @@ -13995,6 +14341,7 @@ dependencies = [ "env_logger 0.11.3", "frame-benchmarking", "frame-benchmarking-cli", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-rpc-runtime-api", @@ -14132,6 +14479,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "polkadot-subsystem-bench", "rand_chacha 0.3.1", "sc-keystore", "sc-network", @@ -14196,6 +14544,7 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "polkadot-primitives-test-helpers", + "polkadot-statement-distribution", "prometheus", "pyroscope", "pyroscope_pprofrs", @@ -14220,6 +14569,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-timestamp", + "strum 0.24.1", "substrate-prometheus-endpoint", "tokio", "tracing-gum", @@ -14272,6 +14622,7 @@ dependencies = [ "polkadot-node-core-pvf-common", "polkadot-node-core-pvf-execute-worker", "polkadot-node-core-pvf-prepare-worker", + "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-test-helpers", @@ -14455,9 +14806,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ "polkavm-common", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -14467,7 +14818,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ "polkavm-derive-impl", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -14629,7 +14980,7 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "syn 1.0.109", ] @@ -14639,8 +14990,8 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ - "proc-macro2 1.0.75", - "syn 2.0.53", + "proc-macro2 1.0.82", + "syn 2.0.61", ] [[package]] @@ -14686,9 +15037,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2685dd208a3771337d8d386a89840f0f43cd68be8dae90a5f8c2384effc9cd" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ "toml_edit 0.21.0", ] @@ -14700,7 +15051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", "version_check", @@ -14712,7 +15063,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "version_check", ] @@ -14729,9 +15080,9 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -14745,9 +15096,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -14810,9 +15161,9 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -14859,12 +15210,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.12.4", ] [[package]] @@ -14882,13 +15233,34 @@ dependencies = [ "petgraph", "prettyplease 0.1.25", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "regex", "syn 1.0.109", "tempfile", "which", ] +[[package]] +name = "prost-build" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80b776a1b2dc779f5ee0641f8ade0125bc1298dd41a9a0c16d8bd57b42d222b1" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.11.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease 0.2.12", + "prost 0.12.4", + "prost-types 0.12.4", + "regex", + "syn 2.0.61", + "tempfile", +] + [[package]] name = "prost-derive" version = "0.11.9" @@ -14897,22 +15269,22 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools 0.10.5", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", "itertools 0.11.0", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -14924,6 +15296,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +dependencies = [ + "prost 0.12.4", +] + [[package]] name = "psm" version = "0.1.21" @@ -15093,7 +15474,7 @@ version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", ] [[package]] @@ -15333,9 +15714,9 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -15476,6 +15857,7 @@ dependencies = [ "jsonpath_lib", "log", "num-traits", + "parking_lot 0.12.1", "serde_json", "sp-runtime", "substrate-prometheus-endpoint", @@ -15715,6 +16097,7 @@ dependencies = [ "bitvec", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-remote-externalities", "frame-support", "frame-system", @@ -15891,12 +16274,12 @@ checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" dependencies = [ "cfg-if", "glob", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.53", + "syn 2.0.61", "unicode-ident", ] @@ -16256,8 +16639,8 @@ dependencies = [ "multihash 0.17.0", "multihash-codetable", "parity-scale-codec", - "prost 0.12.3", - "prost-build", + "prost 0.12.4", + "prost-build 0.12.4", "quickcheck", "rand 0.8.5", "sc-client-api", @@ -16320,11 +16703,12 @@ dependencies = [ name = "sc-chain-spec" version = "28.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "docify", "log", "memmap2 0.9.3", "parity-scale-codec", + "regex", "sc-chain-spec-derive", "sc-client-api", "sc-executor", @@ -16350,23 +16734,23 @@ dependencies = [ name = "sc-chain-spec-derive" version = "11.0.0" dependencies = [ - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "sc-cli" version = "0.36.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "chrono", "clap 4.5.3", "fdlimit", "futures", "futures-timer", - "itertools 0.10.5", + "itertools 0.11.0", "libp2p-identity", "log", "names", @@ -16432,8 +16816,8 @@ dependencies = [ name = "sc-client-db" version = "0.35.0" dependencies = [ - "array-bytes 6.1.0", - "criterion 0.4.0", + "array-bytes", + "criterion", "hash-db", "kitchensink-runtime", "kvdb", @@ -16469,7 +16853,7 @@ dependencies = [ "futures", "futures-timer", "log", - "mockall", + "mockall 0.11.4", "parking_lot 0.12.1", "sc-client-api", "sc-network-types", @@ -16598,7 +16982,7 @@ dependencies = [ name = "sc-consensus-beefy" version = "13.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-channel", "async-trait", "fnv", @@ -16676,7 +17060,7 @@ name = "sc-consensus-grandpa" version = "0.19.0" dependencies = [ "ahash 0.8.8", - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "async-trait", "dyn-clone", @@ -16834,9 +17218,9 @@ dependencies = [ name = "sc-executor" version = "0.32.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", - "criterion 0.4.0", + "criterion", "env_logger 0.11.3", "num_cpus", "parity-scale-codec", @@ -16936,7 +17320,7 @@ dependencies = [ name = "sc-keystore" version = "25.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "parking_lot 0.12.1", "serde_json", "sp-application-crypto", @@ -16950,7 +17334,7 @@ dependencies = [ name = "sc-mixnet" version = "0.4.0" dependencies = [ - "array-bytes 4.2.0", + "array-bytes", "arrayvec 0.7.4", "blake2 0.10.6", "bytes", @@ -16978,7 +17362,7 @@ dependencies = [ name = "sc-network" version = "0.34.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "async-channel", "async-trait", @@ -16994,15 +17378,15 @@ dependencies = [ "linked_hash_set", "litep2p", "log", - "mockall", + "mockall 0.11.4", "multistream-select", "once_cell", "parity-scale-codec", "parking_lot 0.12.1", "partial_sort", "pin-project", - "prost 0.11.9", - "prost-build", + "prost 0.12.4", + "prost-build 0.12.4", "rand 0.8.5", "sc-block-builder", "sc-client-api", @@ -17047,7 +17431,7 @@ dependencies = [ "futures", "libp2p-identity", "parity-scale-codec", - "prost-build", + "prost-build 0.12.4", "sc-consensus", "sc-network-types", "sp-consensus", @@ -17084,13 +17468,13 @@ dependencies = [ name = "sc-network-light" version = "0.33.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-channel", "futures", "log", "parity-scale-codec", - "prost 0.12.3", - "prost-build", + "prost 0.12.4", + "prost-build 0.12.4", "sc-client-api", "sc-network", "sc-network-types", @@ -17104,7 +17488,7 @@ dependencies = [ name = "sc-network-statement" version = "0.16.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-channel", "futures", "libp2p", @@ -17124,7 +17508,7 @@ dependencies = [ name = "sc-network-sync" version = "0.33.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-channel", "async-trait", "fork-tree", @@ -17132,10 +17516,10 @@ dependencies = [ "futures-timer", "libp2p", "log", - "mockall", + "mockall 0.11.4", "parity-scale-codec", - "prost 0.12.3", - "prost-build", + "prost 0.12.4", + "prost-build 0.12.4", "quickcheck", "sc-block-builder", "sc-client-api", @@ -17196,7 +17580,7 @@ dependencies = [ name = "sc-network-transactions" version = "0.33.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "futures", "libp2p", "log", @@ -17213,22 +17597,25 @@ dependencies = [ [[package]] name = "sc-network-types" -version = "0.10.0-dev" +version = "0.10.0" dependencies = [ - "bs58 0.4.0", + "bs58 0.5.0", + "ed25519-dalek 2.1.1", "libp2p-identity", "litep2p", "multiaddr", "multihash 0.17.0", + "quickcheck", "rand 0.8.5", "thiserror", + "zeroize", ] [[package]] name = "sc-offchain" version = "29.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-trait", "bytes", "fnv", @@ -17340,10 +17727,12 @@ dependencies = [ name = "sc-rpc-server" version = "11.0.0" dependencies = [ + "forwarded-header-value", "futures", "governor", "http", "hyper", + "ip_network", "jsonrpsee", "log", "serde_json", @@ -17357,7 +17746,7 @@ dependencies = [ name = "sc-rpc-spec-v2" version = "0.34.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "futures", "futures-util", @@ -17477,7 +17866,7 @@ dependencies = [ name = "sc-service-test" version = "2.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-channel", "fdlimit", "futures", @@ -17615,7 +18004,7 @@ version = "28.0.0" dependencies = [ "ansi_term", "chrono", - "criterion 0.4.0", + "criterion", "is-terminal", "lazy_static", "libc", @@ -17635,7 +18024,7 @@ dependencies = [ "sp-tracing 16.0.0", "thiserror", "tracing", - "tracing-log 0.1.3", + "tracing-log 0.2.0", "tracing-subscriber 0.3.18", ] @@ -17643,20 +18032,20 @@ dependencies = [ name = "sc-tracing-proc-macro" version = "11.0.0" dependencies = [ - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "sc-transaction-pool" version = "28.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "async-trait", - "criterion 0.4.0", + "criterion", "futures", "futures-timer", "linked-hash-map", @@ -17714,11 +18103,34 @@ dependencies = [ "tokio-test", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12ebca36cec2a3f983c46295b282b35e5f8496346fb859a8776dad5389e5389" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", +] + [[package]] name = "scale-info" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec", "cfg-if", @@ -17730,16 +18142,22 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" + [[package]] name = "schannel" version = "0.1.22" @@ -17767,7 +18185,7 @@ version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "serde_derive_internals", "syn 1.0.109", @@ -17814,7 +18232,7 @@ dependencies = [ "merlin", "rand_core 0.6.4", "serde_bytes", - "sha2 0.10.7", + "sha2 0.10.8", "subtle 2.5.0", "zeroize", ] @@ -17849,9 +18267,9 @@ dependencies = [ [[package]] name = "sctp-proto" -version = "0.1.7" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f64cef148d3295c730c3cb340b0b252a4d570b1c7d4bf0808f88540b0a888bc" +checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" dependencies = [ "bytes", "crc", @@ -18061,9 +18479,9 @@ version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -18072,7 +18490,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -18162,9 +18580,9 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -18227,9 +18645,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -18355,6 +18773,11 @@ dependencies = [ "bitflags 2.4.0", ] +[[package]] +name = "simple-mermaid" +version = "0.1.0" +source = "git+https://github.com/kianenigma/simple-mermaid.git?branch=main#e48b187bcfd5cc75111acd9d241f1bd36604344b" + [[package]] name = "simple-mermaid" version = "0.1.1" @@ -18415,9 +18838,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol" @@ -18429,7 +18852,7 @@ dependencies = [ "async-executor", "async-fs", "async-io", - "async-lock 2.8.0", + "async-lock", "async-net", "async-process", "blocking", @@ -18452,7 +18875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0bb30cf57b7b5f6109ce17c3164445e2d6f270af2cb48f6e4d31c2967c9a9f5" dependencies = [ "arrayvec 0.7.4", - "async-lock 2.8.0", + "async-lock", "atomic-take", "base64 0.21.2", "bip39", @@ -18461,9 +18884,9 @@ dependencies = [ "chacha20", "crossbeam-queue", "derive_more", - "ed25519-zebra 4.0.3", + "ed25519-zebra", "either", - "event-listener 2.5.3", + "event-listener", "fnv", "futures-lite", "futures-util", @@ -18487,7 +18910,7 @@ dependencies = [ "schnorrkel 0.10.2", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "siphasher", "slab", @@ -18506,12 +18929,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "256b5bad1d6b49045e95fe87492ce73d5af81545d8b4d8318a872d2007024c33" dependencies = [ "async-channel", - "async-lock 2.8.0", + "async-lock", "base64 0.21.2", "blake2-rfc", "derive_more", "either", - "event-listener 2.5.3", + "event-listener", "fnv", "futures-channel", "futures-lite", @@ -18554,7 +18977,7 @@ dependencies = [ "rand_core 0.6.4", "ring 0.17.7", "rustc_version 0.4.0", - "sha2 0.10.7", + "sha2 0.10.8", "subtle 2.5.0", ] @@ -18654,7 +19077,7 @@ dependencies = [ name = "snowbridge-outbound-queue-merkle-tree" version = "0.3.0" dependencies = [ - "array-bytes 4.2.0", + "array-bytes", "env_logger 0.11.3", "hex", "hex-literal", @@ -19025,18 +19448,18 @@ dependencies = [ "Inflector", "assert_matches", "blake2 0.10.6", - "expander 2.0.0", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "expander", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "sp-api-test" version = "2.0.1" dependencies = [ - "criterion 0.4.0", + "criterion", "futures", "log", "parity-scale-codec", @@ -19082,7 +19505,7 @@ dependencies = [ name = "sp-arithmetic" version = "23.0.0" dependencies = [ - "criterion 0.4.0", + "criterion", "docify", "integer-sqrt", "num-traits", @@ -19213,7 +19636,7 @@ dependencies = [ name = "sp-consensus-beefy" version = "13.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "lazy_static", "parity-scale-codec", "scale-info", @@ -19284,20 +19707,20 @@ dependencies = [ name = "sp-core" version = "28.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "bandersnatch_vrfs", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", "bs58 0.5.0", - "criterion 0.4.0", + "criterion", "dyn-clonable", - "ed25519-zebra 3.1.0", + "ed25519-zebra", "futures", "hash-db", "hash256-std-hasher", "impl-serde", - "itertools 0.10.5", + "itertools 0.11.0", "k256", "lazy_static", "libsecp256k1", @@ -19400,9 +19823,9 @@ version = "0.1.0" dependencies = [ "blake2b_simd", "byteorder", - "criterion 0.4.0", + "criterion", "digest 0.10.7", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "sp-crypto-hashing-proc-macro", "twox-hash", @@ -19414,7 +19837,7 @@ version = "0.1.0" dependencies = [ "quote 1.0.35", "sp-crypto-hashing", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -19430,18 +19853,18 @@ name = "sp-debug-derive" version = "8.0.0" source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] name = "sp-debug-derive" version = "14.0.0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -19493,7 +19916,7 @@ name = "sp-io" version = "30.0.0" dependencies = [ "bytes", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "libsecp256k1", "log", "parity-scale-codec", @@ -19529,7 +19952,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.1", "rand 0.8.5", - "rand_chacha 0.2.2", + "rand_chacha 0.3.1", "sp-core", "sp-externalities 0.25.0", ] @@ -19565,10 +19988,10 @@ dependencies = [ name = "sp-mmr-primitives" version = "26.0.0" dependencies = [ - "array-bytes 6.1.0", - "ckb-merkle-mountain-range", + "array-bytes", "log", "parity-scale-codec", + "polkadot-ckb-merkle-mountain-range", "scale-info", "serde", "sp-api", @@ -19640,13 +20063,14 @@ dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", "log", + "num-traits", "parity-scale-codec", "paste", "rand 0.8.5", "scale-info", "serde", "serde_json", - "simple-mermaid", + "simple-mermaid 0.1.1", "sp-api", "sp-application-crypto", "sp-arithmetic", @@ -19709,9 +20133,9 @@ source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf5 dependencies = [ "Inflector", "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -19719,11 +20143,11 @@ name = "sp-runtime-interface-proc-macro" version = "17.0.0" dependencies = [ "Inflector", - "expander 2.0.0", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "expander", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -19793,7 +20217,7 @@ dependencies = [ name = "sp-state-machine" version = "0.35.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_matches", "hash-db", "log", @@ -19818,12 +20242,12 @@ version = "10.0.0" dependencies = [ "aes-gcm", "curve25519-dalek 4.1.2", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "hkdf", "parity-scale-codec", "rand 0.8.5", "scale-info", - "sha2 0.10.7", + "sha2 0.10.8", "sp-api", "sp-application-crypto", "sp-core", @@ -19939,8 +20363,8 @@ name = "sp-trie" version = "29.0.0" dependencies = [ "ahash 0.8.8", - "array-bytes 6.1.0", - "criterion 0.5.1", + "array-bytes", + "criterion", "hash-db", "lazy_static", "memory-db", @@ -19982,10 +20406,10 @@ name = "sp-version-proc-macro" version = "13.0.0" dependencies = [ "parity-scale-codec", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "sp-version", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -20067,7 +20491,7 @@ checksum = "5e6915280e2d0db8911e5032a5c275571af6bdded2916abd691a659be25d3439" dependencies = [ "Inflector", "num-format", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "serde", "serde_json", @@ -20092,7 +20516,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -20105,7 +20529,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-chain-spec-builder" -version = "3.0.0" +version = "1.6.0" dependencies = [ "clap 4.5.3", "log", @@ -20118,107 +20542,31 @@ dependencies = [ name = "staging-node-cli" version = "3.0.0-dev" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "assert_cmd", "clap 4.5.3", "clap_complete", - "criterion 0.4.0", - "frame-benchmarking", - "frame-benchmarking-cli", - "frame-support", - "frame-system", - "frame-system-rpc-runtime-api", + "criterion", "futures", "jsonrpsee", "kitchensink-runtime", "log", - "mmr-gadget", - "nix 0.26.2", + "nix 0.28.0", "node-primitives", "node-rpc", "node-testing", - "pallet-asset-conversion-tx-payment", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-balances", - "pallet-contracts", - "pallet-glutton", - "pallet-im-online", - "pallet-root-testing", - "pallet-skip-feeless-payment", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-treasury", "parity-scale-codec", "platforms", + "polkadot-sdk", "rand 0.8.5", "regex", - "sc-authority-discovery", - "sc-basic-authorship", - "sc-block-builder", - "sc-chain-spec", - "sc-cli", - "sc-client-api", - "sc-client-db", - "sc-consensus", - "sc-consensus-babe", - "sc-consensus-beefy", - "sc-consensus-epochs", - "sc-consensus-grandpa", - "sc-consensus-slots", - "sc-executor", - "sc-keystore", - "sc-mixnet", - "sc-network", - "sc-network-common", - "sc-network-statement", - "sc-network-sync", - "sc-offchain", - "sc-rpc", - "sc-service", "sc-service-test", - "sc-statement-store", - "sc-storage-monitor", - "sc-sync-state-rpc", - "sc-sysinfo", - "sc-telemetry", - "sc-transaction-pool", - "sc-transaction-pool-api", "scale-info", "serde", "serde_json", "soketto", - "sp-api", - "sp-application-crypto", - "sp-authority-discovery", - "sp-blockchain", - "sp-consensus", - "sp-consensus-babe", - "sp-consensus-beefy", - "sp-consensus-grandpa", - "sp-core", - "sp-crypto-hashing", - "sp-externalities 0.25.0", - "sp-genesis-builder", - "sp-inherents", - "sp-io", - "sp-keyring", - "sp-keystore", - "sp-mixnet", - "sp-mmr-primitives", - "sp-runtime", - "sp-state-machine", - "sp-statement-store", - "sp-timestamp", - "sp-tracing 16.0.0", - "sp-transaction-storage-proof", - "sp-trie", "staging-node-inspect", - "substrate-build-script-utils", "substrate-cli-test-utils", - "substrate-frame-cli", - "substrate-rpc-client", "tempfile", "tokio", "tokio-util", @@ -20264,7 +20612,7 @@ version = "2.0.0" name = "staging-xcm" version = "7.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "bounded-collections", "derivative", "environmental", @@ -20360,24 +20708,24 @@ checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" dependencies = [ "cfg_aliases", "memchr", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "str0m" -version = "0.2.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48572247f422dcbe68630c973f8296fbd5157119cd36a3223e48bf83d47727" +checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" dependencies = [ "combine", "crc", + "fastrand 2.1.0", "hmac 0.12.1", "once_cell", "openssl", "openssl-sys", - "rand 0.8.5", "sctp-proto", "serde", "sha-1 0.10.1", @@ -20435,7 +20783,7 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] @@ -20471,7 +20819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "rustversion", "syn 1.0.109", @@ -20484,10 +20832,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "rustversion", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -20497,10 +20845,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "rustversion", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -20520,7 +20868,7 @@ dependencies = [ "pbkdf2", "rustc-hex", "schnorrkel 0.11.4", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -20534,7 +20882,7 @@ version = "0.1.0" dependencies = [ "assert_cmd", "futures", - "nix 0.26.2", + "nix 0.28.0", "node-primitives", "regex", "sc-cli", @@ -20545,18 +20893,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "substrate-frame-cli" -version = "32.0.0" -dependencies = [ - "clap 4.5.3", - "frame-support", - "frame-system", - "sc-cli", - "sp-core", - "sp-runtime", -] - [[package]] name = "substrate-frame-rpc-support" version = "29.0.0" @@ -20686,7 +21022,7 @@ dependencies = [ name = "substrate-test-client" version = "2.0.1" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "async-trait", "futures", "parity-scale-codec", @@ -20712,8 +21048,9 @@ dependencies = [ name = "substrate-test-runtime" version = "2.0.0" dependencies = [ - "array-bytes 6.1.0", + "array-bytes", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-rpc-runtime-api", @@ -20805,13 +21142,22 @@ dependencies = [ name = "substrate-wasm-builder" version = "17.0.0" dependencies = [ + "array-bytes", "build-helper", "cargo_metadata", "console", "filetime", + "frame-metadata", + "merkleized-metadata", + "parity-scale-codec", "parity-wasm", "polkavm-linker", + "sc-executor", + "sp-core", + "sp-io", "sp-maybe-compressed-blob", + "sp-tracing 16.0.0", + "sp-version", "strum 0.26.2", "tempfile", "toml 0.8.8", @@ -20945,18 +21291,18 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.53" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "unicode-ident", ] @@ -20968,9 +21314,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b837ef12ab88835251726eb12237655e61ec8dc8a280085d1961cdc3dfd047" dependencies = [ "paste", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -20979,7 +21325,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", "unicode-xid 0.2.4", @@ -21051,7 +21397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", - "fastrand 2.0.0", + "fastrand 2.1.0", "redox_syscall 0.4.1", "rustix 0.38.21", "windows-sys 0.48.0", @@ -21082,6 +21428,28 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +[[package]] +name = "test-log" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +dependencies = [ + "env_logger 0.11.3", + "test-log-macros", + "tracing-subscriber 0.3.18", +] + +[[package]] +name = "test-log-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +dependencies = [ + "proc-macro2 1.0.82", + "quote 1.0.35", + "syn 2.0.61", +] + [[package]] name = "test-parachain-adder" version = "1.0.0" @@ -21221,9 +21589,9 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] @@ -21243,20 +21611,20 @@ version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -21417,9 +21785,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -21479,18 +21847,6 @@ dependencies = [ "tokio-stream", ] -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.17.3", -] - [[package]] name = "tokio-tungstenite" version = "0.20.1" @@ -21503,14 +21859,14 @@ dependencies = [ "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", - "tungstenite 0.20.1", + "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -21518,7 +21874,6 @@ dependencies = [ "futures-sink", "pin-project-lite 0.2.12", "tokio", - "tracing", ] [[package]] @@ -21638,9 +21993,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -21678,11 +22033,11 @@ name = "tracing-gum-proc-macro" version = "5.0.0" dependencies = [ "assert_matches", - "expander 2.0.0", - "proc-macro-crate 3.0.0", - "proc-macro2 1.0.75", + "expander", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -21765,7 +22120,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3092f400e9f7e3ce8c1756016a8b6287163ab7a11dd47d82169260cb4cc2d680" dependencies = [ - "criterion 0.5.1", + "criterion", "hash-db", "keccak-hasher", "memory-db", @@ -21926,25 +22281,6 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand 0.8.5", - "sha-1 0.10.1", - "thiserror", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.20.1" @@ -22212,7 +22548,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", "zeroize", @@ -22285,9 +22621,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", "wasm-bindgen-shared", ] @@ -22319,9 +22655,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -22352,7 +22688,7 @@ version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", ] @@ -22530,7 +22866,7 @@ dependencies = [ "log", "rustix 0.36.15", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "toml 0.5.11", "windows-sys 0.45.0", "zstd 0.11.2+zstd.1.5.2", @@ -22744,8 +23080,10 @@ dependencies = [ "sp-consensus-beefy", "sp-core", "sp-runtime", + "staging-xcm", "westend-runtime", "westend-runtime-constants", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -22757,6 +23095,7 @@ dependencies = [ "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-metadata-hash-extension", "frame-remote-externalities", "frame-support", "frame-system", @@ -22775,6 +23114,7 @@ dependencies = [ "pallet-beefy-mmr", "pallet-collective", "pallet-conviction-voting", + "pallet-delegated-staking", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", @@ -23324,6 +23664,31 @@ dependencies = [ "libc", ] +[[package]] +name = "xcm-docs" +version = "0.1.0" +dependencies = [ + "docify", + "pallet-balances", + "pallet-message-queue", + "pallet-xcm", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-parachains", + "polkadot-sdk-frame", + "scale-info", + "simple-mermaid 0.1.0", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "test-log", + "xcm-simulator", +] + [[package]] name = "xcm-emulator" version = "0.5.0" @@ -23385,14 +23750,24 @@ dependencies = [ name = "xcm-fee-payment-runtime-api" version = "0.1.0" dependencies = [ + "env_logger 0.9.3", + "frame-executive", "frame-support", + "frame-system", + "log", + "pallet-assets", + "pallet-balances", + "pallet-xcm", "parity-scale-codec", "scale-info", "sp-api", + "sp-io", "sp-runtime", "sp-std 14.0.0", "sp-weights", "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", ] [[package]] @@ -23400,10 +23775,10 @@ name = "xcm-procedural" version = "7.0.0" dependencies = [ "Inflector", - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", "staging-xcm", - "syn 2.0.53", + "syn 2.0.61", "trybuild", ] @@ -23412,12 +23787,16 @@ name = "xcm-simulator" version = "7.0.0" dependencies = [ "frame-support", + "frame-system", "parity-scale-codec", "paste", "polkadot-core-primitives", "polkadot-parachain-primitives", + "polkadot-primitives", "polkadot-runtime-parachains", + "scale-info", "sp-io", + "sp-runtime", "sp-std 14.0.0", "staging-xcm", "staging-xcm-builder", @@ -23523,9 +23902,9 @@ version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -23543,9 +23922,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 2.0.53", + "syn 2.0.61", ] [[package]] @@ -23560,7 +23939,7 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "tokio-tungstenite 0.17.2", + "tokio-tungstenite", "tracing-gum", "url", ] diff --git a/Cargo.toml b/Cargo.toml index 1d3f3d8e9ecd137493e72370734378fac9b19a87..d6099e420f918832d962bde854cd7c619d276f1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -218,6 +218,7 @@ members = [ "polkadot/utils/generate-bags", "polkadot/utils/remote-ext-tests/bags-list", "polkadot/xcm", + "polkadot/xcm/docs", "polkadot/xcm/pallet-xcm", "polkadot/xcm/pallet-xcm-benchmarks", "polkadot/xcm/procedural", @@ -328,6 +329,7 @@ members = [ "substrate/frame/contracts/uapi", "substrate/frame/conviction-voting", "substrate/frame/core-fellowship", + "substrate/frame/delegated-staking", "substrate/frame/democracy", "substrate/frame/election-provider-multi-phase", "substrate/frame/election-provider-multi-phase/test-staking-e2e", @@ -359,6 +361,7 @@ members = [ "substrate/frame/membership", "substrate/frame/merkle-mountain-range", "substrate/frame/message-queue", + "substrate/frame/metadata-hash-extension", "substrate/frame/migrations", "substrate/frame/mixnet", "substrate/frame/multisig", @@ -371,7 +374,8 @@ members = [ "substrate/frame/nomination-pools/benchmarking", "substrate/frame/nomination-pools/fuzzer", "substrate/frame/nomination-pools/runtime-api", - "substrate/frame/nomination-pools/test-staking", + "substrate/frame/nomination-pools/test-delegate-stake", + "substrate/frame/nomination-pools/test-transfer-stake", "substrate/frame/offences", "substrate/frame/offences/benchmarking", "substrate/frame/paged-list", @@ -500,7 +504,6 @@ members = [ "substrate/utils/build-script-utils", "substrate/utils/fork-tree", "substrate/utils/frame/benchmarking-cli", - "substrate/utils/frame/frame-utilities-cli", "substrate/utils/frame/generate-bags", "substrate/utils/frame/generate-bags/node-runtime", "substrate/utils/frame/omni-bencher", @@ -512,21 +515,23 @@ members = [ "substrate/utils/prometheus", "substrate/utils/substrate-bip39", "substrate/utils/wasm-builder", - "templates/minimal", "templates/minimal/node", "templates/minimal/pallets/template", "templates/minimal/runtime", - + "templates/parachain/node", + "templates/parachain/pallets/template", + "templates/parachain/runtime", "templates/solochain/node", "templates/solochain/pallets/template", "templates/solochain/runtime", + "umbrella", +] - "templates/parachain/node", - "templates/parachain/pallets/template", - "templates/parachain/runtime", +default-members = [ + "polkadot", + "substrate/bin/node/cli", ] -default-members = ["polkadot", "substrate/bin/node/cli"] [workspace.lints.rust] suspicious_double_ref_op = { level = "allow", priority = 2 } diff --git a/README.md b/README.md index 63743a456f4c8f8561bbeee8c59d63b88d352285..773481732520e2a8c9217e72e426a9bda781fb6f 100644 --- a/README.md +++ b/README.md @@ -1,81 +1,83 @@ -> NOTE: We have recently made significant changes to our repository structure. In order to streamline our development -process and foster better contributions, we have merged three separate repositories Cumulus, Substrate and Polkadot into -this repository. Read more about the changes [ -here](https://polkadot-public.notion.site/Polkadot-SDK-FAQ-fbc4cecc2c46443fb37b9eeec2f0d85f). -# Polkadot SDK +
+ +![SDK Logo](./docs/images/Polkadot_Logo_Horizontal_Pink_White.png#gh-dark-mode-only) +![SDK Logo](./docs/images/Polkadot_Logo_Horizontal_Pink_Black.png#gh-light-mode-only) -![](https://cms.polkadot.network/content/images/2021/06/1-xPcVR_fkITd0ssKBvJ3GMw.png) +# Polkadot SDK -[![StackExchange](https://img.shields.io/badge/StackExchange-Community%20&%20Support-222222?logo=stackexchange)](https://substrate.stackexchange.com/) +![GitHub stars](https://img.shields.io/github/stars/paritytech/polkadot-sdk)  ![GitHub +forks](https://img.shields.io/github/forks/paritytech/polkadot-sdk) -The Polkadot SDK repository provides all the resources needed to start building on the Polkadot network, a multi-chain -blockchain platform that enables different blockchains to interoperate and share information in a secure and scalable -way. The Polkadot SDK comprises three main pieces of software: + +[![StackExchange](https://img.shields.io/badge/StackExchange-Community%20&%20Support-222222?logo=stackexchange)](https://substrate.stackexchange.com/)  ![GitHub contributors](https://img.shields.io/github/contributors/paritytech/polkadot-sdk)  ![GitHub commit activity](https://img.shields.io/github/commit-activity/m/paritytech/polkadot-sdk) -## [Polkadot](./polkadot/) -[![PolkadotForum](https://img.shields.io/badge/Polkadot_Forum-e6007a?logo=polkadot)](https://forum.polkadot.network/) -[![Polkadot-license](https://img.shields.io/badge/License-GPL3-blue)](./polkadot/LICENSE) +![GitHub lines of code](https://tokei.rs/b1/github/paritytech/polkadot-sdk)   +![GitHub last commit](https://img.shields.io/github/last-commit/paritytech/polkadot-sdk) -Implementation of a node for the https://polkadot.network in Rust, using the Substrate framework. This directory -currently contains runtimes for the Westend and Rococo test networks. Polkadot, Kusama and their system chain runtimes -are located in the [`runtimes`](https://github.com/polkadot-fellows/runtimes/) repository maintained by -[the Polkadot Technical Fellowship](https://polkadot-fellows.github.io/dashboard/#/overview). +> The Polkadot SDK repository provides all the components needed to start building on the +> [Polkadot](https://polkadot.network) network, a multi-chain blockchain platform that enables +> different blockchains to interoperate and share information in a secure and scalable way. -## [Substrate](./substrate/) - [![SubstrateRustDocs](https://img.shields.io/badge/Rust_Docs-Substrate-24CC85?logo=rust)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html) - [![Substrate-license](https://img.shields.io/badge/License-GPL3%2FApache2.0-blue)](./substrate/README.md#LICENSE) +
-Substrate is the primary blockchain SDK used by developers to create the parachains that make up the Polkadot network. -Additionally, it allows for the development of self-sovereign blockchains that operate completely independently of -Polkadot. +## 📚 Documentation -## [Cumulus](./cumulus/) -[![CumulusRustDocs](https://img.shields.io/badge/Rust_Docs-Cumulus-222222?logo=rust)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html) -[![Cumulus-license](https://img.shields.io/badge/License-GPL3-blue)](./cumulus/LICENSE) +* [🦀 rust-docs](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/index.html) + * [Introduction](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) + to each component of the Polkadot SDK: Substrate, FRAME, Cumulus, and XCM +* Other Resources: + * [Polkadot Wiki -> Build](https://wiki.polkadot.network/docs/build-guide) -Cumulus is a set of tools for writing Substrate-based Polkadot parachains. +## 🚀 Releases -## Releases +> [!NOTE] +> Our release process is still Work-In-Progress and may not yet reflect the aspired outline +> here. -> [!NOTE] -> Our release process is still Work-In-Progress and may not yet reflect the aspired outline here. +The Polkadot-SDK has two release channels: `stable` and `nightly`. Production software is advised to +only use `stable`. `nightly` is meant for tinkerers to try out the latest features. The detailed +release process is described in [RELEASE.md](docs/RELEASE.md). -The Polkadot-SDK has two release channels: `stable` and `nightly`. Production software is advised to only use `stable`. -`nightly` is meant for tinkerers to try out the latest features. The detailed release process is described in -[RELEASE.md](docs/RELEASE.md). +### 😌 Stable -### Stable +`stable` releases have a support duration of **three months**. In this period, the release will not +have any breaking changes. It will receive bug fixes, security fixes, performance fixes and new +non-breaking features on a **two week** cadence. -`stable` releases have a support duration of **three months**. In this period, the release will not have any breaking -changes. It will receive bug fixes, security fixes, performance fixes and new non-breaking features on a **two week** -cadence. +### 🤠 Nightly -### Nightly +`nightly` releases are released every night from the `master` branch, potentially with breaking +changes. They have pre-release version numbers in the format `major.0.0-nightlyYYMMDD`. -`nightly` releases are released every night from the `master` branch, potentially with breaking changes. They have -pre-release version numbers in the format `major.0.0-nightlyYYMMDD`. +## 🔐 Security -## Upstream Dependencies +The security policy and procedures can be found in +[docs/contributor/SECURITY.md](./docs/contributor/SECURITY.md). -Below are the primary upstream dependencies utilized in this project: +## 🤍 Contributing & Code of Conduct -- [`parity-scale-codec`](https://crates.io/crates/parity-scale-codec) -- [`parity-db`](https://crates.io/crates/parity-db) -- [`parity-common`](https://github.com/paritytech/parity-common) -- [`trie`](https://github.com/paritytech/trie) +Ensure you follow our [contribution guidelines](./docs/contributor/CONTRIBUTING.md). In every +interaction and contribution, this project adheres to the [Contributor Covenant Code of +Conduct](./docs/contributor/CODE_OF_CONDUCT.md). -## Security +### 👾 Ready to Contribute? -The security policy and procedures can be found in [docs/contributor/SECURITY.md](./docs/contributor/SECURITY.md). +Take a look at the issues labeled with [`mentor`](https://github.com/paritytech/polkadot-sdk/labels/C1-mentor) +(or alternatively [this](https://mentor.tasty.limo/) page, created by one of the maintainers) label to get started! +We always recognize valuable contributions by proposing an on-chain tip to the Polkadot network as a token of our +appreciation. -## Contributing & Code of Conduct +## Polkadot Fellowship -Ensure you follow our [contribution guidelines](./docs/contributor/CONTRIBUTING.md). In every interaction and -contribution, this project adheres to the [Contributor Covenant Code of Conduct](./docs/contributor/CODE_OF_CONDUCT.md). +Development in this repo usually goes hand in hand with the `fellowship` organization. In short, +this repository provides all the SDK pieces needed to build both Polkadot and its parachains. But, +the actual Polkadot runtime lives in the `fellowship/runtimes` repository. Read more about the +fellowship, this separation, the RFC process +[here](https://polkadot-fellows.github.io/dashboard/). -## Additional Resources +## History -- For monitoring upcoming changes and current proposals related to the technical implementation of the Polkadot network, - visit the [`Requests for Comment (RFC)`](https://github.com/polkadot-fellows/RFCs) repository. While it's maintained - by the Polkadot Fellowship, the RFC process welcomes contributions from everyone. +This repository is the amalgamation of 3 separate repositories that used to make up Polkadot SDK, +namely Substrate, Polkadot and Cumulus. Read more about the merge and its history +[here](https://polkadot-public.notion.site/Polkadot-SDK-FAQ-fbc4cecc2c46443fb37b9eeec2f0d85f). diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index 74049031afe63cf0d2bc95193541a2b1303a1bbf..783009a8c890768bcc85dafec14dc3da9e8da573 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/bin/runtime-common/src/messages_benchmarking.rs b/bridges/bin/runtime-common/src/messages_benchmarking.rs index 0c7a9ad1a83d6a83e0c9fe1f5e77ba2c4cefc17d..74494f7908045fac601b4c3f64a456ad12dacd6f 100644 --- a/bridges/bin/runtime-common/src/messages_benchmarking.rs +++ b/bridges/bin/runtime-common/src/messages_benchmarking.rs @@ -271,7 +271,7 @@ pub fn generate_xcm_builder_bridge_message_sample( move |expected_message_size| -> MessagePayload { // For XCM bridge hubs, it is the message that // will be pushed further to some XCM queue (XCMP/UMP) - let location = xcm::VersionedInteriorLocation::V4(destination.clone()); + let location = xcm::VersionedInteriorLocation::from(destination.clone()); let location_encoded_size = location.encoded_size(); // we don't need to be super-precise with `expected_size` here @@ -294,16 +294,13 @@ pub fn generate_xcm_builder_bridge_message_sample( expected_message_size, location_encoded_size, xcm_size, xcm_data_size, ); - let xcm = xcm::VersionedXcm::<()>::V4( - vec![Instruction::<()>::ExpectPallet { - index: 0, - name: vec![42; xcm_data_size], - module_name: vec![], - crate_major: 0, - min_crate_minor: 0, - }] - .into(), - ); + let xcm = xcm::VersionedXcm::<()>::from(Xcm(vec![Instruction::<()>::ExpectPallet { + index: 0, + name: vec![42; xcm_data_size], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }])); // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor // or public fields, so just tuple diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index e323f1edfc71da8c84fe8cabb977da85ce4d303e..f49474667896049cfd6aff4bf4a4b0d9d6e73c95 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -148,7 +148,6 @@ impl frame_system::Config for TestRuntime { type AccountId = ThisChainAccountId; type Block = ThisChainBlock; type AccountData = pallet_balances::AccountData; - type BlockHashCount = ConstU32<250>; } impl pallet_utility::Config for TestRuntime { diff --git a/bridges/chains/chain-asset-hub-rococo/Cargo.toml b/bridges/chains/chain-asset-hub-rococo/Cargo.toml index 9a6419a5b4055be348f4f8813e3c1301f14f7142..d9afe2c8bf76713104beead1ad4c36dc08dae1ed 100644 --- a/bridges/chains/chain-asset-hub-rococo/Cargo.toml +++ b/bridges/chains/chain-asset-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/bridges/chains/chain-asset-hub-westend/Cargo.toml b/bridges/chains/chain-asset-hub-westend/Cargo.toml index 1c08ee28e417cb50ce9ef9ded5f17163e1bb30d4..4b3ed052f1382d0c7f076ad5152c861f60d8bef1 100644 --- a/bridges/chains/chain-asset-hub-westend/Cargo.toml +++ b/bridges/chains/chain-asset-hub-westend/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/bridges/chains/chain-polkadot-bulletin/Cargo.toml b/bridges/chains/chain-polkadot-bulletin/Cargo.toml index 2db16a00e92492e3a167458343a88a24c2186748..700247b7055a891bec2d4a40bfd126720a0d952c 100644 --- a/bridges/chains/chain-polkadot-bulletin/Cargo.toml +++ b/bridges/chains/chain-polkadot-bulletin/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/bridges/docs/running-relayer.md b/bridges/docs/running-relayer.md index 710810a476e4df5e4b80fde31f9576be5ad26391..594cbc35a106b1ebd8cc1e9e9c0542c759489197 100644 --- a/bridges/docs/running-relayer.md +++ b/bridges/docs/running-relayer.md @@ -139,7 +139,7 @@ your transactions that are **validated** on top of block, where it is active get becomes expired when the block with the number you have specified during registration is "mined". It is the `validTill` parameter of the `register` call (see below). After that `validTill` block, you may unregister and get your reserved funds back. There's also an intermediate point between those blocks - it is the `validTill - LEASE`, -where `LEASE` is the the chain constant, controlled by the governance. Initially it is set to `300` blocks. +where `LEASE` is the chain constant, controlled by the governance. Initially it is set to `300` blocks. All your transactions, **validated** between the `validTill - LEASE` and `validTill` blocks do not get the priority boost. Also, it is forbidden to specify `validTill` such that the `validTill - currentBlock` is less than the `LEASE`. @@ -156,7 +156,7 @@ than the `LEASE`. | 700 | Inactive | Your message delivery transactions are not boosted | | 701 | Inactive | Your message delivery transactions are not boosted | | ... | Inactive | Your message delivery transactions are not boosted | -| 1000 | Expired | Your may submit a tx with the `deregister` call | +| 1000 | Expired | You may submit a tx with the `deregister` call | @@ -230,7 +230,7 @@ your relayer account. Then: - set the `bridgedChainId` to `bhpd`; -- check the both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions +- check both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions and `BridgedChain` is used to pay for message confirmation transactions. If check shows that you have some rewards, you can craft the claim transaction, with similar parameters. diff --git a/bridges/modules/beefy/Cargo.toml b/bridges/modules/beefy/Cargo.toml index 438f32fb146042f2704deb3092381a2b5cc68394..e36bbb615f23a20d4ef4a4f4ea8418e752d5b01f 100644 --- a/bridges/modules/beefy/Cargo.toml +++ b/bridges/modules/beefy/Cargo.toml @@ -12,7 +12,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true } diff --git a/bridges/modules/beefy/src/lib.rs b/bridges/modules/beefy/src/lib.rs index 27c83921021bb4299b18cbf2d3216427f8c89ccc..ccddcde920f694a87ab22042f44d84707982eefe 100644 --- a/bridges/modules/beefy/src/lib.rs +++ b/bridges/modules/beefy/src/lib.rs @@ -316,7 +316,7 @@ pub mod pallet { /// Pallet owner has the right to halt all pallet operations and then resume it. If it is /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. `democracy::referendum` to update halt - /// flag directly or calling `halt_operations`). + /// flag directly or calling `set_operating_mode`). #[pallet::storage] pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; diff --git a/bridges/modules/grandpa/Cargo.toml b/bridges/modules/grandpa/Cargo.toml index 0db1827211a05f715cd1aed0db93da0f52c9d67c..0ca6b67503511976ea9122f64e3c2e515e971177 100644 --- a/bridges/modules/grandpa/Cargo.toml +++ b/bridges/modules/grandpa/Cargo.toml @@ -13,7 +13,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/modules/grandpa/README.md b/bridges/modules/grandpa/README.md index 4a3099b8afc654bfced296aaa0ead4a5d113eb7f..df63f4aa639f21186932bde6b2a475b3873a6bf7 100644 --- a/bridges/modules/grandpa/README.md +++ b/bridges/modules/grandpa/README.md @@ -87,7 +87,7 @@ It'd be better for anyone (for chain and for submitters) to reject all transacti already known headers to the pallet. This way, we leave block space to other useful transactions and we don't charge concurrent submitters for their honest actions. -To deal with that, we have a [signed extension](./src/call_ext) that may be added to the runtime. +To deal with that, we have a [signed extension](./src/call_ext.rs) that may be added to the runtime. It does exactly what is required - rejects all transactions with already known headers. The submitter pays nothing for such transactions - they're simply removed from the transaction pool, when the block is built. diff --git a/bridges/modules/grandpa/src/benchmarking.rs b/bridges/modules/grandpa/src/benchmarking.rs index 11033373ce478fa9fefb613a1377449bb77daf1d..fb7354e05c06eeeab17363d5671cd8d636ec48f3 100644 --- a/bridges/modules/grandpa/src/benchmarking.rs +++ b/bridges/modules/grandpa/src/benchmarking.rs @@ -70,11 +70,12 @@ const MAX_VOTE_ANCESTRIES_RANGE_END: u32 = // the same with validators - if there are too much validators, let's run benchmarks on subrange fn precommits_range_end, I: 'static>() -> u32 { let max_bridged_authorities = T::BridgedChain::MAX_AUTHORITIES_COUNT; - if max_bridged_authorities > 128 { + let max_bridged_authorities = if max_bridged_authorities > 128 { sp_std::cmp::max(128, max_bridged_authorities / 5) } else { max_bridged_authorities }; + required_justification_precommits(max_bridged_authorities) } @@ -138,5 +139,19 @@ benchmarks_instance_pallet! { assert!(!>::contains_key(genesis_header.hash())); } + force_set_pallet_state { + let set_id = 100; + let authorities = accounts(T::BridgedChain::MAX_AUTHORITIES_COUNT as u16) + .iter() + .map(|id| (AuthorityId::from(*id), 1)) + .collect::>(); + let (header, _) = prepare_benchmark_data::(1, 1); + let expected_hash = header.hash(); + }: force_set_pallet_state(RawOrigin::Root, set_id, authorities, Box::new(header)) + verify { + assert_eq!(>::get().unwrap().1, expected_hash); + assert_eq!(>::get().set_id, set_id); + } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/bridges/modules/grandpa/src/call_ext.rs b/bridges/modules/grandpa/src/call_ext.rs index 6fa62ec0cff498e9c33cf3a1ccf7bc76c7b7279e..f08eb4c5d1ab5ae231afc388dacb0699d58fbc46 100644 --- a/bridges/modules/grandpa/src/call_ext.rs +++ b/bridges/modules/grandpa/src/call_ext.rs @@ -18,12 +18,8 @@ use crate::{ weights::WeightInfo, BestFinalized, BridgedBlockNumber, BridgedHeader, Config, CurrentAuthoritySet, Error, FreeHeadersRemaining, Pallet, }; -use bp_header_chain::{ - justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size, - ChainWithGrandpa, GrandpaConsensusLogReader, -}; +use bp_header_chain::{justification::GrandpaJustification, submit_finality_proof_limits_extras}; use bp_runtime::{BlockNumberOf, Chain, OwnedBridgeModule}; -use codec::Encode; use frame_support::{ dispatch::CallableCallFor, traits::{Get, IsSubType}, @@ -148,8 +144,13 @@ impl, I: 'static> SubmitFinalityProofHelper { } } - // we do not check whether the header matches free submission criteria here - it is the - // relayer responsibility to check that + // let's also check whether the header submission fits the hardcoded limits. A normal + // relayer would check that before submitting a transaction (since limits are constants + // and do not depend on a volatile runtime state), but the ckeck itself is cheap, so + // let's do it here too + if !call_info.fits_limits() { + return Err(Error::::HeaderOverflowLimits); + } Ok(improved_by) } @@ -298,53 +299,31 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( current_set_id: Option, is_free_execution_expected: bool, ) -> SubmitFinalityProofInfo> { - let block_number = *finality_target.number(); - - // the `submit_finality_proof` call will reject justifications with invalid, duplicate, - // unknown and extra signatures. It'll also reject justifications with less than necessary - // signatures. So we do not care about extra weight because of additional signatures here. - let precommits_len = justification.commit.precommits.len().saturated_into(); - let required_precommits = precommits_len; + // check if call exceeds limits. In other words - whether some size or weight is included + // in the call + let extras = + submit_finality_proof_limits_extras::(finality_target, justification); // We do care about extra weight because of more-than-expected headers in the votes // ancestries. But we have problems computing extra weight for additional headers (weight of // additional header is too small, so that our benchmarks aren't detecting that). So if there // are more than expected headers in votes ancestries, we will treat the whole call weight // as an extra weight. - let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); - let extra_weight = - if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY { - T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) - } else { - Weight::zero() - }; - - // check if the `finality_target` is a mandatory header. If so, we are ready to refund larger - // size - let is_mandatory_finality_target = - GrandpaConsensusLogReader::>::find_scheduled_change( - finality_target.digest(), - ) - .is_some(); - - // we can estimate extra call size easily, without any additional significant overhead - let actual_call_size: u32 = finality_target - .encoded_size() - .saturating_add(justification.encoded_size()) - .saturated_into(); - let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::( - is_mandatory_finality_target, - required_precommits, - ); - let extra_size = actual_call_size.saturating_sub(max_expected_call_size); + let extra_weight = if extras.is_weight_limit_exceeded { + let precommits_len = justification.commit.precommits.len().saturated_into(); + let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); + T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) + } else { + Weight::zero() + }; SubmitFinalityProofInfo { - block_number, + block_number: *finality_target.number(), current_set_id, - is_mandatory: is_mandatory_finality_target, + is_mandatory: extras.is_mandatory_finality_target, is_free_execution_expected, extra_weight, - extra_size, + extra_size: extras.extra_size, } } @@ -468,6 +447,64 @@ mod tests { }) } + #[test] + fn extension_rejects_new_header_if_it_overflow_size_limits() { + run_test(|| { + let mut large_finality_target = test_header(10 + FreeHeadersInterval::get() as u64); + large_finality_target + .digest_mut() + .push(DigestItem::Other(vec![42u8; 1024 * 1024])); + let justification_params = JustificationGeneratorParams { + header: large_finality_target.clone(), + ..Default::default() + }; + let large_justification = make_justification_for_header(justification_params); + + let bridge_grandpa_call = crate::Call::::submit_finality_proof_ex { + finality_target: Box::new(large_finality_target), + justification: large_justification, + current_set_id: 0, + is_free_execution_expected: true, + }; + sync_to_header_10(); + + // if overflow size limits => Err + FreeHeadersRemaining::::put(2); + assert!(RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa( + bridge_grandpa_call.clone(), + ),) + .is_err()); + }) + } + + #[test] + fn extension_rejects_new_header_if_it_overflow_weight_limits() { + run_test(|| { + let finality_target = test_header(10 + FreeHeadersInterval::get() as u64); + let justification_params = JustificationGeneratorParams { + header: finality_target.clone(), + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY, + ..Default::default() + }; + let justification = make_justification_for_header(justification_params); + + let bridge_grandpa_call = crate::Call::::submit_finality_proof_ex { + finality_target: Box::new(finality_target), + justification, + current_set_id: 0, + is_free_execution_expected: true, + }; + sync_to_header_10(); + + // if overflow weight limits => Err + FreeHeadersRemaining::::put(2); + assert!(RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa( + bridge_grandpa_call.clone(), + ),) + .is_err()); + }) + } + #[test] fn extension_rejects_new_header_if_free_execution_is_requested_and_improved_by_is_below_expected( ) { diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index efcbfb1654b34e08e07d3bda4e32ee587a0ba51c..3b77f676870e1a28b8367f1b14d24c9ca83ece4a 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -44,7 +44,7 @@ use bp_header_chain::{ }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use frame_support::{dispatch::PostDispatchInfo, ensure, DefaultNoBound}; -use sp_consensus_grandpa::SetId; +use sp_consensus_grandpa::{AuthorityList, SetId}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, @@ -360,6 +360,42 @@ pub mod pallet { Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } + + /// Set current authorities set and best finalized bridged header to given values + /// (almost) without any checks. This call can fail only if: + /// + /// - the call origin is not a root or a pallet owner; + /// + /// - there are too many authorities in the new set. + /// + /// No other checks are made. Previously imported headers stay in the storage and + /// are still accessible after the call. + #[pallet::call_index(5)] + #[pallet::weight(T::WeightInfo::force_set_pallet_state())] + pub fn force_set_pallet_state( + origin: OriginFor, + new_current_set_id: SetId, + new_authorities: AuthorityList, + new_best_header: Box>, + ) -> DispatchResult { + Self::ensure_owner_or_root(origin)?; + + // save new authorities set. It only fails if there are too many authorities + // in the new set + save_authorities_set::( + CurrentAuthoritySet::::get().set_id, + new_current_set_id, + new_authorities, + )?; + + // save new best header. It may be older than the best header that is already + // known to the pallet - it changes nothing (except for the fact that previously + // imported headers may still be used to prove something) + let new_best_header_hash = new_best_header.hash(); + insert_header::(*new_best_header, new_best_header_hash); + + Ok(()) + } } /// Number of free header submissions that we may yet accept in the current block. @@ -423,7 +459,7 @@ pub mod pallet { /// Pallet owner has a right to halt all pallet operations and then resume it. If it is /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt - /// flag directly or call the `halt_operations`). + /// flag directly or call the `set_operating_mode`). #[pallet::storage] pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; @@ -504,6 +540,9 @@ pub mod pallet { /// The submitter wanted free execution, but the difference between best known and /// bundled header numbers is below the `FreeHeadersInterval`. BelowFreeHeaderInterval, + /// The header (and its finality) submission overflows hardcoded chain limits: size + /// and/or weight are larger than expected. + HeaderOverflowLimits, } /// Called when new free header is imported. @@ -589,33 +628,45 @@ pub mod pallet { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); - // TODO [#788]: Stop manually increasing the `set_id` here. - let next_authorities = StoredAuthoritySet:: { - authorities: change - .next_authorities - .try_into() - .map_err(|_| Error::::TooManyAuthoritiesInSet)?, - set_id: current_set_id + 1, - }; - // Since our header schedules a change and we know the delay is 0, it must also enact // the change. - >::put(&next_authorities); - - log::info!( - target: LOG_TARGET, - "Transitioned from authority set {} to {}! New authorities are: {:?}", + // TODO [#788]: Stop manually increasing the `set_id` here. + return save_authorities_set::( current_set_id, current_set_id + 1, - next_authorities, + change.next_authorities, ); - - return Ok(Some(next_authorities.into())) }; Ok(None) } + /// Save new authorities set. + pub(crate) fn save_authorities_set, I: 'static>( + old_current_set_id: SetId, + new_current_set_id: SetId, + new_authorities: AuthorityList, + ) -> Result, DispatchError> { + let next_authorities = StoredAuthoritySet:: { + authorities: new_authorities + .try_into() + .map_err(|_| Error::::TooManyAuthoritiesInSet)?, + set_id: new_current_set_id, + }; + + >::put(&next_authorities); + + log::info!( + target: LOG_TARGET, + "Transitioned from authority set {} to {}! New authorities are: {:?}", + old_current_set_id, + new_current_set_id, + next_authorities, + ); + + Ok(Some(next_authorities.into())) + } + /// Verify a GRANDPA justification (finality proof) for a given header. /// /// Will use the GRANDPA current authorities known to the pallet. @@ -1697,4 +1748,98 @@ mod tests { assert_eq!(FreeHeadersRemaining::::get(), Some(0)); }) } + + #[test] + fn force_set_pallet_state_works() { + run_test(|| { + let header25 = test_header(25); + let header50 = test_header(50); + let ok_new_set_id = 100; + let ok_new_authorities = authority_list(); + let bad_new_set_id = 100; + let bad_new_authorities: Vec<_> = std::iter::repeat((ALICE.into(), 1)) + .take(MAX_BRIDGED_AUTHORITIES as usize + 1) + .collect(); + + // initialize and import several headers + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof(30)); + + // wrong origin => error + assert_noop!( + Pallet::::force_set_pallet_state( + RuntimeOrigin::signed(1), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header50.clone()), + ), + DispatchError::BadOrigin, + ); + + // too many authorities in the set => error + assert_noop!( + Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + bad_new_set_id, + bad_new_authorities.clone(), + Box::new(header50.clone()), + ), + Error::::TooManyAuthoritiesInSet, + ); + + // force import header 50 => ok + assert_ok!(Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header50.clone()), + ),); + + // force import header 25 after 50 => ok + assert_ok!(Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header25.clone()), + ),); + + // we may import better headers + assert_noop!(submit_finality_proof(20), Error::::OldHeader); + assert_ok!(submit_finality_proof_with_set_id(26, ok_new_set_id)); + + // we can even reimport header #50. It **will cause** some issues during pruning + // (see below) + assert_ok!(submit_finality_proof_with_set_id(50, ok_new_set_id)); + + // and all headers are available. Even though there are 4 headers, the ring + // buffer thinks that there are 5, because we've imported header $50 twice + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(30).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(50).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(25).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(26).hash() + ) + .is_some()); + + // next header import will prune header 30 + assert_ok!(submit_finality_proof_with_set_id(70, ok_new_set_id)); + // next header import will prune header 50 + assert_ok!(submit_finality_proof_with_set_id(80, ok_new_set_id)); + // next header import will prune header 25 + assert_ok!(submit_finality_proof_with_set_id(90, ok_new_set_id)); + // next header import will prune header 26 + assert_ok!(submit_finality_proof_with_set_id(100, ok_new_set_id)); + // next header import will prune header 50 again. But it is fine + assert_ok!(submit_finality_proof_with_set_id(110, ok_new_set_id)); + }); + } } diff --git a/bridges/modules/grandpa/src/weights.rs b/bridges/modules/grandpa/src/weights.rs index a75e7b5a8e4ada8ce880a040492c904d8035642c..9719bc9c022e2f082307ddf49fc02eb70f4c3497 100644 --- a/bridges/modules/grandpa/src/weights.rs +++ b/bridges/modules/grandpa/src/weights.rs @@ -51,6 +51,7 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_bridge_grandpa. pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; + fn force_set_pallet_state() -> Weight; } /// Weights for `pallet_bridge_grandpa` that are generated using one of the Bridge testnets. @@ -109,6 +110,30 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } + + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: + /// Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: + /// Some(4), added: 499, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHashes` + /// (r:1 w:1) Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), + /// `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), + /// added: 531, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 + /// w:2) Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: + /// Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 62_232_000 picoseconds. + Weight::from_parts(78_755_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(6)) + } } // For backwards compatibility and tests @@ -164,4 +189,28 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } + + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: + /// Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: + /// Some(4), added: 499, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHashes` + /// (r:1 w:1) Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), + /// `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), + /// added: 531, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 + /// w:2) Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: + /// Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 62_232_000 picoseconds. + Weight::from_parts(78_755_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(6)) + } } diff --git a/bridges/modules/messages/Cargo.toml b/bridges/modules/messages/Cargo.toml index df5b92db7402bd048b1afca9c13cfb1dddc74863..71c86ccc0361708684d0a93166f858118dbf0d92 100644 --- a/bridges/modules/messages/Cargo.toml +++ b/bridges/modules/messages/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/modules/messages/README.md b/bridges/modules/messages/README.md index fe62305748cd1d6030a7a8085bff29f24ee4dbc5..c06b96b857dea1cdf7fdaed81e70d66aff116064 100644 --- a/bridges/modules/messages/README.md +++ b/bridges/modules/messages/README.md @@ -187,11 +187,13 @@ There may be a special account in every runtime where the messages module is dep owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring runtime upgrade. Calls that are related to this account are: - `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; -- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all module operations. After - this call, all message-related transactions will be rejected until further `resume_operations` call'. This call may be - used when something extraordinary happens with the bridge; -- `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its - regular operations after this call. +- `fn set_operating_mode()`: the module owner (or sudo account) may call this function to pause/resume + pallet operations. Owner may halt the pallet by calling this method with + `MessagesOperatingMode::Basic(BasicOperatingMode::Halted)` argument - all message-related + transactions will be rejected. Owner may then resume pallet operations by passing the + `MessagesOperatingMode::Basic(BasicOperatingMode::Normal)` argument. There's also + `MessagesOperatingMode::RejectingOutboundMessages` pallet mode, where it still accepts all incoming + messages, but all outbound messages are rejected. If pallet owner is not defined, the governance may be used to make those calls. diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index bc00db9eba5ba12dbdaa0de7008f293a727a7ef5..e31a4542056cb30466f236d0dc9957c053a03f66 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -573,7 +573,7 @@ pub mod pallet { /// Pallet owner has a right to halt all pallet operations and then resume it. If it is /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt - /// flag directly or call the `halt_operations`). + /// flag directly or call the `set_operating_mode`). #[pallet::storage] #[pallet::getter(fn module_owner)] pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId>; diff --git a/bridges/modules/parachains/Cargo.toml b/bridges/modules/parachains/Cargo.toml index 35213be0674a8c8d31de79afb720fbf457f3445a..d3152f8d0a4aa9b6dc1c726441c5e139e08de162 100644 --- a/bridges/modules/parachains/Cargo.toml +++ b/bridges/modules/parachains/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/modules/parachains/src/lib.rs b/bridges/modules/parachains/src/lib.rs index 61e04aed3770dcaa9cb611dc754aad21325e1b39..d323aef3b22070d1db1e4709fe0dad8bf0360caf 100644 --- a/bridges/modules/parachains/src/lib.rs +++ b/bridges/modules/parachains/src/lib.rs @@ -260,7 +260,7 @@ pub mod pallet { /// Pallet owner has a right to halt all pallet operations and then resume them. If it is /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt - /// flag directly or call the `halt_operations`). + /// flag directly or call the `set_operating_mode`). #[pallet::storage] pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml index e2b7aca92249c19096bf129be6fab1be08a5357a..08e1438d4f1946fb41f614b0e94c0ce6f1611fd5 100644 --- a/bridges/modules/relayers/Cargo.toml +++ b/bridges/modules/relayers/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/modules/xcm-bridge-hub-router/Cargo.toml b/bridges/modules/xcm-bridge-hub-router/Cargo.toml index 06f2a339bed9d07b5615ca047177228d6585cfc2..b80240c974de9f5874e2825f5506885fea11ef3a 100644 --- a/bridges/modules/xcm-bridge-hub-router/Cargo.toml +++ b/bridges/modules/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive", "serde"] } diff --git a/bridges/modules/xcm-bridge-hub-router/src/lib.rs b/bridges/modules/xcm-bridge-hub-router/src/lib.rs index ece72ac8494b763035b7ebfead71e3e280bf4b5c..607394603466e6cb60d20dbefa4aa47580b54c42 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/lib.rs @@ -37,8 +37,9 @@ use codec::Encode; use frame_support::traits::Get; use sp_core::H256; use sp_runtime::{FixedPointNumber, FixedU128, Saturating}; +use sp_std::vec::Vec; use xcm::prelude::*; -use xcm_builder::{ExporterFor, SovereignPaidRemoteExporter}; +use xcm_builder::{ExporterFor, InspectMessageQueues, SovereignPaidRemoteExporter}; pub use pallet::*; pub use weights::WeightInfo; @@ -95,7 +96,7 @@ pub mod pallet { /// Origin of the sibling bridge hub that is allowed to report bridge status. type BridgeHubOrigin: EnsureOrigin; /// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location. - type ToBridgeHubSender: SendXcm; + type ToBridgeHubSender: SendXcm + InspectMessageQueues; /// Underlying channel with the sibling bridge hub. It must match the channel, used /// by the `Self::ToBridgeHubSender`. type WithBridgeHubChannel: XcmChannelStatusProvider; @@ -396,6 +397,12 @@ impl, I: 'static> SendXcm for Pallet { } } +impl, I: 'static> InspectMessageQueues for Pallet { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + ViaBridgeHubExporter::::get_messages() + } +} + #[cfg(test)] mod tests { use super::*; @@ -635,4 +642,36 @@ mod tests { ); }); } + + #[test] + fn get_messages_works() { + run_test(|| { + assert_ok!(send_xcm::( + (Parent, Parent, GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)).into(), + vec![ClearOrigin].into() + )); + assert_eq!( + XcmBridgeHubRouter::get_messages(), + vec![( + VersionedLocation::V4((Parent, Parachain(1002)).into()), + vec![VersionedXcm::V4( + Xcm::builder() + .withdraw_asset((Parent, 1_002_000)) + .buy_execution((Parent, 1_002_000), Unlimited) + .set_appendix( + Xcm::builder_unsafe() + .deposit_asset(AllCounted(1), (Parent, Parachain(1000))) + .build() + ) + .export_message( + Kusama, + Parachain(1000), + Xcm::builder_unsafe().clear_origin().build() + ) + .build() + )], + ),], + ); + }); + } } diff --git a/bridges/modules/xcm-bridge-hub-router/src/mock.rs b/bridges/modules/xcm-bridge-hub-router/src/mock.rs index 20c86d1da9a2e315c9465b7e8fe0633401a3a3d4..3e2c1bb369cb72439e53e492cf638a404caa99a3 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/mock.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/mock.rs @@ -19,14 +19,16 @@ use crate as pallet_xcm_bridge_hub_router; use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; +use codec::Encode; use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{Contains, Equals}, }; use frame_system::EnsureRoot; use sp_runtime::{traits::ConstU128, BuildStorage}; +use sp_std::cell::RefCell; use xcm::prelude::*; -use xcm_builder::{NetworkExportTable, NetworkExportTableItem}; +use xcm_builder::{InspectMessageQueues, NetworkExportTable, NetworkExportTableItem}; pub type AccountId = u64; type Block = frame_system::mocking::MockBlock; @@ -102,23 +104,46 @@ pub struct TestToBridgeHubSender; impl TestToBridgeHubSender { pub fn is_message_sent() -> bool { - frame_support::storage::unhashed::get_or_default(b"TestToBridgeHubSender.Sent") + !Self::get_messages().is_empty() } } +thread_local! { + pub static SENT_XCM: RefCell)>> = RefCell::new(Vec::new()); +} + impl SendXcm for TestToBridgeHubSender { - type Ticket = (); + type Ticket = (Location, Xcm<()>); fn validate( - _destination: &mut Option, - _message: &mut Option>, + destination: &mut Option, + message: &mut Option>, ) -> SendResult { - Ok(((), (BridgeFeeAsset::get(), HRMP_FEE).into())) + let pair = (destination.take().unwrap(), message.take().unwrap()); + Ok((pair, (BridgeFeeAsset::get(), HRMP_FEE).into())) } - fn deliver(_ticket: Self::Ticket) -> Result { - frame_support::storage::unhashed::put(b"TestToBridgeHubSender.Sent", &true); - Ok([0u8; 32]) + fn deliver(pair: Self::Ticket) -> Result { + let hash = fake_message_hash(&pair.1); + SENT_XCM.with(|q| q.borrow_mut().push(pair)); + Ok(hash) + } +} + +impl InspectMessageQueues for TestToBridgeHubSender { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + SENT_XCM.with(|q| { + (*q.borrow()) + .clone() + .iter() + .map(|(location, message)| { + ( + VersionedLocation::V4(location.clone()), + vec![VersionedXcm::V4(message.clone())], + ) + }) + .collect() + }) } } @@ -146,3 +171,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { pub fn run_test(test: impl FnOnce() -> T) -> T { new_test_ext().execute_with(test) } + +pub(crate) fn fake_message_hash(message: &Xcm) -> XcmHash { + message.using_encoded(sp_io::hashing::blake2_256) +} diff --git a/bridges/modules/xcm-bridge-hub/Cargo.toml b/bridges/modules/xcm-bridge-hub/Cargo.toml index 4483a3790900f975030e8c820f9b42442a747262..9b22770061a9a9ffd981f186de9231d7ff41cde9 100644 --- a/bridges/modules/xcm-bridge-hub/Cargo.toml +++ b/bridges/modules/xcm-bridge-hub/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/primitives/beefy/Cargo.toml b/bridges/primitives/beefy/Cargo.toml index 2a13685207cc633fe18633525231866511afd01e..bd68076ca48fc8ccc7bb8f48611083c0930731f7 100644 --- a/bridges/primitives/beefy/Cargo.toml +++ b/bridges/primitives/beefy/Cargo.toml @@ -12,7 +12,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { default-features = false, features = ["alloc", "derive"], workspace = true } diff --git a/bridges/primitives/beefy/src/lib.rs b/bridges/primitives/beefy/src/lib.rs index 0441781e79a66f785b985047ad56da70c0f13d49..2494706818ef14c11a8193983164e65a510a80e6 100644 --- a/bridges/primitives/beefy/src/lib.rs +++ b/bridges/primitives/beefy/src/lib.rs @@ -22,7 +22,7 @@ pub use binary_merkle_tree::merkle_root; pub use pallet_beefy_mmr::BeefyEcdsaToEthereum; pub use pallet_mmr::{ - primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, + primitives::{DataOrHash as MmrDataOrHash, LeafProof as MmrProof}, verify_leaves_proof as verify_mmr_leaves_proof, }; pub use sp_consensus_beefy::{ diff --git a/bridges/primitives/header-chain/Cargo.toml b/bridges/primitives/header-chain/Cargo.toml index f7a61a9ff32bd42f4199859834b6296aeaa18f4a..def1f7ad4dfefb14c3f8459a3d2960c3890ddcf8 100644 --- a/bridges/primitives/header-chain/Cargo.toml +++ b/bridges/primitives/header-chain/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index ad496012c6a3f95d636a2c1ae52fcb5f4ec5434d..af2afb65a26a7f206fdbfcf22e20cb5100a8c95f 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -24,8 +24,8 @@ use crate::justification::{ GrandpaJustification, JustificationVerificationContext, JustificationVerificationError, }; use bp_runtime::{ - BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, - StorageProofError, UnderlyingChainProvider, + BasicOperatingMode, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, + StorageProofChecker, StorageProofError, UnderlyingChainProvider, }; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; @@ -35,7 +35,7 @@ use serde::{Deserialize, Serialize}; use sp_consensus_grandpa::{ AuthorityList, ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID, }; -use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; +use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug, SaturatedConversion}; use sp_std::{boxed::Box, vec::Vec}; pub mod justification; @@ -325,6 +325,68 @@ where const AVERAGE_HEADER_SIZE: u32 = ::AVERAGE_HEADER_SIZE; } +/// Result of checking maximal expected submit finality proof call weight and size. +#[derive(Debug)] +pub struct SubmitFinalityProofCallExtras { + /// If true, the call weight is larger than what we have assumed. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for weight above that limit, is never refunded. + pub is_weight_limit_exceeded: bool, + /// Extra size (in bytes) that we assume are included in the call. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for bytes above that limit, is never refunded. + pub extra_size: u32, + /// A flag that is true if the header is the mandatory header that enacts new + /// authorities set. + pub is_mandatory_finality_target: bool, +} + +/// Checks whether the given `header` and its finality `proof` fit the maximal expected +/// call limits (size and weight). The submission may be refunded sometimes (see pallet +/// configuration for details), but it should fit some limits. If the call has some extra +/// weight and/or size included, though, we won't refund it or refund will be partial. +pub fn submit_finality_proof_limits_extras( + header: &C::Header, + proof: &justification::GrandpaJustification, +) -> SubmitFinalityProofCallExtras { + // the `submit_finality_proof` call will reject justifications with invalid, duplicate, + // unknown and extra signatures. It'll also reject justifications with less than necessary + // signatures. So we do not care about extra weight because of additional signatures here. + let precommits_len = proof.commit.precommits.len().saturated_into(); + let required_precommits = precommits_len; + + // the weight check is simple - we assume that there are no more than the `limit` + // headers in the ancestry proof + let votes_ancestries_len: u32 = proof.votes_ancestries.len().saturated_into(); + let is_weight_limit_exceeded = + votes_ancestries_len > C::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; + + // check if the `finality_target` is a mandatory header. If so, we are ready to refund larger + // size + let is_mandatory_finality_target = + GrandpaConsensusLogReader::>::find_scheduled_change(header.digest()) + .is_some(); + + // we can estimate extra call size easily, without any additional significant overhead + let actual_call_size: u32 = + header.encoded_size().saturating_add(proof.encoded_size()).saturated_into(); + let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::( + is_mandatory_finality_target, + required_precommits, + ); + let extra_size = actual_call_size.saturating_sub(max_expected_call_size); + + SubmitFinalityProofCallExtras { + is_weight_limit_exceeded, + extra_size, + is_mandatory_finality_target, + } +} + /// Returns maximal expected size of `submit_finality_proof` call arguments. pub fn max_expected_submit_finality_proof_arguments_size( is_mandatory_finality_target: bool, diff --git a/bridges/primitives/messages/Cargo.toml b/bridges/primitives/messages/Cargo.toml index d41acfb9d32863d14e56e095755791a420fd3ce6..20337873c2e6abac5872807adf67557be60a46e8 100644 --- a/bridges/primitives/messages/Cargo.toml +++ b/bridges/primitives/messages/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { features = ["alloc", "derive"], workspace = true } diff --git a/bridges/primitives/parachains/Cargo.toml b/bridges/primitives/parachains/Cargo.toml index 2e7000b86a5e4ba21ccadf74b1c2d5374db5c545..a6e71876cefbb3963ef1923469d641281cda00dc 100644 --- a/bridges/primitives/parachains/Cargo.toml +++ b/bridges/primitives/parachains/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/bridges/primitives/polkadot-core/Cargo.toml b/bridges/primitives/polkadot-core/Cargo.toml index 53b1e574cb1997e556f17b7f21f6a28d9eb84400..d4b2f503e9e2ca92c095649f8aa36741d02c8037 100644 --- a/bridges/primitives/polkadot-core/Cargo.toml +++ b/bridges/primitives/polkadot-core/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } diff --git a/bridges/primitives/relayers/Cargo.toml b/bridges/primitives/relayers/Cargo.toml index 1be7f1dc6ebd38061e98865b45d4f85d8f3f7448..5081dddce1e61eccbae540f665257e122d777dd6 100644 --- a/bridges/primitives/relayers/Cargo.toml +++ b/bridges/primitives/relayers/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/bridges/primitives/runtime/Cargo.toml b/bridges/primitives/runtime/Cargo.toml index 9a9b0291687d19ac0b5698ce3ef6a591da9f86c9..ac65ad538b4988c71e59d081cba46d47ebdc7c39 100644 --- a/bridges/primitives/runtime/Cargo.toml +++ b/bridges/primitives/runtime/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } diff --git a/bridges/primitives/test-utils/Cargo.toml b/bridges/primitives/test-utils/Cargo.toml index d314c38683cdbc8b40cfda3a14c64f91854e5d7f..99f5ee0d1aee4528f64028bbb4ce089cfb6f4c44 100644 --- a/bridges/primitives/test-utils/Cargo.toml +++ b/bridges/primitives/test-utils/Cargo.toml @@ -15,7 +15,7 @@ bp-header-chain = { path = "../header-chain", default-features = false } bp-parachains = { path = "../parachains", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } ed25519-dalek = { version = "2.1", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { path = "../../../substrate/primitives/application-crypto", default-features = false } diff --git a/bridges/primitives/xcm-bridge-hub-router/Cargo.toml b/bridges/primitives/xcm-bridge-hub-router/Cargo.toml index 94eece16d5797eb23dd12af5b8b5aeb7d283d862..b94e722024562e526c33d2bf1efe9b89f1a035aa 100644 --- a/bridges/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/bridges/primitives/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies diff --git a/bridges/relays/client-substrate/Cargo.toml b/bridges/relays/client-substrate/Cargo.toml index 2c98441fc3017e8bcd4a213b27d5f5d2fee3223d..cb7eae4f340c7375ad69b111f6b561c84bc57144 100644 --- a/bridges/relays/client-substrate/Cargo.toml +++ b/bridges/relays/client-substrate/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] async-std = { version = "1.9.0", features = ["attributes"] } async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" jsonrpsee = { version = "0.22", features = ["macros", "ws-client"] } log = { workspace = true } diff --git a/bridges/relays/client-substrate/src/client.rs b/bridges/relays/client-substrate/src/client.rs index afbda8599b2aa03c4ed4a7c33a93fdd429646516..2e7cb7455f76cceee1c63aae4efb4a5cfe9f2a69 100644 --- a/bridges/relays/client-substrate/src/client.rs +++ b/bridges/relays/client-substrate/src/client.rs @@ -77,7 +77,12 @@ pub fn is_ancient_block + PartialOrd + Saturating>(block: N, best: } /// Opaque justifications subscription type. -pub struct Subscription(pub(crate) Mutex>>); +pub struct Subscription( + pub(crate) Mutex>>, + // The following field is not explicitly used by the code. But when it is dropped, + // the bakground task receives a shutdown signal. + #[allow(dead_code)] pub(crate) futures::channel::oneshot::Sender<()>, +); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -621,6 +626,7 @@ impl Client { e })??; + let (cancel_sender, cancel_receiver) = futures::channel::oneshot::channel(); let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); let (tracker, subscription) = self .jsonrpsee_execute(move |client| async move { @@ -639,7 +645,7 @@ impl Client { self_clone, stall_timeout, tx_hash, - Subscription(Mutex::new(receiver)), + Subscription(Mutex::new(receiver), cancel_sender), ); Ok((tracker, subscription)) }) @@ -649,6 +655,7 @@ impl Client { "extrinsic".into(), subscription, sender, + cancel_receiver, )); Ok(tracker) } @@ -790,14 +797,16 @@ impl Client { Ok(FC::subscribe_justifications(&client).await?) }) .await?; + let (cancel_sender, cancel_receiver) = futures::channel::oneshot::channel(); let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); self.data.read().await.tokio.spawn(Subscription::background_worker( C::NAME.into(), "justification".into(), subscription, sender, + cancel_receiver, )); - Ok(Subscription(Mutex::new(receiver))) + Ok(Subscription(Mutex::new(receiver), cancel_sender)) } /// Generates a proof of key ownership for the given authority in the given set. @@ -843,9 +852,17 @@ impl Client { impl Subscription { /// Consumes subscription and returns future statuses stream. pub fn into_stream(self) -> impl futures::Stream { - futures::stream::unfold(self, |this| async { + futures::stream::unfold(Some(self), |mut this| async move { + let Some(this) = this.take() else { return None }; let item = this.0.lock().await.next().await.unwrap_or(None); - item.map(|i| (i, this)) + match item { + Some(item) => Some((item, Some(this))), + None => { + // let's make it explicit here + let _ = this.1.send(()); + None + }, + } }) } @@ -860,19 +877,35 @@ impl Subscription { async fn background_worker( chain_name: String, item_type: String, - mut subscription: jsonrpsee::core::client::Subscription, + subscription: jsonrpsee::core::client::Subscription, mut sender: futures::channel::mpsc::Sender>, + cancel_receiver: futures::channel::oneshot::Receiver<()>, ) { + log::trace!( + target: "bridge", + "Starting background worker for {} {} subscription stream.", + chain_name, + item_type, + ); + + futures::pin_mut!(subscription, cancel_receiver); loop { - match subscription.next().await { - Some(Ok(item)) => + match futures::future::select(subscription.next(), &mut cancel_receiver).await { + futures::future::Either::Left((Some(Ok(item)), _)) => if sender.send(Some(item)).await.is_err() { + log::trace!( + target: "bridge", + "{} {} subscription stream: no listener. Stopping background worker.", + chain_name, + item_type, + ); + break }, - Some(Err(e)) => { + futures::future::Either::Left((Some(Err(e)), _)) => { log::trace!( target: "bridge", - "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", + "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted. Stopping background worker.", chain_name, item_type, e, @@ -880,16 +913,25 @@ impl Subscription { let _ = sender.send(None).await; break }, - None => { + futures::future::Either::Left((None, _)) => { log::trace!( target: "bridge", - "{} {} subscription stream has returned None. Stream needs to be restarted.", + "{} {} subscription stream has returned None. Stream needs to be restarted. Stopping background worker.", chain_name, item_type, ); let _ = sender.send(None).await; break }, + futures::future::Either::Right((_, _)) => { + log::trace!( + target: "bridge", + "{} {} subscription stream: listener has been dropped. Stopping background worker.", + chain_name, + item_type, + ); + break; + }, } } } diff --git a/bridges/relays/client-substrate/src/error.rs b/bridges/relays/client-substrate/src/error.rs index 0b446681818879d662ba9a71679a799519cf491b..2133c18887846b4f4360bdb6baa34799a24e6164 100644 --- a/bridges/relays/client-substrate/src/error.rs +++ b/bridges/relays/client-substrate/src/error.rs @@ -17,6 +17,7 @@ //! Substrate node RPC errors. use crate::SimpleRuntimeVersion; +use bp_header_chain::SubmitFinalityProofCallExtras; use bp_polkadot_core::parachains::ParaId; use jsonrpsee::core::ClientError as RpcError; use relay_utils::MaybeConnectionError; @@ -129,6 +130,12 @@ pub enum Error { /// Actual runtime version. actual: SimpleRuntimeVersion, }, + /// Finality proof submission exceeds size and/or weight limits. + #[error("Finality proof submission exceeds limits: {extras:?}")] + FinalityProofWeightLimitExceeded { + /// Finality proof submission extras. + extras: SubmitFinalityProofCallExtras, + }, /// Custom logic error. #[error("{0}")] Custom(String), diff --git a/bridges/relays/client-substrate/src/transaction_tracker.rs b/bridges/relays/client-substrate/src/transaction_tracker.rs index 00375768c45c27c23dfccb7730668108a6fab788..b181a945c2c15393daf821901b298e81214f85e3 100644 --- a/bridges/relays/client-substrate/src/transaction_tracker.rs +++ b/bridges/relays/client-substrate/src/transaction_tracker.rs @@ -306,12 +306,13 @@ mod tests { TrackedTransactionStatus>, InvalidationStatus>, )> { + let (cancel_sender, _cancel_receiver) = futures::channel::oneshot::channel(); let (mut sender, receiver) = futures::channel::mpsc::channel(1); let tx_tracker = TransactionTracker::::new( TestEnvironment(Ok(HeaderId(0, Default::default()))), Duration::from_secs(0), Default::default(), - Subscription(async_std::sync::Mutex::new(receiver)), + Subscription(async_std::sync::Mutex::new(receiver), cancel_sender), ); let wait_for_stall_timeout = futures::future::pending(); @@ -428,12 +429,13 @@ mod tests { #[async_std::test] async fn lost_on_timeout_when_waiting_for_invalidation_status() { + let (cancel_sender, _cancel_receiver) = futures::channel::oneshot::channel(); let (_sender, receiver) = futures::channel::mpsc::channel(1); let tx_tracker = TransactionTracker::::new( TestEnvironment(Ok(HeaderId(0, Default::default()))), Duration::from_secs(0), Default::default(), - Subscription(async_std::sync::Mutex::new(receiver)), + Subscription(async_std::sync::Mutex::new(receiver), cancel_sender), ); let wait_for_stall_timeout = futures::future::ready(()).shared(); diff --git a/bridges/relays/lib-substrate-relay/Cargo.toml b/bridges/relays/lib-substrate-relay/Cargo.toml index 3f657645b591c51ab74c5b6b64bfdd8ca04e7b18..077d1b1ff356a871364d45c1251aec0af7680cdd 100644 --- a/bridges/relays/lib-substrate-relay/Cargo.toml +++ b/bridges/relays/lib-substrate-relay/Cargo.toml @@ -14,7 +14,7 @@ workspace = true anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" hex = "0.4" log = { workspace = true } diff --git a/bridges/relays/lib-substrate-relay/src/cli/mod.rs b/bridges/relays/lib-substrate-relay/src/cli/mod.rs index 0dd0d5474b3a517b7eb67b641a5d3b427cad2b84..270608bf6ed8e1500d10000173bd7945a31c8135 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/mod.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/mod.rs @@ -125,14 +125,13 @@ impl PrometheusParams { None }; - let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); + let relay_version = relay_utils::initialize::RELAYER_VERSION + .lock() + .clone() + .unwrap_or_else(|| "unknown".to_string()); let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); - relay_utils::metrics::MetricsParams::new( - metrics_address, - relay_version.into(), - relay_commit, - ) - .map_err(|e| anyhow::format_err!("{:?}", e)) + relay_utils::metrics::MetricsParams::new(metrics_address, relay_version, relay_commit) + .map_err(|e| anyhow::format_err!("{:?}", e)) } } diff --git a/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs index b672bd4f9b86812c87532012debb89e0a601451f..943feba072e408d98360ece228fe8c5558181b69 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs @@ -26,9 +26,12 @@ use async_trait::async_trait; use sp_core::Pair; use structopt::StructOpt; +use bp_messages::MessageNonce; +use bp_runtime::HeaderIdProvider; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithRuntimeVersion, ChainWithTransactions, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, }; +use relay_utils::UniqueSaturatedInto; /// Messages relaying params. #[derive(StructOpt)] @@ -48,6 +51,53 @@ pub struct RelayMessagesParams { prometheus_params: PrometheusParams, } +/// Messages range relaying params. +#[derive(StructOpt)] +pub struct RelayMessagesRangeParams { + /// Number of the source chain header that we will use to prepare a messages proof. + /// This header must be previously proved to the target chain. + #[structopt(long)] + at_source_block: u128, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Nonce (inclusive) of the first message to relay. + #[structopt(long)] + messages_start: MessageNonce, + /// Nonce (inclusive) of the last message to relay. + #[structopt(long)] + messages_end: MessageNonce, + /// Whether the outbound lane state proof should be included into transaction. + #[structopt(long)] + outbound_state_proof_required: bool, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, +} + +/// Messages delivery confirmation relaying params. +#[derive(StructOpt)] +pub struct RelayMessagesDeliveryConfirmationParams { + /// Number of the target chain header that we will use to prepare a messages + /// delivery proof. This header must be previously proved to the source chain. + #[structopt(long)] + at_target_block: u128, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, +} + /// Trait used for relaying messages between 2 chains. #[async_trait] pub trait MessagesRelayer: MessagesCliBridge @@ -86,4 +136,73 @@ where .await .map_err(|e| anyhow::format_err!("{}", e)) } + + /// Relay a consequitive range of messages. + async fn relay_messages_range(data: RelayMessagesRangeParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + let target_sign = data.target_sign.to_keypair::()?; + let target_transactions_mortality = data.target_sign.transactions_mortality()?; + + let at_source_block = source_client + .header_by_number(data.at_source_block.unique_saturated_into()) + .await + .map_err(|e| { + log::trace!( + target: "bridge", + "Failed to read {} header with number {}: {e:?}", + Self::Source::NAME, + data.at_source_block, + ); + anyhow::format_err!("The command has failed") + })? + .id(); + + crate::messages_lane::relay_messages_range::( + source_client, + target_client, + TransactionParams { signer: source_sign, mortality: source_transactions_mortality }, + TransactionParams { signer: target_sign, mortality: target_transactions_mortality }, + at_source_block, + data.lane.into(), + data.messages_start..=data.messages_end, + data.outbound_state_proof_required, + ) + .await + } + + /// Relay a messages delivery confirmation. + async fn relay_messages_delivery_confirmation( + data: RelayMessagesDeliveryConfirmationParams, + ) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + + let at_target_block = target_client + .header_by_number(data.at_target_block.unique_saturated_into()) + .await + .map_err(|e| { + log::trace!( + target: "bridge", + "Failed to read {} header with number {}: {e:?}", + Self::Target::NAME, + data.at_target_block, + ); + anyhow::format_err!("The command has failed") + })? + .id(); + + crate::messages_lane::relay_messages_delivery_confirmation::( + source_client, + target_client, + TransactionParams { signer: source_sign, mortality: source_transactions_mortality }, + at_target_block, + data.lane.into(), + ) + .await + } } diff --git a/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs index 1425233add1ee3a58b1729a10ed2bb2d2fbc8667..00f8cf79ef1fb54577954cf198e7296819591a43 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs @@ -18,6 +18,8 @@ use async_std::sync::Mutex; use async_trait::async_trait; +use bp_polkadot_core::BlockNumber as RelayBlockNumber; +use bp_runtime::HeaderIdProvider; use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; use relay_substrate_client::Parachain; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; @@ -51,6 +53,21 @@ pub struct RelayParachainsParams { prometheus_params: PrometheusParams, } +/// Single parachains head relaying params. +#[derive(StructOpt)] +pub struct RelayParachainHeadParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + /// Prove parachain head at that relay block number. This relay header must be previously + /// proved to the target chain. + #[structopt(long)] + at_relay_block: RelayBlockNumber, +} + /// Trait used for relaying parachains finality between 2 chains. #[async_trait] pub trait ParachainsRelayer: ParachainToRelayHeadersCliBridge @@ -94,4 +111,38 @@ where .await .map_err(|e| anyhow::format_err!("{}", e)) } + + /// Relay single parachain head. No checks are made to ensure that transaction will succeed. + async fn relay_parachain_head(data: RelayParachainHeadParams) -> anyhow::Result<()> { + let source_chain_client = data.source.into_client::().await?; + let at_relay_block = source_chain_client + .header_by_number(data.at_relay_block) + .await + .map_err(|e| anyhow::format_err!("{}", e))? + .id(); + + let source_client = ParachainsSource::::new( + source_chain_client.clone(), + Arc::new(Mutex::new(AvailableHeader::Missing)), + ); + + let target_transaction_params = TransactionParams { + signer: data.target_sign.to_keypair::()?, + mortality: data.target_sign.target_transactions_mortality, + }; + let target_chain_client = data.target.into_client::().await?; + let target_client = ParachainsTarget::::new( + source_chain_client, + target_chain_client, + target_transaction_params, + ); + + parachains_relay::parachains_loop::relay_single_head( + source_client, + target_client, + at_relay_block, + ) + .await + .map_err(|_| anyhow::format_err!("The command has failed")) + } } diff --git a/bridges/relays/lib-substrate-relay/src/finality/target.rs b/bridges/relays/lib-substrate-relay/src/finality/target.rs index adbcfe0096d5f46ddacdf80e335f74967febca0e..52ab2462c62c4784b80bfbd128c11194a4f2edd4 100644 --- a/bridges/relays/lib-substrate-relay/src/finality/target.rs +++ b/bridges/relays/lib-substrate-relay/src/finality/target.rs @@ -107,13 +107,24 @@ impl TargetClient Result>, Self::Error> { - self.client + Ok(self + .client .typed_state_call( P::SourceChain::FREE_HEADERS_INTERVAL_METHOD.into(), (), Some(self.client.best_header().await?.hash()), ) .await + .unwrap_or_else(|e| { + log::info!( + target: "bridge", + "Call of {} at {} has failed with an error: {:?}. Treating as `None`", + P::SourceChain::FREE_HEADERS_INTERVAL_METHOD, + P::TargetChain::NAME, + e, + ); + None + })) } async fn submit_finality_proof( @@ -126,6 +137,16 @@ impl TargetClient: Send { @@ -129,12 +115,11 @@ pub trait Engine: Send { ) -> Result; /// Checks whether the given `header` and its finality `proof` fit the maximal expected - /// call size limit. If result is `MaxExpectedCallSizeCheck::Exceeds { .. }`, this - /// submission won't be fully refunded and relayer will spend its own funds on that. - fn check_max_expected_call_size( + /// call limits (size and weight). + fn check_max_expected_call_limits( header: &C::Header, proof: &Self::FinalityProof, - ) -> MaxExpectedCallSizeCheck; + ) -> SubmitFinalityProofCallExtras; /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( @@ -245,22 +230,11 @@ impl Engine for Grandpa { }) } - fn check_max_expected_call_size( + fn check_max_expected_call_limits( header: &C::Header, proof: &Self::FinalityProof, - ) -> MaxExpectedCallSizeCheck { - let is_mandatory = Self::ConsensusLogReader::schedules_authorities_change(header.digest()); - let call_size: u32 = - header.encoded_size().saturating_add(proof.encoded_size()).saturated_into(); - let max_call_size = max_expected_submit_finality_proof_arguments_size::( - is_mandatory, - proof.commit.precommits.len().saturated_into(), - ); - if call_size > max_call_size { - MaxExpectedCallSizeCheck::Exceeds { call_size, max_call_size } - } else { - MaxExpectedCallSizeCheck::Ok - } + ) -> SubmitFinalityProofCallExtras { + bp_header_chain::submit_finality_proof_limits_extras::(header, proof) } /// Prepare initialization data for the GRANDPA verifier pallet. diff --git a/bridges/relays/lib-substrate-relay/src/messages_lane.rs b/bridges/relays/lib-substrate-relay/src/messages_lane.rs index 58e9ded312dfea4813d1a5ddf843e76752bfc0cb..08550d19bae03aaf955c81800267cd80f9ce0f20 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_lane.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_lane.rs @@ -46,7 +46,7 @@ use relay_utils::{ }; use sp_core::Pair; use sp_runtime::traits::Zero; -use std::{fmt::Debug, marker::PhantomData}; +use std::{fmt::Debug, marker::PhantomData, ops::RangeInclusive}; /// Substrate -> Substrate messages synchronization pipeline. pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { @@ -262,7 +262,7 @@ where source_client, params.lane_id, relayer_id_at_source, - params.target_transaction_params, + Some(params.target_transaction_params), params.source_to_target_headers_relay, ), { @@ -275,6 +275,87 @@ where .map_err(Into::into) } +/// Deliver range of Substrate-to-Substrate messages. No checks are made to ensure that transaction +/// will succeed. +pub async fn relay_messages_range( + source_client: Client, + target_client: Client, + source_transaction_params: TransactionParams>, + target_transaction_params: TransactionParams>, + at_source_block: HeaderIdOf, + lane_id: LaneId, + range: RangeInclusive, + outbound_state_proof_required: bool, +) -> anyhow::Result<()> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, +{ + let relayer_id_at_source: AccountIdOf = + source_transaction_params.signer.public().into(); + messages_relay::relay_messages_range( + SubstrateMessagesSource::

::new( + source_client.clone(), + target_client.clone(), + lane_id, + source_transaction_params, + None, + ), + SubstrateMessagesTarget::

::new( + target_client, + source_client, + lane_id, + relayer_id_at_source, + Some(target_transaction_params), + None, + ), + at_source_block, + range, + outbound_state_proof_required, + ) + .await + .map_err(|_| anyhow::format_err!("The command has failed")) +} + +/// Relay messages delivery confirmation of Substrate-to-Substrate messages. +/// No checks are made to ensure that transaction will succeed. +pub async fn relay_messages_delivery_confirmation( + source_client: Client, + target_client: Client, + source_transaction_params: TransactionParams>, + at_target_block: HeaderIdOf, + lane_id: LaneId, +) -> anyhow::Result<()> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, +{ + let relayer_id_at_source: AccountIdOf = + source_transaction_params.signer.public().into(); + messages_relay::relay_messages_delivery_confirmation( + SubstrateMessagesSource::

::new( + source_client.clone(), + target_client.clone(), + lane_id, + source_transaction_params, + None, + ), + SubstrateMessagesTarget::

::new( + target_client, + source_client, + lane_id, + relayer_id_at_source, + None, + None, + ), + at_target_block, + ) + .await + .map_err(|_| anyhow::format_err!("The command has failed")) +} + /// Different ways of building `receive_messages_proof` calls. pub trait ReceiveMessagesProofCallBuilder { /// Given messages proof, build call of `receive_messages_proof` function of bridge diff --git a/bridges/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs index 633b11f0b8028636fdb8c9c6b4f1ec5fa42ccf33..5ffb2b6c771e0fec2bf44640993abba3706cb0a5 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_target.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_target.rs @@ -40,8 +40,8 @@ use messages_relay::{ message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Client, Error as SubstrateError, HashOf, - TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, Client, Error as SubstrateError, + HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -57,7 +57,7 @@ pub struct SubstrateMessagesTarget { source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: Option>>, source_to_target_headers_relay: Option>>, } @@ -68,7 +68,7 @@ impl SubstrateMessagesTarget

{ source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: Option>>, source_to_target_headers_relay: Option< Arc>, >, @@ -249,11 +249,18 @@ where None => messages_proof_call, }; - let transaction_params = self.transaction_params.clone(); + let transaction_params = self.transaction_params.clone().map(Ok).unwrap_or_else(|| { + // this error shall never happen in practice, so it not deserves + // a separate error variant + Err(SubstrateError::Custom(format!( + "Cannot sign transaction of {} chain", + P::TargetChain::NAME, + ))) + })?; let tx_tracker = self .target_client .submit_and_watch_signed_extrinsic( - &self.transaction_params.signer, + &transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs b/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs index 74f3a70c5e81bbc1d27162a74fb8dadab46a6d09..202f53ea4e4f50510f125f28da86de878125d581 100644 --- a/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -16,9 +16,7 @@ //! On-demand Substrate -> Substrate header finality relay. -use crate::{ - finality::SubmitFinalityProofCallBuilder, finality_base::engine::MaxExpectedCallSizeCheck, -}; +use crate::finality::SubmitFinalityProofCallBuilder; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; @@ -156,22 +154,21 @@ impl OnDemandRelay Result>, Self::Error> { - self.target_client + Ok(self + .target_client .typed_state_call(P::SourceRelayChain::FREE_HEADERS_INTERVAL_METHOD.into(), (), None) .await + .unwrap_or_else(|e| { + log::info!( + target: "bridge", + "Call of {} at {} has failed with an error: {:?}. Treating as `None`", + P::SourceRelayChain::FREE_HEADERS_INTERVAL_METHOD, + P::TargetChain::NAME, + e, + ); + None + })) } async fn parachain_head( diff --git a/bridges/relays/messages/src/lib.rs b/bridges/relays/messages/src/lib.rs index 9c62cee5ee3db1e0b8825d2893d53422bf44a33c..78a3237ba4fe03851412b86e08867fcba07e8451 100644 --- a/bridges/relays/messages/src/lib.rs +++ b/bridges/relays/messages/src/lib.rs @@ -35,3 +35,6 @@ mod message_race_limits; mod message_race_loop; mod message_race_receiving; mod message_race_strategy; + +pub use message_race_delivery::relay_messages_range; +pub use message_race_receiving::relay_messages_delivery_confirmation; diff --git a/bridges/relays/messages/src/message_race_delivery.rs b/bridges/relays/messages/src/message_race_delivery.rs index f18c43cc7f0e084100d8096432dccafbd61301be..cbb89baabcc5ab38f164189066e225ad1e8f9240 100644 --- a/bridges/relays/messages/src/message_race_delivery.rs +++ b/bridges/relays/messages/src/message_race_delivery.rs @@ -19,7 +19,7 @@ use async_trait::async_trait; use futures::stream::FusedStream; use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; -use relay_utils::FailedClient; +use relay_utils::{FailedClient, TrackedTransactionStatus, TransactionTracker}; use crate::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, @@ -77,6 +77,69 @@ pub async fn run( .await } +/// Relay range of messages. +pub async fn relay_messages_range( + source_client: impl MessageLaneSourceClient

, + target_client: impl MessageLaneTargetClient

, + at: SourceHeaderIdOf

, + range: RangeInclusive, + outbound_state_proof_required: bool, +) -> Result<(), ()> { + // compute cumulative dispatch weight of all messages in given range + let dispatch_weight = source_client + .generated_message_details(at.clone(), range.clone()) + .await + .map_err(|e| { + log::error!( + target: "bridge", + "Failed to get generated message details at {:?} for messages {:?}: {:?}", + at, + range, + e, + ); + })? + .values() + .fold(Weight::zero(), |total, details| total.saturating_add(details.dispatch_weight)); + // prepare messages proof + let (at, range, proof) = source_client + .prove_messages( + at.clone(), + range.clone(), + MessageProofParameters { outbound_state_proof_required, dispatch_weight }, + ) + .await + .map_err(|e| { + log::error!( + target: "bridge", + "Failed to generate messages proof at {:?} for messages {:?}: {:?}", + at, + range, + e, + ); + })?; + // submit messages proof to the target node + let tx_tracker = target_client + .submit_messages_proof(None, at, range.clone(), proof) + .await + .map_err(|e| { + log::error!( + target: "bridge", + "Failed to submit messages proof for messages {:?}: {:?}", + range, + e, + ); + })? + .tx_tracker; + + match tx_tracker.wait().await { + TrackedTransactionStatus::Finalized(_) => Ok(()), + TrackedTransactionStatus::Lost => { + log::error!("Transaction with messages {:?} is considered lost", range,); + Err(()) + }, + } +} + /// Message delivery race. struct MessageDeliveryRace

(std::marker::PhantomData

); diff --git a/bridges/relays/messages/src/message_race_receiving.rs b/bridges/relays/messages/src/message_race_receiving.rs index e6497a1b79eb70999f16cd0c1926ae9cf0ad5411..ac4149b22d7b124f9cf661e8a99de7dedc4a15fe 100644 --- a/bridges/relays/messages/src/message_race_receiving.rs +++ b/bridges/relays/messages/src/message_race_receiving.rs @@ -30,7 +30,7 @@ use crate::{ use async_trait::async_trait; use bp_messages::MessageNonce; use futures::stream::FusedStream; -use relay_utils::FailedClient; +use relay_utils::{FailedClient, TrackedTransactionStatus, TransactionTracker}; use std::{marker::PhantomData, ops::RangeInclusive}; /// Message receiving confirmations delivery strategy. @@ -69,6 +69,43 @@ pub async fn run( .await } +/// Relay messages delivery confirmation. +pub async fn relay_messages_delivery_confirmation( + source_client: impl MessageLaneSourceClient

, + target_client: impl MessageLaneTargetClient

, + at: TargetHeaderIdOf

, +) -> Result<(), ()> { + // prepare messages delivery proof + let (at, proof) = target_client.prove_messages_receiving(at.clone()).await.map_err(|e| { + log::error!( + target: "bridge", + "Failed to generate messages delivery proof at {:?}: {:?}", + at, + e, + ); + })?; + // submit messages delivery proof to the source node + let tx_tracker = + source_client + .submit_messages_receiving_proof(None, at, proof) + .await + .map_err(|e| { + log::error!( + target: "bridge", + "Failed to submit messages delivery proof: {:?}", + e, + ); + })?; + + match tx_tracker.wait().await { + TrackedTransactionStatus::Finalized(_) => Ok(()), + TrackedTransactionStatus::Lost => { + log::error!("Transaction with messages delivery proof is considered lost"); + Err(()) + }, + } +} + /// Messages receiving confirmations race. struct ReceivingConfirmationsRace

(std::marker::PhantomData

); diff --git a/bridges/relays/parachains/Cargo.toml b/bridges/relays/parachains/Cargo.toml index a73a2f5b31c1aca5d93bf0b871b79b5e279da6ff..8d38e4e6bd07c2420adcf233729c1bac9bb77c37 100644 --- a/bridges/relays/parachains/Cargo.toml +++ b/bridges/relays/parachains/Cargo.toml @@ -23,6 +23,6 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } relay-substrate-client = { path = "../client-substrate" } [dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } sp-core = { path = "../../../substrate/primitives/core" } diff --git a/bridges/relays/parachains/src/parachains_loop.rs b/bridges/relays/parachains/src/parachains_loop.rs index 55f236eeac1d842ff9ed0f337cf1ea2c725dc763..fd73ca2d46c00f8e05bb05a14a7fa4104ef898c4 100644 --- a/bridges/relays/parachains/src/parachains_loop.rs +++ b/bridges/relays/parachains/src/parachains_loop.rs @@ -139,6 +139,33 @@ pub fn metrics_prefix() -> String { ) } +/// Relay single parachain head. +pub async fn relay_single_head( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + at_relay_block: HeaderIdOf, +) -> Result<(), ()> +where + P::SourceRelayChain: Chain, +{ + let tx_tracker = + submit_selected_head::(&source_client, &target_client, at_relay_block, false) + .await + .map_err(drop)?; + match tx_tracker.wait().await { + TrackedTransactionStatus::Finalized(_) => Ok(()), + TrackedTransactionStatus::Lost => { + log::error!( + "Transaction with {} header at relay header {:?} is considered lost at {}", + P::SourceParachain::NAME, + at_relay_block, + P::TargetChain::NAME, + ); + Err(()) + }, + } +} + /// Run parachain heads synchronization. pub async fn run( source_client: impl SourceClient

, @@ -361,52 +388,63 @@ where ); if is_update_required { - let (head_proof, head_hash) = - source_client.prove_parachain_head(prove_at_relay_block).await.map_err(|e| { - log::warn!( - target: "bridge", - "Failed to prove {} parachain ParaId({}) heads: {:?}", - P::SourceRelayChain::NAME, - P::SourceParachain::PARACHAIN_ID, - e, - ); - FailedClient::Source - })?; - log::info!( - target: "bridge", - "Submitting {} parachain ParaId({}) head update transaction to {}. Para hash at source relay {:?}: {:?}", - P::SourceRelayChain::NAME, - P::SourceParachain::PARACHAIN_ID, - P::TargetChain::NAME, + let transaction_tracker = submit_selected_head::( + &source_client, + &target_client, prove_at_relay_block, - head_hash, - ); - - let transaction_tracker = target_client - .submit_parachain_head_proof( - prove_at_relay_block, - head_hash, - head_proof, - only_free_headers, - ) - .await - .map_err(|e| { - log::warn!( - target: "bridge", - "Failed to submit {} parachain ParaId({}) heads proof to {}: {:?}", - P::SourceRelayChain::NAME, - P::SourceParachain::PARACHAIN_ID, - P::TargetChain::NAME, - e, - ); - FailedClient::Target - })?; + only_free_headers, + ) + .await?; submitted_heads_tracker = Some(SubmittedHeadsTracker::

::new(head_at_source, transaction_tracker)); } } } +/// Prove and submit parachain head at given relay chain block. +async fn submit_selected_head>( + source_client: &impl SourceClient

, + target_client: &TC, + prove_at_relay_block: HeaderIdOf, + only_free_headers: bool, +) -> Result { + let (head_proof, head_hash) = + source_client.prove_parachain_head(prove_at_relay_block).await.map_err(|e| { + log::warn!( + target: "bridge", + "Failed to prove {} parachain ParaId({}) heads: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + e, + ); + FailedClient::Source + })?; + log::info!( + target: "bridge", + "Submitting {} parachain ParaId({}) head update transaction to {}. Para hash at source relay {:?}: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME, + prove_at_relay_block, + head_hash, + ); + + target_client + .submit_parachain_head_proof(prove_at_relay_block, head_hash, head_proof, only_free_headers) + .await + .map_err(|e| { + log::warn!( + target: "bridge", + "Failed to submit {} parachain ParaId({}) heads proof to {}: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME, + e, + ); + FailedClient::Target + }) +} + /// Returns `true` if we need to submit parachain-head-update transaction. fn is_update_required( head_at_source: AvailableHeader>, diff --git a/bridges/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml index ee56ebf9a956c6f4fdd06b554da279b56ed534dc..1264f582983f93c0f0b739f9d6c456df417f00ac 100644 --- a/bridges/relays/utils/Cargo.toml +++ b/bridges/relays/utils/Cargo.toml @@ -22,6 +22,7 @@ futures = "0.3.30" jsonpath_lib = "0.3" log = { workspace = true } num-traits = "0.2" +parking_lot = "0.12.1" serde_json = { workspace = true, default-features = true } sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } diff --git a/bridges/relays/utils/src/initialize.rs b/bridges/relays/utils/src/initialize.rs index 8224c1803ad2f74ec694cd68c18a556dddc6d76f..64d710242710b722b3b5be67dc439f814cd7e9df 100644 --- a/bridges/relays/utils/src/initialize.rs +++ b/bridges/relays/utils/src/initialize.rs @@ -16,8 +16,13 @@ //! Relayer initialization functions. +use parking_lot::Mutex; use std::{cell::RefCell, fmt::Display, io::Write}; +/// Relayer version that is provided as metric. Must be set by a binary +/// (get it with `option_env!("CARGO_PKG_VERSION")` from a binary package code). +pub static RELAYER_VERSION: Mutex> = Mutex::new(None); + async_std::task_local! { pub(crate) static LOOP_NAME: RefCell = RefCell::new(String::default()); } diff --git a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml index 0e15304ff11234d6c1871511fc8c3237830fe9a4..e60934e34740600e78b9973d66ce648751a55138 100644 --- a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { optional = true, workspace = true, default-features = true } serde_json = { optional = true, workspace = true, default-features = true } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } +codec = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1", optional = true } log = { workspace = true } diff --git a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs index c1b9e19729bc47588ad179db0c9c280a05834bc1..6a5972ca7a142e4a5842d506fce5a87991e25f3a 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs @@ -104,6 +104,7 @@ pub mod pallet { #[pallet::error] pub enum Error { SkippedSyncCommitteePeriod, + SyncCommitteeUpdateRequired, /// Attested header is older than latest finalized header. IrrelevantUpdate, NotBootstrapped, @@ -138,41 +139,39 @@ pub mod pallet { /// Latest imported checkpoint root #[pallet::storage] #[pallet::getter(fn initial_checkpoint_root)] - pub(super) type InitialCheckpointRoot = StorageValue<_, H256, ValueQuery>; + pub type InitialCheckpointRoot = StorageValue<_, H256, ValueQuery>; /// Latest imported finalized block root #[pallet::storage] #[pallet::getter(fn latest_finalized_block_root)] - pub(super) type LatestFinalizedBlockRoot = StorageValue<_, H256, ValueQuery>; + pub type LatestFinalizedBlockRoot = StorageValue<_, H256, ValueQuery>; /// Beacon state by finalized block root #[pallet::storage] #[pallet::getter(fn finalized_beacon_state)] - pub(super) type FinalizedBeaconState = + pub type FinalizedBeaconState = StorageMap<_, Identity, H256, CompactBeaconState, OptionQuery>; /// Finalized Headers: Current position in ring buffer #[pallet::storage] - pub(crate) type FinalizedBeaconStateIndex = StorageValue<_, u32, ValueQuery>; + pub type FinalizedBeaconStateIndex = StorageValue<_, u32, ValueQuery>; /// Finalized Headers: Mapping of ring buffer index to a pruning candidate #[pallet::storage] - pub(crate) type FinalizedBeaconStateMapping = + pub type FinalizedBeaconStateMapping = StorageMap<_, Identity, u32, H256, ValueQuery>; #[pallet::storage] #[pallet::getter(fn validators_root)] - pub(super) type ValidatorsRoot = StorageValue<_, H256, ValueQuery>; + pub type ValidatorsRoot = StorageValue<_, H256, ValueQuery>; /// Sync committee for current period #[pallet::storage] - pub(super) type CurrentSyncCommittee = - StorageValue<_, SyncCommitteePrepared, ValueQuery>; + pub type CurrentSyncCommittee = StorageValue<_, SyncCommitteePrepared, ValueQuery>; /// Sync committee for next period #[pallet::storage] - pub(super) type NextSyncCommittee = - StorageValue<_, SyncCommitteePrepared, ValueQuery>; + pub type NextSyncCommittee = StorageValue<_, SyncCommitteePrepared, ValueQuery>; /// The current operating mode of the pallet. #[pallet::storage] @@ -320,6 +319,7 @@ pub mod pallet { // Verify update is relevant. let update_attested_period = compute_period(update.attested_header.slot); + let update_finalized_period = compute_period(update.finalized_header.slot); let update_has_next_sync_committee = !>::exists() && (update.next_sync_committee_update.is_some() && update_attested_period == store_period); @@ -395,6 +395,11 @@ pub mod pallet { ), Error::::InvalidSyncCommitteeMerkleProof ); + } else { + ensure!( + update_finalized_period == store_period, + Error::::SyncCommitteeUpdateRequired + ); } // Verify sync committee aggregate signature. diff --git a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs index 765958c128212ee279bf547eb864335c7921e2eb..da762dc2fd8071969a1f68c707a0145aa0803852 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs @@ -362,13 +362,14 @@ fn submit_update_with_sync_committee_in_current_period() { } #[test] -fn submit_update_in_next_period() { +fn reject_submit_update_in_next_period() { let checkpoint = Box::new(load_checkpoint_update_fixture()); let sync_committee_update = Box::new(load_sync_committee_update_fixture()); let update = Box::new(load_next_finalized_header_update_fixture()); let sync_committee_period = compute_period(sync_committee_update.finalized_header.slot); let next_sync_committee_period = compute_period(update.finalized_header.slot); assert_eq!(sync_committee_period + 1, next_sync_committee_period); + let next_sync_committee_update = Box::new(load_next_sync_committee_update_fixture()); new_tester().execute_with(|| { assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); @@ -376,6 +377,17 @@ fn submit_update_in_next_period() { RuntimeOrigin::signed(1), sync_committee_update.clone() )); + // check an update in the next period is rejected + assert_err!( + EthereumBeaconClient::submit(RuntimeOrigin::signed(1), update.clone()), + Error::::SyncCommitteeUpdateRequired + ); + // submit update with next sync committee + assert_ok!(EthereumBeaconClient::submit( + RuntimeOrigin::signed(1), + next_sync_committee_update + )); + // check same header in the next period can now be submitted successfully assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), update.clone())); let block_root: H256 = update.finalized_header.clone().hash_tree_root().unwrap(); assert!(>::contains_key(block_root)); diff --git a/bridges/snowbridge/pallets/ethereum-client/src/types.rs b/bridges/snowbridge/pallets/ethereum-client/src/types.rs index 8808f989754b240d207101cbeff6fe25fe74279a..92b9f77f739b062b89de2685db91e7f8355a2722 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/types.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/types.rs @@ -18,7 +18,7 @@ pub type NextSyncCommitteeUpdate = primitives::NextSyncCommitteeUpdate; pub use primitives::{AncestryProof, ExecutionProof}; /// FinalizedState ring buffer implementation -pub(crate) type FinalizedBeaconStateBuffer = RingBufferMapImpl< +pub type FinalizedBeaconStateBuffer = RingBufferMapImpl< u32, crate::MaxFinalizedHeadersToKeep, crate::FinalizedBeaconStateIndex, diff --git a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml index 71d49e684e0b9379778f45743f6427a41796fd8a..d63398770f207051ebb5adb72f4f574c767e8770 100644 --- a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { optional = true, workspace = true, default-features = true } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } +codec = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1", optional = true } log = { workspace = true } diff --git a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs index c96c868bc26ef71984e70bc40863db73cf18b9c5..05481ca2f6b439a82ba0065075c879725f2c3818 100644 --- a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs @@ -43,10 +43,6 @@ frame_support::construct_runtime!( pub type Signature = MultiSignature; pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - type Balance = u128; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] @@ -60,7 +56,6 @@ impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type Nonce = u64; diff --git a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml index 387491abae0f652d63c55d50279d4145dc03b18d..15c6c3a5b32b0fc2bd1a95fd842bab78f07a697a 100644 --- a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { features = ["alloc", "derive"], workspace = true } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } +codec = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true } diff --git a/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml index 5315d6b4adbc1618720c7e0c781c65353c0ca4d6..1b1a9905928f8b5ea8eaccc15d18813f87406494 100644 --- a/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { version = "3.1.5", package = "parity-scale-codec", default-features = false, features = ["derive"] } +codec = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } @@ -25,7 +25,7 @@ sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-fea hex-literal = { version = "0.4.1" } env_logger = "0.11" hex = "0.4" -array-bytes = "4.1" +array-bytes = "6.2.2" sp-crypto-hashing = { path = "../../../../../substrate/primitives/crypto/hashing" } [features] diff --git a/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml index fa49cc0f29a0a161838ab62a1210e33a79f32c59..b8d704f1cb92d570ea8e8b06cd00410bea7746bb 100644 --- a/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { version = "3.1.5", package = "parity-scale-codec", features = ["derive"], default-features = false } +codec = { version = "3.6.12", package = "parity-scale-codec", features = ["derive"], default-features = false } sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } sp-api = { path = "../../../../../substrate/primitives/api", default-features = false } frame-support = { path = "../../../../../substrate/frame/support", default-features = false } diff --git a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs index 5eeeeead140018e81a8aaaf302d678e3a4321e08..d65a96e2702dfbc69e52a913964de230bcdeadd0 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs @@ -33,10 +33,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; @@ -48,7 +44,6 @@ impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type PalletInfo = PalletInfo; type Nonce = u64; type Block = Block; diff --git a/bridges/snowbridge/pallets/system/Cargo.toml b/bridges/snowbridge/pallets/system/Cargo.toml index c1ee44214c84a81dd9c4727bf81be93d5375c50c..5bbbb1d9310da4c3617ec4b03ea63620c30feb20 100644 --- a/bridges/snowbridge/pallets/system/Cargo.toml +++ b/bridges/snowbridge/pallets/system/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } diff --git a/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml b/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml index 4073dc0f71c2096edce47a0857cd70cf969affed..42df5edfb7b2d4e5abaf0e30850ecbd3ebd04b98 100644 --- a/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml +++ b/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs index 687072a49e2e5ca9e27d7f1be94ea89564c2275f..d7fc4152b371025687d2a36cbd49e628c88205fc 100644 --- a/bridges/snowbridge/pallets/system/src/mock.rs +++ b/bridges/snowbridge/pallets/system/src/mock.rs @@ -3,7 +3,7 @@ use crate as snowbridge_system; use frame_support::{ derive_impl, parameter_types, - traits::{tokens::fungible::Mutate, ConstU128, ConstU64, ConstU8}, + traits::{tokens::fungible::Mutate, ConstU128, ConstU8}, weights::IdentityFee, PalletId, }; @@ -106,7 +106,6 @@ impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type Nonce = u64; diff --git a/bridges/snowbridge/primitives/beacon/Cargo.toml b/bridges/snowbridge/primitives/beacon/Cargo.toml index 7d901bcdb04493ea3103150c7dfeff0a32814269..18123910c35b2e198ec03ca1aa01aef1ea0d96ca 100644 --- a/bridges/snowbridge/primitives/beacon/Cargo.toml +++ b/bridges/snowbridge/primitives/beacon/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] serde = { optional = true, features = ["derive"], workspace = true, default-features = true } hex = { version = "0.4", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } rlp = { version = "0.5", default-features = false } diff --git a/bridges/snowbridge/primitives/core/Cargo.toml b/bridges/snowbridge/primitives/core/Cargo.toml index 9a299ad0ae92326a6d0bb0391baf81e6e5bad663..573ab6608e5f91c0333f5ee7288cb679d6c38fb6 100644 --- a/bridges/snowbridge/primitives/core/Cargo.toml +++ b/bridges/snowbridge/primitives/core/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] serde = { optional = true, features = ["alloc", "derive"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1" } diff --git a/bridges/snowbridge/primitives/ethereum/Cargo.toml b/bridges/snowbridge/primitives/ethereum/Cargo.toml index d72cd2661733b516a6a9b8102782b4d8d5c40e36..fb0b6cbaf3c2fba82c709fbc84ca565c53e7505e 100644 --- a/bridges/snowbridge/primitives/ethereum/Cargo.toml +++ b/bridges/snowbridge/primitives/ethereum/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] serde = { optional = true, features = ["derive"], workspace = true, default-features = true } serde-big-array = { optional = true, features = ["const-generics"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } ethbloom = { version = "0.13.0", default-features = false } ethereum-types = { version = "0.14.1", default-features = false, features = ["codec", "rlp", "serialize"] } diff --git a/bridges/snowbridge/primitives/router/Cargo.toml b/bridges/snowbridge/primitives/router/Cargo.toml index 361b539af3e350a29871e82a76265de072bbf779..1d3fc43909df46a20f6e030985c2a7eea189fdc4 100644 --- a/bridges/snowbridge/primitives/router/Cargo.toml +++ b/bridges/snowbridge/primitives/router/Cargo.toml @@ -12,7 +12,7 @@ categories = ["cryptography::cryptocurrencies"] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } log = { workspace = true } diff --git a/bridges/snowbridge/runtime/runtime-common/Cargo.toml b/bridges/snowbridge/runtime/runtime-common/Cargo.toml index 995475349e4cb62045c613596acaf659eabd7076..2372908b86ab5134f4ea0f8373ffe00cbcc2bd32 100644 --- a/bridges/snowbridge/runtime/runtime-common/Cargo.toml +++ b/bridges/snowbridge/runtime/runtime-common/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] log = { workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } frame-support = { path = "../../../../substrate/frame/support", default-features = false } sp-std = { path = "../../../../substrate/primitives/std", default-features = false } sp-arithmetic = { path = "../../../../substrate/primitives/arithmetic", default-features = false } diff --git a/bridges/snowbridge/runtime/test-common/Cargo.toml b/bridges/snowbridge/runtime/test-common/Cargo.toml index 7cbb38574034c0b4c7f8b0bf82866c0392c82a10..e19c682de4542994e19e20d0c194598fc8009db5 100644 --- a/bridges/snowbridge/runtime/test-common/Cargo.toml +++ b/bridges/snowbridge/runtime/test-common/Cargo.toml @@ -11,7 +11,7 @@ categories = ["cryptography::cryptocurrencies"] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } # Substrate frame-support = { path = "../../../../substrate/frame/support", default-features = false } @@ -32,7 +32,7 @@ xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-feat xcm-executor = { package = "staging-xcm-executor", path = "../../../../polkadot/xcm/xcm-executor", default-features = false } # Cumulus -cumulus-pallet-parachain-system = { path = "../../../../cumulus/pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../cumulus/pallets/parachain-system", default-features = false } pallet-collator-selection = { path = "../../../../cumulus/pallets/collator-selection", default-features = false } parachain-info = { package = "staging-parachain-info", path = "../../../../cumulus/parachains/pallets/parachain-info", default-features = false } parachains-runtimes-test-utils = { path = "../../../../cumulus/parachains/runtimes/test-utils", default-features = false } diff --git a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh index 2f11692d97b9d2ff1853b9e85f7f30f884702bc7..ef4a5597902fdc61caedd071f408f03a87a19ea0 100755 --- a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh +++ b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh @@ -175,10 +175,9 @@ function run_finality_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-headers rococo-to-bridge-hub-westend \ --only-free-headers \ - --source-host localhost \ - --source-port 9942 \ - --target-host localhost \ - --target-port 8945 \ + --source-uri ws://localhost:9942 \ + --source-version-mode Auto \ + --target-uri ws://localhost:8945 \ --target-version-mode Auto \ --target-signer //Charlie \ --target-transactions-mortality 4& @@ -186,10 +185,9 @@ function run_finality_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-headers westend-to-bridge-hub-rococo \ --only-free-headers \ - --source-host localhost \ - --source-port 9945 \ - --target-host localhost \ - --target-port 8943 \ + --source-uri ws://localhost:9945 \ + --source-version-mode Auto \ + --target-uri ws://localhost:8943 \ --target-version-mode Auto \ --target-signer //Charlie \ --target-transactions-mortality 4 @@ -201,10 +199,9 @@ function run_parachains_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-parachains rococo-to-bridge-hub-westend \ --only-free-headers \ - --source-host localhost \ - --source-port 9942 \ - --target-host localhost \ - --target-port 8945 \ + --source-uri ws://localhost:9942 \ + --source-version-mode Auto \ + --target-uri ws://localhost:8945 \ --target-version-mode Auto \ --target-signer //Dave \ --target-transactions-mortality 4& @@ -212,10 +209,9 @@ function run_parachains_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-parachains westend-to-bridge-hub-rococo \ --only-free-headers \ - --source-host localhost \ - --source-port 9945 \ - --target-host localhost \ - --target-port 8943 \ + --source-uri ws://localhost:9945 \ + --source-version-mode Auto \ + --target-uri ws://localhost:8943 \ --target-version-mode Auto \ --target-signer //Dave \ --target-transactions-mortality 4 @@ -226,13 +222,11 @@ function run_messages_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-messages bridge-hub-rococo-to-bridge-hub-westend \ - --source-host localhost \ - --source-port 8943 \ + --source-uri ws://localhost:8943 \ --source-version-mode Auto \ --source-signer //Eve \ --source-transactions-mortality 4 \ - --target-host localhost \ - --target-port 8945 \ + --target-uri ws://localhost:8945 \ --target-version-mode Auto \ --target-signer //Eve \ --target-transactions-mortality 4 \ @@ -240,13 +234,11 @@ function run_messages_relay() { RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ $relayer_path relay-messages bridge-hub-westend-to-bridge-hub-rococo \ - --source-host localhost \ - --source-port 8945 \ + --source-uri ws://localhost:8945 \ --source-version-mode Auto \ --source-signer //Ferdie \ --source-transactions-mortality 4 \ - --target-host localhost \ - --target-port 8943 \ + --target-uri ws://localhost:8943 \ --target-version-mode Auto \ --target-signer //Ferdie \ --target-transactions-mortality 4 \ diff --git a/cumulus/client/cli/Cargo.toml b/cumulus/client/cli/Cargo.toml index 0b2edb593c405bef266fa7e389a996fe3a2fcec1..410ac8b983d96f0a38633ac0199208a4e249e49b 100644 --- a/cumulus/client/cli/Cargo.toml +++ b/cumulus/client/cli/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] clap = { version = "4.5.3", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.6.12" } url = "2.4.0" # Substrate diff --git a/cumulus/client/collator/Cargo.toml b/cumulus/client/collator/Cargo.toml index 42f7342d1a5381a6174c15909b815485eb7c8a7e..39cedf87a0cb1b6fb8296c1a3bdec1483170af38 100644 --- a/cumulus/client/collator/Cargo.toml +++ b/cumulus/client/collator/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] parking_lot = "0.12.1" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" tracing = "0.1.25" diff --git a/cumulus/client/consensus/aura/Cargo.toml b/cumulus/client/consensus/aura/Cargo.toml index 9a52b9fe4e5c60488d32a71671c295eb8e347d77..9ad75144f0efeb3728aae9bddba0f8042b103368 100644 --- a/cumulus/client/consensus/aura/Cargo.toml +++ b/cumulus/client/consensus/aura/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.28" tracing = "0.1.37" schnellru = "0.2.1" diff --git a/cumulus/client/consensus/common/Cargo.toml b/cumulus/client/consensus/common/Cargo.toml index fb4a85ad122637470a81371eb12352a14ac7c61e..3a7c6b57d6d931b8809e9be9fda4cf4e07e50b8c 100644 --- a/cumulus/client/consensus/common/Cargo.toml +++ b/cumulus/client/consensus/common/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } dyn-clone = "1.0.16" futures = "0.3.28" log = { workspace = true, default-features = true } diff --git a/cumulus/client/network/Cargo.toml b/cumulus/client/network/Cargo.toml index 1210975ef690c4d110a7f96b2e88e4d151edfa87..d4fc752872589fbfd361f5df49939874d208ab3d 100644 --- a/cumulus/client/network/Cargo.toml +++ b/cumulus/client/network/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.28" futures-timer = "3.0.2" parking_lot = "0.12.1" diff --git a/cumulus/client/parachain-inherent/Cargo.toml b/cumulus/client/parachain-inherent/Cargo.toml index 6e9adab1ffc9e2bf9de9d8101eb38e4da8212b27..85619e8403458c0bfa3dae6dadc688f2cb895731 100644 --- a/cumulus/client/parachain-inherent/Cargo.toml +++ b/cumulus/client/parachain-inherent/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } scale-info = { version = "2.11.1", features = ["derive"] } tracing = { version = "0.1.37" } diff --git a/cumulus/client/parachain-inherent/src/mock.rs b/cumulus/client/parachain-inherent/src/mock.rs index 22691006f93ed264e3e7d37b7b2120ea576e9da3..dfe4a66c3dc19665d413fed47434d803d6ed63af 100644 --- a/cumulus/client/parachain-inherent/src/mock.rs +++ b/cumulus/client/parachain-inherent/src/mock.rs @@ -28,6 +28,9 @@ use std::collections::BTreeMap; use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; +/// Relay chain slot duration, in milliseconds. +pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; + /// Inherent data provider that supplies mocked validation data. /// /// This is useful when running a node that is not actually backed by any relay chain. @@ -43,10 +46,14 @@ use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; /// your parachain's configuration in order to mock the MQC heads properly. /// See [`MockXcmConfig`] for more information pub struct MockValidationDataInherentDataProvider { - /// The current block number of the local block chain (the parachain) + /// The current block number of the local block chain (the parachain). pub current_para_block: u32, + /// The parachain ID of the parachain for that the inherent data is created. + pub para_id: ParaId, + /// The current block head data of the local block chain (the parachain). + pub current_para_block_head: Option, /// The relay block in which this parachain appeared to start. This will be the relay block - /// number in para block #P1 + /// number in para block #P1. pub relay_offset: u32, /// The number of relay blocks that elapses between each parablock. Probably set this to 1 or 2 /// to simulate optimistic or realistic relay chain behavior. @@ -54,19 +61,21 @@ pub struct MockValidationDataInherentDataProvider { /// Number of parachain blocks per relay chain epoch /// Mock epoch is computed by dividing `current_para_block` by this value. pub para_blocks_per_relay_epoch: u32, - /// Function to mock BABE one epoch ago randomness + /// Function to mock BABE one epoch ago randomness. pub relay_randomness_config: R, /// XCM messages and associated configuration information. pub xcm_config: MockXcmConfig, /// Inbound downward XCM messages to be injected into the block. pub raw_downward_messages: Vec>, - // Inbound Horizontal messages sorted by channel + // Inbound Horizontal messages sorted by channel. pub raw_horizontal_messages: Vec<(ParaId, Vec)>, // Additional key-value pairs that should be injected. pub additional_key_values: Option, Vec)>>, } +/// Something that can generate randomness. pub trait GenerateRandomness { + /// Generate the randomness using the given `input`. fn generate_randomness(&self, input: I) -> relay_chain::Hash; } @@ -86,8 +95,6 @@ impl GenerateRandomness for () { /// parachain's storage, and the corresponding relay data mocked. #[derive(Default)] pub struct MockXcmConfig { - /// The parachain id of the parachain being mocked. - pub para_id: ParaId, /// The starting state of the dmq_mqc_head. pub starting_dmq_mqc_head: relay_chain::Hash, /// The starting state of each parachain's mqc head @@ -114,7 +121,6 @@ impl MockXcmConfig { pub fn new, C: StorageProvider>( client: &C, parent_block: B::Hash, - para_id: ParaId, parachain_system_name: ParachainSystemName, ) -> Self { let starting_dmq_mqc_head = client @@ -147,7 +153,7 @@ impl MockXcmConfig { }) .unwrap_or_default(); - Self { para_id, starting_dmq_mqc_head, starting_hrmp_mqc_heads } + Self { starting_dmq_mqc_head, starting_hrmp_mqc_heads } } } @@ -159,13 +165,15 @@ impl> InherentDataProvider &self, inherent_data: &mut InherentData, ) -> Result<(), sp_inherents::Error> { + // Use the "sproof" (spoof proof) builder to build valid mock state root and proof. + let mut sproof_builder = + RelayStateSproofBuilder { para_id: self.para_id, ..Default::default() }; + // Calculate the mocked relay block based on the current para block let relay_parent_number = self.relay_offset + self.relay_blocks_per_para_block * self.current_para_block; - - // Use the "sproof" (spoof proof) builder to build valid mock state root and proof. - let mut sproof_builder = - RelayStateSproofBuilder { para_id: self.xcm_config.para_id, ..Default::default() }; + sproof_builder.current_slot = + ((relay_parent_number / RELAY_CHAIN_SLOT_DURATION_MILLIS) as u64).into(); // Process the downward messages and set up the correct head let mut downward_messages = Vec::new(); @@ -217,6 +225,9 @@ impl> InherentDataProvider sproof_builder.additional_key_values = key_values.clone() } + // Inject current para block head, if any + sproof_builder.included_para_head = self.current_para_block_head.clone(); + let (relay_parent_storage_root, proof) = sproof_builder.into_state_root_and_proof(); inherent_data.put_data( diff --git a/cumulus/client/pov-recovery/Cargo.toml b/cumulus/client/pov-recovery/Cargo.toml index 571935620d6d90b3aa1157124a2bae6fd73a19c2..7afe7fae34bd799ed75d557ad5f0ca5067743f7f 100644 --- a/cumulus/client/pov-recovery/Cargo.toml +++ b/cumulus/client/pov-recovery/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.28" futures-timer = "3.0.2" rand = "0.8.5" diff --git a/cumulus/client/pov-recovery/src/active_candidate_recovery.rs b/cumulus/client/pov-recovery/src/active_candidate_recovery.rs index 2c635320ff4ae6f68f33bb9da5ca545098851f65..c41c543f04d1f0d3f3a9fe7356dc7ab3ed5e5f11 100644 --- a/cumulus/client/pov-recovery/src/active_candidate_recovery.rs +++ b/cumulus/client/pov-recovery/src/active_candidate_recovery.rs @@ -56,6 +56,7 @@ impl ActiveCandidateRecovery { candidate.receipt.clone(), candidate.session_index, None, + None, tx, ), "ActiveCandidateRecovery", diff --git a/cumulus/client/relay-chain-interface/Cargo.toml b/cumulus/client/relay-chain-interface/Cargo.toml index 6df9847252fecf8e4bdcdec0ff9f830d6530668b..5962c68bba7a561b05a1710c2477b31964bbfe07 100644 --- a/cumulus/client/relay-chain-interface/Cargo.toml +++ b/cumulus/client/relay-chain-interface/Cargo.toml @@ -23,4 +23,4 @@ futures = "0.3.28" async-trait = "0.1.79" thiserror = { workspace = true } jsonrpsee-core = "0.22" -parity-scale-codec = "3.6.4" +parity-scale-codec = "3.6.12" diff --git a/cumulus/client/relay-chain-minimal-node/Cargo.toml b/cumulus/client/relay-chain-minimal-node/Cargo.toml index 6860b42a5078d48e74bbbd7ee64fbab43e5d5e13..88673a8f08fe37e4c5688b6bbec40fb36903c6dd 100644 --- a/cumulus/client/relay-chain-minimal-node/Cargo.toml +++ b/cumulus/client/relay-chain-minimal-node/Cargo.toml @@ -47,7 +47,7 @@ cumulus-relay-chain-interface = { path = "../relay-chain-interface" } cumulus-relay-chain-rpc-interface = { path = "../relay-chain-rpc-interface" } cumulus-primitives-core = { path = "../../primitives/core" } -array-bytes = "6.1" +array-bytes = "6.2.2" tracing = "0.1.37" async-trait = "0.1.79" futures = "0.3.28" diff --git a/cumulus/client/relay-chain-minimal-node/src/lib.rs b/cumulus/client/relay-chain-minimal-node/src/lib.rs index b84427c3a75a55e30d9867cbe8d45522a2d2f8c0..699393e2d48a7d6a0260246e9cef28b168c4a33a 100644 --- a/cumulus/client/relay-chain-minimal-node/src/lib.rs +++ b/cumulus/client/relay-chain-minimal-node/src/lib.rs @@ -285,5 +285,8 @@ fn build_request_response_protocol_receivers< let cfg = Protocol::ChunkFetchingV1.get_outbound_only_config::<_, Network>(request_protocol_names); config.add_request_response_protocol(cfg); + let cfg = + Protocol::ChunkFetchingV2.get_outbound_only_config::<_, Network>(request_protocol_names); + config.add_request_response_protocol(cfg); (collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver) } diff --git a/cumulus/client/relay-chain-rpc-interface/Cargo.toml b/cumulus/client/relay-chain-rpc-interface/Cargo.toml index 14981677289561040875b0951dbdbffb5854a439..2ec42ebca851e4d30a9ac17acd923f005956c287 100644 --- a/cumulus/client/relay-chain-rpc-interface/Cargo.toml +++ b/cumulus/client/relay-chain-rpc-interface/Cargo.toml @@ -32,7 +32,7 @@ tokio-util = { version = "0.7.8", features = ["compat"] } futures = "0.3.28" futures-timer = "3.0.2" -parity-scale-codec = "3.6.4" +parity-scale-codec = "3.6.12" jsonrpsee = { version = "0.22", features = ["ws-client"] } tracing = "0.1.37" async-trait = "0.1.79" diff --git a/cumulus/pallets/aura-ext/Cargo.toml b/cumulus/pallets/aura-ext/Cargo.toml index fe717596f9b307993f968ea0e7b58faef591dcf7..daff5ef8f482e82b80f341d5208cad51b23b7b1a 100644 --- a/cumulus/pallets/aura-ext/Cargo.toml +++ b/cumulus/pallets/aura-ext/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate diff --git a/cumulus/pallets/collator-selection/Cargo.toml b/cumulus/pallets/collator-selection/Cargo.toml index 25ca2fe057baf2a3e9c313556961615a3b14c2f7..f30802fa5d82ecb93e8610e7c7bb17a2a83cacb4 100644 --- a/cumulus/pallets/collator-selection/Cargo.toml +++ b/cumulus/pallets/collator-selection/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { workspace = true } -codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "3.0.0" } +codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "3.6.12" } rand = { version = "0.8.5", features = ["std_rng"], default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/cumulus/pallets/collator-selection/src/mock.rs b/cumulus/pallets/collator-selection/src/mock.rs index 4a440dfe1e92f26685415d260e0af9b1eb56a9a4..196184d62781e4a79968ed9834460e6bc39b0f98 100644 --- a/cumulus/pallets/collator-selection/src/mock.rs +++ b/cumulus/pallets/collator-selection/src/mock.rs @@ -46,7 +46,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = 42; } @@ -65,7 +64,6 @@ impl system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/cumulus/pallets/dmp-queue/Cargo.toml b/cumulus/pallets/dmp-queue/Cargo.toml index b2b24aeed72ba28ea320a90b8e725ce983fa1a07..687cda164fb0bd3d4aefb9d6b51f6735ef3a43c3 100644 --- a/cumulus/pallets/dmp-queue/Cargo.toml +++ b/cumulus/pallets/dmp-queue/Cargo.toml @@ -14,7 +14,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/cumulus/pallets/dmp-queue/src/lib.rs b/cumulus/pallets/dmp-queue/src/lib.rs index 79cc4bc895ec29b87eb95e629e0a9624fd7f62a5..9b3ec684febab81fb535c52118cbadb64b61e984 100644 --- a/cumulus/pallets/dmp-queue/src/lib.rs +++ b/cumulus/pallets/dmp-queue/src/lib.rs @@ -21,6 +21,7 @@ //! from the runtime once `Completed` was emitted. #![cfg_attr(not(feature = "std"), no_std)] +#![allow(deprecated)] // The pallet itself is deprecated. use migration::*; pub use pallet::*; @@ -38,6 +39,9 @@ pub type MaxDmpMessageLenOf = <::DmpSink as frame_support::traits::HandleMessage>::MaxMessageLen; #[frame_support::pallet] +#[deprecated( + note = "`cumulus-pallet-dmp-queue` will be removed after November 2024. It can be removed once its lazy migration completed. See ." +)] pub mod pallet { use super::*; use frame_support::{pallet_prelude::*, traits::HandleMessage, weights::WeightMeter}; diff --git a/cumulus/pallets/parachain-system/Cargo.toml b/cumulus/pallets/parachain-system/Cargo.toml index cc2e8943caad529ec05d6daa82598dc4c210aeee..1a6a19f2ab4a2523074bd02aa96053a0f7236140 100644 --- a/cumulus/pallets/parachain-system/Cargo.toml +++ b/cumulus/pallets/parachain-system/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] bytes = { version = "1.4.0", default-features = false } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } environmental = { version = "1.1.4", default-features = false } impl-trait-for-tuples = "0.2.1" log = { workspace = true } @@ -38,6 +38,7 @@ polkadot-parachain-primitives = { path = "../../../polkadot/parachain", default- polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", default-features = false } polkadot-runtime-common = { path = "../../../polkadot/runtime/common", default-features = false, optional = true } xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } +xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false } # Cumulus cumulus-pallet-parachain-system-proc-macro = { path = "proc-macro", default-features = false } @@ -95,6 +96,7 @@ std = [ "sp-tracing/std", "sp-trie/std", "trie-db/std", + "xcm-builder/std", "xcm/std", ] @@ -109,6 +111,7 @@ runtime-benchmarks = [ "polkadot-runtime-common/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", ] try-runtime = [ @@ -119,5 +122,3 @@ try-runtime = [ "polkadot-runtime-parachains/try-runtime", "sp-runtime/try-runtime", ] - -parameterized-consensus-hook = [] diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 54a1def59600dff5dd8b1484691dcb18fff5ce63..3b609a675db6036e408c66be9282eb1e0b21138a 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -30,7 +30,7 @@ use codec::{Decode, Encode}; use cumulus_primitives_core::{ relay_chain, AbridgedHostConfiguration, ChannelInfo, ChannelStatus, CollationInfo, - GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError, + GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, ListChannelInfos, MessageSendError, OutboundHrmpMessage, ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender, XcmpMessageHandler, XcmpMessageSource, }; @@ -55,7 +55,8 @@ use sp_runtime::{ BoundedSlice, FixedU128, RuntimeDebug, Saturating, }; use sp_std::{cmp, collections::btree_map::BTreeMap, prelude::*}; -use xcm::latest::XcmHash; +use xcm::{latest::XcmHash, VersionedLocation, VersionedXcm}; +use xcm_builder::InspectMessageQueues; mod benchmarking; pub mod migration; @@ -244,10 +245,6 @@ pub mod pallet { /// [`consensus_hook::ExpectParentIncluded`] here. This is only necessary in the case /// that collators aren't expected to have node versions that supply the included block /// in the relay-chain state proof. - /// - /// This config type is only available when the `parameterized-consensus-hook` crate feature - /// is activated. - #[cfg(feature = "parameterized-consensus-hook")] type ConsensusHook: ConsensusHook; } @@ -555,10 +552,8 @@ pub mod pallet { .expect("Invalid relay chain state proof"); // Update the desired maximum capacity according to the consensus hook. - #[cfg(feature = "parameterized-consensus-hook")] - let (consensus_hook_weight, capacity) = T::ConsensusHook::on_state_proof(&relay_state_proof); - #[cfg(not(feature = "parameterized-consensus-hook"))] - let (consensus_hook_weight, capacity) = ExpectParentIncluded::on_state_proof(&relay_state_proof); + let (consensus_hook_weight, capacity) = + T::ConsensusHook::on_state_proof(&relay_state_proof); total_weight += consensus_hook_weight; total_weight += Self::maybe_drop_included_ancestors(&relay_state_proof, capacity); // Deposit a log indicating the relay-parent storage root. @@ -1021,6 +1016,13 @@ impl FeeTracker for Pallet { } } +impl ListChannelInfos for Pallet { + fn outgoing_channels() -> Vec { + let Some(state) = RelevantMessagingState::::get() else { return Vec::new() }; + state.egress_channels.into_iter().map(|(id, _)| id).collect() + } +} + impl GetChannelInfo for Pallet { fn get_channel_status(id: ParaId) -> ChannelStatus { // Note, that we are using `relevant_messaging_state` which may be from the previous @@ -1608,6 +1610,19 @@ impl UpwardMessageSender for Pallet { } } +impl InspectMessageQueues for Pallet { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + use xcm::prelude::*; + + let messages: Vec> = PendingUpwardMessages::::get() + .iter() + .map(|encoded_message| VersionedXcm::<()>::decode(&mut &encoded_message[..]).unwrap()) + .collect(); + + vec![(VersionedLocation::V4(Parent.into()), messages)] + } +} + #[cfg(feature = "runtime-benchmarks")] impl polkadot_runtime_common::xcm_sender::EnsureForParachain for Pallet { fn ensure(para_id: ParaId) { @@ -1618,10 +1633,8 @@ impl polkadot_runtime_common::xcm_sender::EnsureForParachain for Pall } /// Something that can check the inherents of a block. -#[cfg_attr( - feature = "parameterized-consensus-hook", - deprecated = "consider switching to `cumulus-pallet-parachain-system::ConsensusHook`" -)] +#[deprecated(note = "This trait is deprecated and will be removed by September 2024. \ + Consider switching to `cumulus-pallet-parachain-system::ConsensusHook`")] pub trait CheckInherents { /// Check all inherents of the block. /// diff --git a/cumulus/pallets/parachain-system/src/mock.rs b/cumulus/pallets/parachain-system/src/mock.rs index fe89dfe68c67e4b5d9f9e046dcf2a780a292da0a..da904c0079a00a39dcca24c2d408d0bb381b2252 100644 --- a/cumulus/pallets/parachain-system/src/mock.rs +++ b/cumulus/pallets/parachain-system/src/mock.rs @@ -55,7 +55,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub Version: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("test"), impl_name: sp_version::create_runtime_str!("system-test"), @@ -74,7 +73,6 @@ parameter_types! { #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; - type BlockHashCount = BlockHashCount; type Version = Version; type OnSetCode = ParachainSetCode; } @@ -122,7 +120,7 @@ impl pallet_message_queue::Config for Test { type Size = u32; type QueueChangeHandler = (); type QueuePausedQuery = (); - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MaxWeight; type IdleMaxServiceWeight = (); diff --git a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs index ecab7a9a09311ae0f952a7842e9f1826b00adc69..956962fce157d3c5d090dd4bd8de78bba4d80405 100644 --- a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs +++ b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs @@ -80,6 +80,7 @@ environmental::environmental!(recorder: trait ProofSizeProvider); /// ensuring that the final storage root matches the storage root in the header of the block. In the /// end we return back the [`ValidationResult`] with all the required information for the validator. #[doc(hidden)] +#[allow(deprecated)] pub fn validate_block< B: BlockT, E: ExecuteBlock, @@ -186,6 +187,7 @@ where ) .expect("Invalid relay chain state proof"); + #[allow(deprecated)] let res = CI::check_inherents(&block, &relay_chain_proof); if !res.ok() { diff --git a/cumulus/pallets/session-benchmarking/Cargo.toml b/cumulus/pallets/session-benchmarking/Cargo.toml index 43fde4ea6009cce7d2dedceb815e2948beb80196..001c3d8aceac5a5db27aba87d666fdf83e92021c 100644 --- a/cumulus/pallets/session-benchmarking/Cargo.toml +++ b/cumulus/pallets/session-benchmarking/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parity-scale-codec = { version = "3.6.4", default-features = false } +parity-scale-codec = { version = "3.6.12", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } frame-support = { path = "../../../substrate/frame/support", default-features = false } diff --git a/cumulus/pallets/solo-to-para/Cargo.toml b/cumulus/pallets/solo-to-para/Cargo.toml index 417038d7833c5ca4ec4acf681cba73d24ab45c5e..17b0fb2a01662d517a49d1bfd669ed071caf0ed7 100644 --- a/cumulus/pallets/solo-to-para/Cargo.toml +++ b/cumulus/pallets/solo-to-para/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate diff --git a/cumulus/pallets/xcm/Cargo.toml b/cumulus/pallets/xcm/Cargo.toml index 9122e110fb92e51b0f85e3ba4136d30178d8ab7a..178d981702f2e6dc42d05556e20a86f50106b6ee 100644 --- a/cumulus/pallets/xcm/Cargo.toml +++ b/cumulus/pallets/xcm/Cargo.toml @@ -10,7 +10,7 @@ description = "Pallet for stuff specific to parachains' usage of XCM" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-std = { path = "../../../substrate/primitives/std", default-features = false } diff --git a/cumulus/pallets/xcmp-queue/Cargo.toml b/cumulus/pallets/xcmp-queue/Cargo.toml index ab196c6d3ec6a089d8099d6ae893631ac513e9d7..87602978521fc363539b2aeb81f5b485dbe409ea 100644 --- a/cumulus/pallets/xcmp-queue/Cargo.toml +++ b/cumulus/pallets/xcmp-queue/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"], default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -28,6 +28,7 @@ polkadot-runtime-common = { path = "../../../polkadot/runtime/common", default-f polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", default-features = false } xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm/xcm-executor", default-features = false } +xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false } # Cumulus cumulus-primitives-core = { path = "../../primitives/core", default-features = false } @@ -46,11 +47,8 @@ sp-core = { path = "../../../substrate/primitives/core" } pallet-balances = { path = "../../../substrate/frame/balances" } frame-support = { path = "../../../substrate/frame/support", features = ["experimental"] } -# Polkadot -xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder" } - # Cumulus -cumulus-pallet-parachain-system = { path = "../parachain-system", features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../parachain-system" } [features] default = ["std"] @@ -71,6 +69,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", "xcm-executor/std", "xcm/std", ] diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index 7de2fd8094213aaa0f8b8ef0dbb4539556b48465..5633f05f13bb81370a23512effefaf6ae1fb23fa 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -51,7 +51,7 @@ pub mod weights; pub use weights::WeightInfo; use bounded_collections::BoundedBTreeSet; -use codec::{Decode, DecodeLimit, Encode}; +use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; use cumulus_primitives_core::{ relay_chain::BlockNumber as RelayBlockNumber, ChannelStatus, GetChannelInfo, MessageSendError, ParaId, XcmpMessageFormat, XcmpMessageHandler, XcmpMessageSource, @@ -59,7 +59,7 @@ use cumulus_primitives_core::{ use frame_support::{ defensive, defensive_assert, - traits::{EnqueueMessage, EnsureOrigin, Get, QueueFootprint, QueuePausedQuery}, + traits::{Defensive, EnqueueMessage, EnsureOrigin, Get, QueueFootprint, QueuePausedQuery}, weights::{Weight, WeightMeter}, BoundedVec, }; @@ -68,9 +68,10 @@ use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery; use polkadot_runtime_parachains::FeeTracker; use scale_info::TypeInfo; use sp_core::MAX_POSSIBLE_ALLOCATION; -use sp_runtime::{FixedU128, RuntimeDebug, Saturating}; +use sp_runtime::{FixedU128, RuntimeDebug, Saturating, WeakBoundedVec}; use sp_std::prelude::*; -use xcm::{latest::prelude::*, VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH}; +use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH}; +use xcm_builder::InspectMessageQueues; use xcm_executor::traits::ConvertOrigin; pub use pallet::*; @@ -105,7 +106,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(migration::STORAGE_VERSION)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -132,6 +132,25 @@ pub mod pallet { #[pallet::constant] type MaxInboundSuspended: Get; + /// Maximal number of outbound XCMP channels that can have messages queued at the same time. + /// + /// If this is reached, then no further messages can be sent to channels that do not yet + /// have a message queued. This should be set to the expected maximum of outbound channels + /// which is determined by [`Self::ChannelInfo`]. It is important to set this large enough, + /// since otherwise the congestion control protocol will not work as intended and messages + /// may be dropped. This value increases the PoV and should therefore not be picked too + /// high. Governance needs to pay attention to not open more channels than this value. + #[pallet::constant] + type MaxActiveOutboundChannels: Get; + + /// The maximal page size for HRMP message pages. + /// + /// A lower limit can be set dynamically, but this is the hard-limit for the PoV worst case + /// benchmarking. The limit for the size of a message is slightly below this, since some + /// overhead is incurred for encoding the format. + #[pallet::constant] + type MaxPageSize: Get; + /// The origin that is allowed to resume or suspend the XCMP queue. type ControllerOrigin: EnsureOrigin; @@ -276,6 +295,10 @@ pub mod pallet { AlreadySuspended, /// The execution is already resumed. AlreadyResumed, + /// There are too many active outbound channels. + TooManyActiveOutboundChannels, + /// The message is too big. + TooBig, } /// The suspended inbound XCMP channels. All others are not suspended. @@ -297,19 +320,28 @@ pub mod pallet { /// case of the need to send a high-priority signal message this block. /// The bool is true if there is a signal message waiting to be sent. #[pallet::storage] - pub(super) type OutboundXcmpStatus = - StorageValue<_, Vec, ValueQuery>; + pub(super) type OutboundXcmpStatus = StorageValue< + _, + BoundedVec, + ValueQuery, + >; - // The new way of doing it: /// The messages outbound in a given XCMP channel. #[pallet::storage] - pub(super) type OutboundXcmpMessages = - StorageDoubleMap<_, Blake2_128Concat, ParaId, Twox64Concat, u16, Vec, ValueQuery>; + pub(super) type OutboundXcmpMessages = StorageDoubleMap< + _, + Blake2_128Concat, + ParaId, + Twox64Concat, + u16, + WeakBoundedVec, + ValueQuery, + >; /// Any signal messages waiting to be sent. #[pallet::storage] pub(super) type SignalMessages = - StorageMap<_, Blake2_128Concat, ParaId, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, ParaId, WeakBoundedVec, ValueQuery>; /// The configuration which controls the dynamics of the outbound queue. #[pallet::storage] @@ -331,15 +363,14 @@ pub mod pallet { StorageMap<_, Twox64Concat, ParaId, FixedU128, ValueQuery, InitialFactor>; } -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum OutboundState { Ok, Suspended, } /// Struct containing detailed information about the outbound channel. -#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, RuntimeDebug, MaxEncodedLen)] pub struct OutboundChannelDetails { /// The `ParaId` of the parachain that this channel is connected with. recipient: ParaId, @@ -375,7 +406,7 @@ impl OutboundChannelDetails { } } -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct QueueConfigData { /// The number of pages which must be in the queue for the other side to be told to suspend /// their sending. @@ -478,7 +509,10 @@ impl Pallet { { details } else { - all_channels.push(OutboundChannelDetails::new(recipient)); + all_channels.try_push(OutboundChannelDetails::new(recipient)).map_err(|e| { + log::error!("Failed to activate HRMP channel: {:?}", e); + MessageSendError::TooManyChannels + })?; all_channels .last_mut() .expect("can't be empty; a new element was just pushed; qed") @@ -503,7 +537,9 @@ impl Pallet { if page.len() + encoded_fragment.len() > max_message_size { return None } - page.extend_from_slice(&encoded_fragment[..]); + for frag in encoded_fragment.iter() { + page.try_push(*frag).ok()?; + } Some(page.len()) }, ) @@ -521,7 +557,10 @@ impl Pallet { new_page.extend_from_slice(&encoded_fragment[..]); let last_page_size = new_page.len(); let number_of_pages = (channel_details.last_index - channel_details.first_index) as u32; - >::insert(recipient, page_index, new_page); + let bounded_page = BoundedVec::::try_from(new_page) + .map_err(|_| MessageSendError::TooBig)?; + let bounded_page = WeakBoundedVec::force_from(bounded_page.into_inner(), None); + >::insert(recipient, page_index, bounded_page); >::put(all_channels); (number_of_pages, last_page_size) }; @@ -543,17 +582,24 @@ impl Pallet { /// Sends a signal to the `dest` chain over XCMP. This is guaranteed to be dispatched on this /// block. - fn send_signal(dest: ParaId, signal: ChannelSignal) { + fn send_signal(dest: ParaId, signal: ChannelSignal) -> Result<(), Error> { let mut s = >::get(); if let Some(details) = s.iter_mut().find(|item| item.recipient == dest) { details.signals_exist = true; } else { - s.push(OutboundChannelDetails::new(dest).with_signals()); + s.try_push(OutboundChannelDetails::new(dest).with_signals()) + .map_err(|_| Error::::TooManyActiveOutboundChannels)?; } - >::mutate(dest, |page| { - *page = (XcmpMessageFormat::Signals, signal).encode(); - }); + + let page = BoundedVec::::try_from( + (XcmpMessageFormat::Signals, signal).encode(), + ) + .map_err(|_| Error::::TooBig)?; + let page = WeakBoundedVec::force_from(page.into_inner(), None); + + >::insert(dest, page); >::put(s); + Ok(()) } fn suspend_channel(target: ParaId) { @@ -563,7 +609,9 @@ impl Pallet { defensive_assert!(ok, "WARNING: Attempt to suspend channel that was not Ok."); details.state = OutboundState::Suspended; } else { - s.push(OutboundChannelDetails::new(target).with_suspended_state()); + if s.try_push(OutboundChannelDetails::new(target).with_suspended_state()).is_err() { + defensive!("Cannot pause channel; too many outbound channels"); + } } }); } @@ -664,18 +712,25 @@ impl OnQueueChanged for Pallet { let suspended = suspended_channels.contains(¶); if suspended && fp.ready_pages <= resume_threshold { - Self::send_signal(para, ChannelSignal::Resume); - - suspended_channels.remove(¶); - >::put(suspended_channels); + if let Err(err) = Self::send_signal(para, ChannelSignal::Resume) { + log::error!("defensive: Could not send resumption signal to inbound channel of sibling {:?}: {:?}; channel remains suspended.", para, err); + } else { + suspended_channels.remove(¶); + >::put(suspended_channels); + } } else if !suspended && fp.ready_pages >= suspend_threshold { log::warn!("XCMP queue for sibling {:?} is full; suspending channel.", para); - Self::send_signal(para, ChannelSignal::Suspend); - if let Err(err) = suspended_channels.try_insert(para) { + if let Err(err) = Self::send_signal(para, ChannelSignal::Suspend) { + // It will retry if `drop_threshold` is not reached, but it could be too late. + log::error!( + "defensive: Could not send suspension signal; future messages may be dropped: {:?}", err + ); + } else if let Err(err) = suspended_channels.try_insert(para) { log::error!("Too many channels suspended; cannot suspend sibling {:?}: {:?}; further messages may be dropped.", para, err); + } else { + >::put(suspended_channels); } - >::put(suspended_channels); } } } @@ -842,7 +897,7 @@ impl XcmpMessageSource for Pallet { // since it's so unlikely then for now we just drop it. defensive!("WARNING: oversize message in queue - dropping"); } else { - result.push((para_id, page)); + result.push((para_id, page.into_inner())); } let max_total_size = match T::ChannelInfo::get_channel_info(para_id) { @@ -890,7 +945,9 @@ impl XcmpMessageSource for Pallet { let pruned = old_statuses_len - statuses.len(); // removing an item from status implies a message being sent, so the result messages must // be no less than the pruned channels. - statuses.rotate_left(result.len().saturating_sub(pruned)); + let _ = statuses.try_rotate_left(result.len().saturating_sub(pruned)).defensive_proof( + "Could not store HRMP channels config. Some HRMP channels may be broken.", + ); >::put(statuses); @@ -947,6 +1004,38 @@ impl SendXcm for Pallet { } } +impl InspectMessageQueues for Pallet { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + use xcm::prelude::*; + + OutboundXcmpMessages::::iter() + .map(|(para_id, _, messages)| { + let mut data = &messages[..]; + let decoded_format = + XcmpMessageFormat::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, &mut data) + .unwrap(); + if decoded_format != XcmpMessageFormat::ConcatenatedVersionedXcm { + panic!("Unexpected format.") + } + let mut decoded_messages = Vec::new(); + while !data.is_empty() { + let decoded_message = VersionedXcm::<()>::decode_with_depth_limit( + MAX_XCM_DECODE_DEPTH, + &mut data, + ) + .unwrap(); + decoded_messages.push(decoded_message); + } + + ( + VersionedLocation::V4((Parent, Parachain(para_id.into())).into()), + decoded_messages, + ) + }) + .collect() + } +} + impl FeeTracker for Pallet { type Id = ParaId; diff --git a/cumulus/pallets/xcmp-queue/src/migration.rs b/cumulus/pallets/xcmp-queue/src/migration.rs index 1702cd70bc2fb7e09cf15fbe21294bdb76b96ef1..b64982a893029f51aeb689d94d54066165ac40a3 100644 --- a/cumulus/pallets/xcmp-queue/src/migration.rs +++ b/cumulus/pallets/xcmp-queue/src/migration.rs @@ -16,6 +16,8 @@ //! A module that is responsible for migration of storage. +pub mod v5; + use crate::{Config, OverweightIndex, Pallet, QueueConfig, QueueConfigData, DEFAULT_POV_SIZE}; use cumulus_primitives_core::XcmpMessageFormat; use frame_support::{ @@ -25,7 +27,7 @@ use frame_support::{ }; /// The in-code storage version. -pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); +pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); pub const LOG: &str = "runtime::xcmp-queue-migration"; diff --git a/cumulus/pallets/xcmp-queue/src/migration/v5.rs b/cumulus/pallets/xcmp-queue/src/migration/v5.rs new file mode 100644 index 0000000000000000000000000000000000000000..247adab7108fac8a278ee81827a9e65e27c320f0 --- /dev/null +++ b/cumulus/pallets/xcmp-queue/src/migration/v5.rs @@ -0,0 +1,108 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Migrates the storage to version 5. + +use crate::*; +use cumulus_primitives_core::ListChannelInfos; +use frame_support::{pallet_prelude::*, traits::UncheckedOnRuntimeUpgrade}; + +/// Configs needed to run the V5 migration. +pub trait V5Config: Config { + /// List all outbound channels with their target `ParaId` and maximum message size. + type ChannelList: ListChannelInfos; +} + +/// Ensures that the storage migrates cleanly to V5. +/// +/// The migration itself is a no-op, but it checks that none of the `BoundedVec`s would truncate on +/// the next decode after the upgrade was applied. +pub type MigrateV4ToV5 = frame_support::migrations::VersionedMigration< + 4, + 5, + unversioned::UncheckedMigrateV4ToV5, + Pallet, + ::DbWeight, +>; + +// V4 storage aliases +mod v4 { + use super::*; + + #[frame_support::storage_alias] + pub(super) type OutboundXcmpStatus = + StorageValue, Vec, ValueQuery>; + + #[frame_support::storage_alias] + pub(super) type OutboundXcmpMessages = StorageDoubleMap< + Pallet, + Blake2_128Concat, + ParaId, + Twox64Concat, + u16, + Vec, + ValueQuery, + >; + + #[frame_support::storage_alias] + pub(super) type SignalMessages = + StorageMap, Blake2_128Concat, ParaId, Vec, ValueQuery>; +} + +// Private module to hide the migration. +mod unversioned { + /// Please use [`MigrateV4ToV5`] instead. + pub struct UncheckedMigrateV4ToV5(core::marker::PhantomData); +} + +impl UncheckedOnRuntimeUpgrade for unversioned::UncheckedMigrateV4ToV5 { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + Default::default() + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), sp_runtime::DispatchError> { + // We dont need any front-run protection for this since channels are opened by governance. + ensure!( + v4::OutboundXcmpStatus::::get().len() as u32 <= T::MaxActiveOutboundChannels::get(), + "Too many outbound channels. Close some channels or increase `MaxActiveOutboundChannels`." + ); + + ensure!(T::MaxPageSize::get() >= 16, "Sanity check failed: MaxPageSize too small"); + + // Check if any channels have a too large message max sizes. + let max_msg_len = T::MaxPageSize::get() - XcmpMessageFormat::max_encoded_len() as u32; + for channel in T::ChannelList::outgoing_channels() { + let info = T::ChannelInfo::get_channel_info(channel) + .expect("All listed channels must provide info"); + + if info.max_message_size > max_msg_len { + log::error!( + "Max message size for channel is too large. This means that the V5 \ + migration can be front-run and an attacker could place a large message just right \ + before the migration to make other messages un-decodable. Please either increase \ + `MaxPageSize` or decrease the `max_message_size` for this channel. Channel max: {}, \ + MaxPageSize: {}", + info.max_message_size, + max_msg_len + ); + return Err("Migration can be front-run".into()); + } + } + + Ok(()) + } +} diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 9d9a723cf8b538b604c45ff5b2bd366cd6f92c2d..e166a78ee822097ebadb613ed81dd344a6574bf0 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -52,7 +52,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = 42; } @@ -73,7 +72,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -178,6 +176,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } pub type XcmRouter = ( @@ -276,7 +275,11 @@ impl Config for Test { type ChannelInfo = MockedChannelInfo; type VersionWrapper = (); type XcmpQueue = EnqueueToLocalStorage>; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = SystemParachainAsSuperuser; type WeightInfo = (); @@ -318,10 +321,13 @@ impl GetChannelInfo for MockedChannelInfo { pub(crate) fn mk_page() -> Vec { let mut page = Vec::::new(); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + for i in 0..100 { page.extend(match i % 2 { - 0 => v2_xcm().encode(), - 1 => v3_xcm().encode(), + 0 => versioned_xcm(older_xcm_version).encode(), + 1 => versioned_xcm(newer_xcm_version).encode(), // We cannot push an undecodable XCM here since it would break the decode stream. // This is expected and the whole reason to introduce `MaybeDoubleEncodedVersionedXcm` // instead. @@ -332,12 +338,9 @@ pub(crate) fn mk_page() -> Vec { page } -pub(crate) fn v2_xcm() -> VersionedXcm<()> { - let instr = xcm::v2::Instruction::<()>::ClearOrigin; - VersionedXcm::V2(xcm::v2::Xcm::<()>(vec![instr; 3])) -} - -pub(crate) fn v3_xcm() -> VersionedXcm<()> { - let instr = xcm::v3::Instruction::<()>::Trap(1); - VersionedXcm::V3(xcm::v3::Xcm::<()>(vec![instr; 3])) +pub(crate) fn versioned_xcm(version: XcmVersion) -> VersionedXcm<()> { + let instr = Instruction::<()>::Trap(1); + VersionedXcm::from(Xcm::<()>(vec![instr; 3])) + .into_version(version) + .expect("Version conversion should work") } diff --git a/cumulus/pallets/xcmp-queue/src/tests.rs b/cumulus/pallets/xcmp-queue/src/tests.rs index 0b41095828f2f93810a2855d175ecd60a12853d7..cdf41e27f0b27aa99a8fc73fd42f98b02ee0e48e 100644 --- a/cumulus/pallets/xcmp-queue/src/tests.rs +++ b/cumulus/pallets/xcmp-queue/src/tests.rs @@ -14,7 +14,7 @@ // limitations under the License. use super::{ - mock::{mk_page, v2_xcm, v3_xcm, EnqueuedMessages, HRMP_PARA_ID}, + mock::{mk_page, versioned_xcm, EnqueuedMessages, HRMP_PARA_ID}, *, }; use XcmpMessageFormat::*; @@ -520,7 +520,7 @@ fn hrmp_signals_are_prioritized() { }); // But a signal gets prioritized instead of the messages: - XcmpQueue::send_signal(sibling_para_id.into(), ChannelSignal::Suspend); + assert_ok!(XcmpQueue::send_signal(sibling_para_id.into(), ChannelSignal::Suspend)); let taken = XcmpQueue::take_outbound_messages(130); assert_eq!( @@ -536,8 +536,8 @@ fn hrmp_signals_are_prioritized() { #[test] fn maybe_double_encoded_versioned_xcm_works() { // pre conditions - assert_eq!(VersionedXcm::<()>::V2(Default::default()).encode(), &[2, 0]); assert_eq!(VersionedXcm::<()>::V3(Default::default()).encode(), &[3, 0]); + assert_eq!(VersionedXcm::<()>::V4(Default::default()).encode(), &[4, 0]); } // Now also testing a page instead of just concat messages. @@ -545,15 +545,18 @@ fn maybe_double_encoded_versioned_xcm_works() { fn maybe_double_encoded_versioned_xcm_decode_page_works() { let page = mk_page(); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + // Now try to decode the page. let input = &mut &page[..]; for i in 0..100 { match (i % 2, VersionedXcm::<()>::decode(input)) { (0, Ok(xcm)) => { - assert_eq!(xcm, v2_xcm()); + assert_eq!(xcm, versioned_xcm(older_xcm_version)); }, (1, Ok(xcm)) => { - assert_eq!(xcm, v3_xcm()); + assert_eq!(xcm, versioned_xcm(newer_xcm_version)); }, unexpected => unreachable!("{:?}", unexpected), } @@ -568,14 +571,17 @@ fn take_first_concatenated_xcm_works() { let page = mk_page(); let input = &mut &page[..]; + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + for i in 0..100 { let xcm = XcmpQueue::take_first_concatenated_xcm(input, &mut WeightMeter::new()).unwrap(); match (i % 2, xcm) { (0, data) | (2, data) => { - assert_eq!(data, v2_xcm().encode()); + assert_eq!(data, versioned_xcm(older_xcm_version).encode()); }, (1, data) | (3, data) => { - assert_eq!(data, v3_xcm().encode()); + assert_eq!(data, versioned_xcm(newer_xcm_version).encode()); }, unexpected => unreachable!("{:?}", unexpected), } @@ -844,3 +850,43 @@ fn verify_fee_factor_increase_and_decrease() { assert!(DeliveryFeeFactor::::get(sibling_para_id) < FixedU128::from_float(1.63)); }); } + +#[test] +fn get_messages_works() { + new_test_ext().execute_with(|| { + use xcm_builder::InspectMessageQueues; + let sibling_para_id = ParaId::from(2001); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(sibling_para_id); + let destination: Location = (Parent, Parachain(sibling_para_id.into())).into(); + let other_sibling_para_id = ParaId::from(2002); + let other_destination: Location = (Parent, Parachain(other_sibling_para_id.into())).into(); + let message = Xcm(vec![ClearOrigin]); + assert_ok!(send_xcm::(destination.clone(), message.clone())); + assert_ok!(send_xcm::(destination.clone(), message.clone())); + assert_ok!(send_xcm::(destination.clone(), message.clone())); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(other_sibling_para_id); + assert_ok!(send_xcm::(other_destination.clone(), message.clone())); + assert_ok!(send_xcm::(other_destination.clone(), message)); + let queued_messages = XcmpQueue::get_messages(); + assert_eq!( + queued_messages, + vec![ + ( + VersionedLocation::V4(other_destination), + vec![ + VersionedXcm::V4(Xcm(vec![ClearOrigin])), + VersionedXcm::V4(Xcm(vec![ClearOrigin])), + ], + ), + ( + VersionedLocation::V4(destination), + vec![ + VersionedXcm::V4(Xcm(vec![ClearOrigin])), + VersionedXcm::V4(Xcm(vec![ClearOrigin])), + VersionedXcm::V4(Xcm(vec![ClearOrigin])), + ], + ), + ], + ); + }); +} diff --git a/cumulus/parachains/chain-specs/asset-hub-kusama.json b/cumulus/parachains/chain-specs/asset-hub-kusama.json index 66a705a40869ce6eb3fe2ac7a028ce68c784c18c..00e342381ee1c06a65bfaa51111fb55643cfabba 100644 --- a/cumulus/parachains/chain-specs/asset-hub-kusama.json +++ b/cumulus/parachains/chain-specs/asset-hub-kusama.json @@ -11,8 +11,8 @@ "/dns/boot.stake.plus/tcp/34334/wss/p2p/12D3KooWAzSSZ7jLqMw1WPomYEKCYANQaKemXQ8BKoFvNEvfmdqR", "/dns/boot.metaspan.io/tcp/26052/p2p/12D3KooW9z9hKqe3mqYAp5UJMhZiCqhkTHyiR43fegnGmTJ3JAba", "/dns/boot.metaspan.io/tcp/26056/wss/p2p/12D3KooW9z9hKqe3mqYAp5UJMhZiCqhkTHyiR43fegnGmTJ3JAba", - "/dns/boot-cr.gatotech.network/tcp/33210/p2p/12D3KooWRMUYeWMPkadDG8baX9j1e95fspfp8MhPGym5BQza7Fm5", - "/dns/boot-cr.gatotech.network/tcp/35210/wss/p2p/12D3KooWRMUYeWMPkadDG8baX9j1e95fspfp8MhPGym5BQza7Fm5", + "/dns/boot.gatotech.network/tcp/33210/p2p/12D3KooWRMUYeWMPkadDG8baX9j1e95fspfp8MhPGym5BQza7Fm5", + "/dns/boot.gatotech.network/tcp/35210/wss/p2p/12D3KooWRMUYeWMPkadDG8baX9j1e95fspfp8MhPGym5BQza7Fm5", "/dns/statemine-bootnode.turboflakes.io/tcp/30320/p2p/12D3KooWN2Qqvp5wWgjbBMpbqhKgvSibSHfomP5VWVD9VCn3VrV4", "/dns/statemine-bootnode.turboflakes.io/tcp/30420/wss/p2p/12D3KooWN2Qqvp5wWgjbBMpbqhKgvSibSHfomP5VWVD9VCn3VrV4", "/dns/boot-node.helikon.io/tcp/10210/p2p/12D3KooWFXRQce3aMgZMn5SxvHtYH4PsR63TZLf8LrnBsEVTyzdr", diff --git a/cumulus/parachains/chain-specs/asset-hub-polkadot.json b/cumulus/parachains/chain-specs/asset-hub-polkadot.json index 16caa52ba91376ed30187c89d249ff38ed1ea42a..22b11757b66bb7103152997b4d276378f0960700 100644 --- a/cumulus/parachains/chain-specs/asset-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/asset-hub-polkadot.json @@ -11,8 +11,8 @@ "/dns/boot.stake.plus/tcp/35334/wss/p2p/12D3KooWFrQjYaPZSSLLxEVmoaHFcrF6VoY4awG4KRSLaqy3JCdQ", "/dns/boot.metaspan.io/tcp/16052/p2p/12D3KooWLwiJuvqQUB4kYaSjLenFKH9dWZhGZ4qi7pSb3sUYU651", "/dns/boot.metaspan.io/tcp/16056/wss/p2p/12D3KooWLwiJuvqQUB4kYaSjLenFKH9dWZhGZ4qi7pSb3sUYU651", - "/dns/boot-cr.gatotech.network/tcp/33110/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", - "/dns/boot-cr.gatotech.network/tcp/35110/wss/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", + "/dns/boot.gatotech.network/tcp/33110/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", + "/dns/boot.gatotech.network/tcp/35110/wss/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", "/dns/statemint-bootnode.turboflakes.io/tcp/30315/p2p/12D3KooWL8CyLww3m3pRySQGGYGNJhWDMqko3j5xi67ckP7hDUvo", "/dns/statemint-bootnode.turboflakes.io/tcp/30415/wss/p2p/12D3KooWL8CyLww3m3pRySQGGYGNJhWDMqko3j5xi67ckP7hDUvo", "/dns/boot-node.helikon.io/tcp/10220/p2p/12D3KooW9uybhguhDjVJc3U3kgZC3i8rWmAnSpbnJkmuR7C6ZsRW", diff --git a/cumulus/parachains/chain-specs/asset-hub-westend.json b/cumulus/parachains/chain-specs/asset-hub-westend.json index 3752213e702eb8d1ef86e042531cc1f6fdec2767..830eb2c5918069ac46fed21a27360ba92c5aebce 100644 --- a/cumulus/parachains/chain-specs/asset-hub-westend.json +++ b/cumulus/parachains/chain-specs/asset-hub-westend.json @@ -13,8 +13,8 @@ "/dns/boot.stake.plus/tcp/33334/wss/p2p/12D3KooWNiB27rpXX7EYongoWWUeRKzLQxWGms6MQU2B9LX7Ztzo", "/dns/boot.metaspan.io/tcp/36052/p2p/12D3KooWBCqfNb6Y39DXTr4UBWXyjuS3hcZM1qTbHhDXxF6HkAJJ", "/dns/boot.metaspan.io/tcp/36056/wss/p2p/12D3KooWBCqfNb6Y39DXTr4UBWXyjuS3hcZM1qTbHhDXxF6HkAJJ", - "/dns/boot-cr.gatotech.network/tcp/33310/p2p/12D3KooWMSW6hr8KcNBhGFN1bg8kYC76o67PnuDEbxRhxacW6dui", - "/dns/boot-cr.gatotech.network/tcp/35310/wss/p2p/12D3KooWMSW6hr8KcNBhGFN1bg8kYC76o67PnuDEbxRhxacW6dui", + "/dns/boot.gatotech.network/tcp/33310/p2p/12D3KooWMSW6hr8KcNBhGFN1bg8kYC76o67PnuDEbxRhxacW6dui", + "/dns/boot.gatotech.network/tcp/35310/wss/p2p/12D3KooWMSW6hr8KcNBhGFN1bg8kYC76o67PnuDEbxRhxacW6dui", "/dns/westmint-bootnode.turboflakes.io/tcp/30325/p2p/12D3KooWHU4qqSyqKdbXdrCTMXUJxxueaZjqpqSaQqYiFPw6XqEx", "/dns/westmint-bootnode.turboflakes.io/tcp/30425/wss/p2p/12D3KooWHU4qqSyqKdbXdrCTMXUJxxueaZjqpqSaQqYiFPw6XqEx", "/dns/boot-node.helikon.io/tcp/10200/p2p/12D3KooWMRY8wb7rMT81LLuivvsy6ahUxKHQgYJw4zm1hC1uYLxb", diff --git a/cumulus/parachains/chain-specs/bridge-hub-kusama.json b/cumulus/parachains/chain-specs/bridge-hub-kusama.json index 6644ea41ab748548d3c6dcbd06951522672dbb53..46b33ed44c1a823daf25a2e834abc602cb35f0dc 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-kusama.json +++ b/cumulus/parachains/chain-specs/bridge-hub-kusama.json @@ -11,8 +11,8 @@ "/dns/boot.stake.plus/tcp/41334/wss/p2p/12D3KooWBzbs2jsXjG5dipktGPKaUm9XWvkmeJFsEAGkVt946Aa7", "/dns/boot.metaspan.io/tcp/26032/p2p/12D3KooWKfuSaZrLNz43PDgM4inMALXRHTSh2WBuqQtZRq8zmT1Z", "/dns/boot.metaspan.io/tcp/26036/wss/p2p/12D3KooWKfuSaZrLNz43PDgM4inMALXRHTSh2WBuqQtZRq8zmT1Z", - "/dns/boot-cr.gatotech.network/tcp/33230/p2p/12D3KooWFQFmg8UqAYLDNc2onySB6o5LLvpbx3eXZVqz9YFxAmXs", - "/dns/boot-cr.gatotech.network/tcp/35230/wss/p2p/12D3KooWFQFmg8UqAYLDNc2onySB6o5LLvpbx3eXZVqz9YFxAmXs", + "/dns/boot.gatotech.network/tcp/33230/p2p/12D3KooWFQFmg8UqAYLDNc2onySB6o5LLvpbx3eXZVqz9YFxAmXs", + "/dns/boot.gatotech.network/tcp/35230/wss/p2p/12D3KooWFQFmg8UqAYLDNc2onySB6o5LLvpbx3eXZVqz9YFxAmXs", "/dns/bridge-hub-kusama-bootnode.turboflakes.io/tcp/30615/p2p/12D3KooWE3dJXbwA5SQqbDNxHfj7BXJRcy2KiXWjJY4VUMKoa7S2", "/dns/bridge-hub-kusama-bootnode.turboflakes.io/tcp/30715/wss/p2p/12D3KooWE3dJXbwA5SQqbDNxHfj7BXJRcy2KiXWjJY4VUMKoa7S2", "/dns/boot-node.helikon.io/tcp/10250/p2p/12D3KooWDJLkhqQdXcVKWX7CqJHnpAY6PzrPc4ZG2CUWnARbmguy", diff --git a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json index c51c5eff89b86a0ce553bbcfc472f6fb5cf0d535..0a642caddb7684b35b74eb4b115157667f4370ba 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json @@ -9,8 +9,10 @@ "/dns/polkadot-bridge-hub-connect-a-1.polkadot.io/tcp/443/wss/p2p/12D3KooWG4ypDHLKGCv4BZ6PuaGUwQHKAH6p2D6arR2uQ1eiR1T3", "/dns/polkadot-bridge-hub-boot-ng.dwellir.com/tcp/30339/p2p/12D3KooWPZ38PL3PhRVcUVYDNn7nRcZF8MykmWWLBKeDV2yna1vV", "/dns/polkadot-bridge-hub-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWPZ38PL3PhRVcUVYDNn7nRcZF8MykmWWLBKeDV2yna1vV", - "/dns/boot-cr.gatotech.network/tcp/33130/p2p/12D3KooWCnFzfEdd7MwUNrrDv66FuS2DM5MGuiaB4y48XS7qNjF6", - "/dns/boot-cr.gatotech.network/tcp/35130/wss/p2p/12D3KooWCnFzfEdd7MwUNrrDv66FuS2DM5MGuiaB4y48XS7qNjF6", + "/dns/boot.gatotech.network/tcp/33130/p2p/12D3KooWCnFzfEdd7MwUNrrDv66FuS2DM5MGuiaB4y48XS7qNjF6", + "/dns/boot.gatotech.network/tcp/35130/wss/p2p/12D3KooWCnFzfEdd7MwUNrrDv66FuS2DM5MGuiaB4y48XS7qNjF6", + "/dns/boot.stake.plus/tcp/42333/p2p/12D3KooWEoTCu22Uab6prbfcD1FPpPZmfhkAVeMZQJ3fHnkCVmJz", + "/dns/boot.stake.plus/tcp/42334/wss/p2p/12D3KooWEoTCu22Uab6prbfcD1FPpPZmfhkAVeMZQJ3fHnkCVmJz", "/dns/bridge-hub-polkadot-bootnode.turboflakes.io/tcp/30610/p2p/12D3KooWNEgaQRQHJHvGDh8Rg4RyLmDCCz3yAf2gAdHZZJAUUD8Q", "/dns/bridge-hub-polkadot-bootnode.turboflakes.io/tcp/30710/wss/p2p/12D3KooWNEgaQRQHJHvGDh8Rg4RyLmDCCz3yAf2gAdHZZJAUUD8Q", "/dns/boot.metaspan.io/tcp/16032/p2p/12D3KooWQTfRnrK3FfbrotpSP5RVJbjBHVBSu8VSzhj9qcvjaqnZ", diff --git a/cumulus/parachains/chain-specs/bridge-hub-westend.json b/cumulus/parachains/chain-specs/bridge-hub-westend.json index 5140071ec44ca1956b01f608ce85ca2d6177a617..c07857894f71663fe80c35f775ea56ddd55accc4 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-westend.json +++ b/cumulus/parachains/chain-specs/bridge-hub-westend.json @@ -11,8 +11,10 @@ "/dns/westend-bridge-hub-collator-node-1.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWBpvudthz61XC4oP2YYFFJdhWohBeQ1ffn1BMSGWhapjd", "/dns/westend-bridge-hub-boot-ng.dwellir.com/tcp/30338/p2p/12D3KooWJWWRYTAwBLqYkh7iMBGDr5ouJ3MHj7M3fZ7zWS4zEk6F", "/dns/westend-bridge-hub-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWJWWRYTAwBLqYkh7iMBGDr5ouJ3MHj7M3fZ7zWS4zEk6F", - "/dns/boot-cr.gatotech.network/tcp/33330/p2p/12D3KooWJHG6qznPzTSEbuujHNcvyzBZcR9zNRPFcXWUaoVWZBEw", - "/dns/boot-cr.gatotech.network/tcp/35330/wss/p2p/12D3KooWJHG6qznPzTSEbuujHNcvyzBZcR9zNRPFcXWUaoVWZBEw", + "/dns/boot.stake.plus/tcp/40333/p2p/12D3KooWPGMsGPdGJx6HrByiKUyz91wgUHmjG5UXTmkJ9tUphAQn", + "/dns/boot.stake.plus/tcp/40334/wss/p2p/12D3KooWPGMsGPdGJx6HrByiKUyz91wgUHmjG5UXTmkJ9tUphAQn", + "/dns/boot.gatotech.network/tcp/33330/p2p/12D3KooWJHG6qznPzTSEbuujHNcvyzBZcR9zNRPFcXWUaoVWZBEw", + "/dns/boot.gatotech.network/tcp/35330/wss/p2p/12D3KooWJHG6qznPzTSEbuujHNcvyzBZcR9zNRPFcXWUaoVWZBEw", "/dns/bridge-hub-westend-bootnode.turboflakes.io/tcp/30620/p2p/12D3KooWLeExhPWCDUjcxCdzxTP5TpPbNBVG5t9MPvk1dZUM5naU", "/dns/bridge-hub-westend-bootnode.turboflakes.io/tcp/30720/wss/p2p/12D3KooWLeExhPWCDUjcxCdzxTP5TpPbNBVG5t9MPvk1dZUM5naU", "/dns/boot.metaspan.io/tcp/36032/p2p/12D3KooWPaLsu3buByBnGFQnp5UP4q1S652dGVft92TFeChizFir", diff --git a/cumulus/parachains/chain-specs/collectives-polkadot.json b/cumulus/parachains/chain-specs/collectives-polkadot.json index ce80e21ae625e813be0f71245bc454cb284455f3..b2f3ff812d05da83d28be150de5a00466cc450bd 100644 --- a/cumulus/parachains/chain-specs/collectives-polkadot.json +++ b/cumulus/parachains/chain-specs/collectives-polkadot.json @@ -11,8 +11,8 @@ "/dns/boot.stake.plus/tcp/37334/wss/p2p/12D3KooWRgFfEtwPo3xorKGYALRHRteKNgF37iN9q8xTLPYc34LA", "/dns/boot.metaspan.io/tcp/16072/p2p/12D3KooWJWTTu2t2yg5bFRH6tjEpfzKwZir5R9JRRjQpgFPXdDfp", "/dns/boot.metaspan.io/tcp/16076/wss/p2p/12D3KooWJWTTu2t2yg5bFRH6tjEpfzKwZir5R9JRRjQpgFPXdDfp", - "/dns/boot-cr.gatotech.network/tcp/33120/p2p/12D3KooWGZsa9tSeLQ1VeC996e1YsCPuyRYMipHQuXikPjcKcpVQ", - "/dns/boot-cr.gatotech.network/tcp/35120/wss/p2p/12D3KooWGZsa9tSeLQ1VeC996e1YsCPuyRYMipHQuXikPjcKcpVQ", + "/dns/boot.gatotech.network/tcp/33120/p2p/12D3KooWGZsa9tSeLQ1VeC996e1YsCPuyRYMipHQuXikPjcKcpVQ", + "/dns/boot.gatotech.network/tcp/35120/wss/p2p/12D3KooWGZsa9tSeLQ1VeC996e1YsCPuyRYMipHQuXikPjcKcpVQ", "/dns/collectives-polkadot-bootnode.turboflakes.io/tcp/30605/p2p/12D3KooWPyzM7eX64J4aG8uRfSARakDVtiEtthEM8FUjrLWAg2sC", "/dns/collectives-polkadot-bootnode.turboflakes.io/tcp/30705/wss/p2p/12D3KooWPyzM7eX64J4aG8uRfSARakDVtiEtthEM8FUjrLWAg2sC", "/dns/boot-node.helikon.io/tcp/10230/p2p/12D3KooWS8CBz4P5CBny9aBy2EQUvAExFo9PUVT57X8r3zWMFkXT", diff --git a/cumulus/parachains/chain-specs/collectives-westend.json b/cumulus/parachains/chain-specs/collectives-westend.json index fdd6348f02a9ce7b07c0483847a348c7b334f5c2..8680e3a7671dcb402f7f445eea44baccbe79b00d 100644 --- a/cumulus/parachains/chain-specs/collectives-westend.json +++ b/cumulus/parachains/chain-specs/collectives-westend.json @@ -13,8 +13,8 @@ "/dns/boot.stake.plus/tcp/38334/wss/p2p/12D3KooWQoVsFCfgu21iu6kdtQsU9T6dPn1wsyLn1U34yPerR6zQ", "/dns/boot.metaspan.io/tcp/36072/p2p/12D3KooWEf2QXWq5pAbFJLfbnexA7KYtRRDSPkqTP64n1KtdsdV2", "/dns/boot.metaspan.io/tcp/36076/wss/p2p/12D3KooWEf2QXWq5pAbFJLfbnexA7KYtRRDSPkqTP64n1KtdsdV2", - "/dns/boot-cr.gatotech.network/tcp/33320/p2p/12D3KooWMedtdBGiSn7HLZusHwafXkZAdmWD18ciGQBfS4X1fv9K", - "/dns/boot-cr.gatotech.network/tcp/35320/wss/p2p/12D3KooWMedtdBGiSn7HLZusHwafXkZAdmWD18ciGQBfS4X1fv9K", + "/dns/boot.gatotech.network/tcp/33320/p2p/12D3KooWMedtdBGiSn7HLZusHwafXkZAdmWD18ciGQBfS4X1fv9K", + "/dns/boot.gatotech.network/tcp/35320/wss/p2p/12D3KooWMedtdBGiSn7HLZusHwafXkZAdmWD18ciGQBfS4X1fv9K", "/dns/collectives-westend-bootnode.turboflakes.io/tcp/30600/p2p/12D3KooWAe9CFXp6je3TAPQJE135KRemTLSqEqQBZMFwJontrThZ", "/dns/collectives-westend-bootnode.turboflakes.io/tcp/30700/wss/p2p/12D3KooWAe9CFXp6je3TAPQJE135KRemTLSqEqQBZMFwJontrThZ", "/dns/boot-node.helikon.io/tcp/10260/p2p/12D3KooWMzfnt29VAmrJHQcJU6Vfn4RsMbqPqgyWHqt9VTTAbSrL", diff --git a/cumulus/parachains/chain-specs/coretime-kusama.json b/cumulus/parachains/chain-specs/coretime-kusama.json index ebb79e03f045565a915800afee4574491eaa3bc7..4ebaab82e75242f5c50c725cfdbde980c7e24459 100644 --- a/cumulus/parachains/chain-specs/coretime-kusama.json +++ b/cumulus/parachains/chain-specs/coretime-kusama.json @@ -6,7 +6,25 @@ "/dns/kusama-coretime-connect-a-0.polkadot.io/tcp/30334/p2p/12D3KooWR7Biy6nPgQFhk2eYP62pAkcFA6he9RUFURTDh7ewTjpo", "/dns/kusama-coretime-connect-a-1.polkadot.io/tcp/30334/p2p/12D3KooWAGFiMZDF9RxdacrkenzGdo8nhfSe9EXofHc5mHeJ9vGX", "/dns/kusama-coretime-connect-a-0.polkadot.io/tcp/443/wss/p2p/12D3KooWR7Biy6nPgQFhk2eYP62pAkcFA6he9RUFURTDh7ewTjpo", - "/dns/kusama-coretime-connect-a-1.polkadot.io/tcp/443/wss/p2p/12D3KooWAGFiMZDF9RxdacrkenzGdo8nhfSe9EXofHc5mHeJ9vGX" + "/dns/kusama-coretime-connect-a-1.polkadot.io/tcp/443/wss/p2p/12D3KooWAGFiMZDF9RxdacrkenzGdo8nhfSe9EXofHc5mHeJ9vGX", + "/dns/boot.metaspan.io/tcp/33024/p2p/12D3KooWPmwMhG54ixDv2b3sCfYEJ1DWDrjaduBCBwqFFdqvVsmS", + "/dns/boot.metaspan.io/tcp/33026/wss/p2p/12D3KooWPmwMhG54ixDv2b3sCfYEJ1DWDrjaduBCBwqFFdqvVsmS", + "/dns/boot.stake.plus/tcp/47333/p2p/12D3KooWKKKoyywqdkkpZzCzVWt5VXEk5PbS9tUm635L5ohyf8bU", + "/dns/boot.stake.plus/tcp/47334/wss/p2p/12D3KooWKKKoyywqdkkpZzCzVWt5VXEk5PbS9tUm635L5ohyf8bU", + "/dns/coretime-kusama-boot-ng.dwellir.com/tcp/30358/p2p/12D3KooWSoPisbYQTAj79Dtsxx1qAiEFTouvXCfNJ1A3SQWQzuct", + "/dns/coretime-kusama-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWSoPisbYQTAj79Dtsxx1qAiEFTouvXCfNJ1A3SQWQzuct", + "/dns/boot.gatotech.network/tcp/33250/p2p/12D3KooWMpgcWr5pb7em7rWaQV4J6P2kn3YCjCeP1ESMsJPffn1a", + "/dns/boot.gatotech.network/tcp/35250/wss/p2p/12D3KooWMpgcWr5pb7em7rWaQV4J6P2kn3YCjCeP1ESMsJPffn1a", + "/dns/kcore16.rotko.net/tcp/33726/p2p/12D3KooWCyPSkk5cq2eEdw1qHizfa6UT4QggSarCEtcvNXpnod8B", + "/dns/kcore16.rotko.net/tcp/35726/wss/p2p/12D3KooWCyPSkk5cq2eEdw1qHizfa6UT4QggSarCEtcvNXpnod8B", + "/dns/coretime-kusama-bootnode.turboflakes.io/tcp/30660/p2p/12D3KooWHTr9GLvJEnGYKCu3FHC3DwqBiFg9MQUWsjPCP4YH5xyf", + "/dns/coretime-kusama-bootnode.turboflakes.io/tcp/30760/wss/p2p/12D3KooWHTr9GLvJEnGYKCu3FHC3DwqBiFg9MQUWsjPCP4YH5xyf", + "/dns/coretime-kusama.bootnodes.polkadotters.com/tcp/30371/p2p/12D3KooWHy7TAuK6EoVij2tfaeh3KkaEJxhTmumbEom3HfRnSEsp", + "/dns/coretime-kusama.bootnodes.polkadotters.com/tcp/30373/wss/p2p/12D3KooWHy7TAuK6EoVij2tfaeh3KkaEJxhTmumbEom3HfRnSEsp", + "/dns/boot-node.helikon.io/tcp/7420/p2p/12D3KooWK4eKFpYftyuLdBdXrkdJXHKt7KZcNLb92Ufkvo17B9T2", + "/dns/boot-node.helikon.io/tcp/7422/wss/p2p/12D3KooWK4eKFpYftyuLdBdXrkdJXHKt7KZcNLb92Ufkvo17B9T2", + "/dns/coretime-kusama-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWFzW9AgxNfkVNCepVByS7URDCRDAA5p3XzBLVptqZvWoL", + "/dns/coretime-kusama-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWFzW9AgxNfkVNCepVByS7URDCRDAA5p3XzBLVptqZvWoL" ], "telemetryEndpoints": null, "protocolId": null, @@ -89,4 +107,4 @@ "childrenDefault": {} } } -} \ No newline at end of file +} diff --git a/cumulus/parachains/chain-specs/coretime-westend.json b/cumulus/parachains/chain-specs/coretime-westend.json index 85e129e684896a137be58727d1190ddfb3f81b33..586879b9abc2f043f170f20523132a1c7e02e74d 100644 --- a/cumulus/parachains/chain-specs/coretime-westend.json +++ b/cumulus/parachains/chain-specs/coretime-westend.json @@ -5,15 +5,30 @@ "bootNodes": [ "/dns/westend-coretime-collator-node-0.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWP93Dzk8T7GWxyWw9jhLcz8Pksokk3R9vL2eEH337bNkT", "/dns/westend-coretime-collator-node-1.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWMh2imeAzsZKGQgm2cv6Uoep3GBYtwGfujt1bs5YfVzkH", + "/dns/coretime-westend-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWK7Zj1mCPg6h3eMp7v6akJ1o6AocRr59NLusDwBXQgrhw", + "/dns/coretime-westend-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWK7Zj1mCPg6h3eMp7v6akJ1o6AocRr59NLusDwBXQgrhw", "/dns/westend-coretime-collator-node-0.parity-testnet.parity.io/tcp/30335/ws/p2p/12D3KooWP93Dzk8T7GWxyWw9jhLcz8Pksokk3R9vL2eEH337bNkT", "/dns/westend-coretime-collator-node-1.parity-testnet.parity.io/tcp/30335/ws/p2p/12D3KooWMh2imeAzsZKGQgm2cv6Uoep3GBYtwGfujt1bs5YfVzkH", "/dns/westend-coretime-collator-node-0.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWP93Dzk8T7GWxyWw9jhLcz8Pksokk3R9vL2eEH337bNkT", "/dns/westend-coretime-collator-node-1.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWMh2imeAzsZKGQgm2cv6Uoep3GBYtwGfujt1bs5YfVzkH", "/dns/boot.metaspan.io/tcp/33019/p2p/12D3KooWCa1uNnEZqiqJY9jkKNQxwSLGPeZ5MjWHhjQMGwga9JMM", + "/dns/boot.metaspan.io/tcp/33020/wss/p2p/12D3KooWCa1uNnEZqiqJY9jkKNQxwSLGPeZ5MjWHhjQMGwga9JMM", "/dns/boot-node.helikon.io/tcp/9420/p2p/12D3KooWFBPartM873MNm1AmVK3etUz34cAE9A9rwPztPno2epQ3", "/dns/boot-node.helikon.io/tcp/9422/wss/p2p/12D3KooWFBPartM873MNm1AmVK3etUz34cAE9A9rwPztPno2epQ3", "/dns/coretime-westend-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWHewSFwJueRprNZNfkncdjud9DrGzvP1qfmgPd7VK66gw", - "/dns/coretime-westend-boot-ng.dwellir.com/tcp/30356/p2p/12D3KooWHewSFwJueRprNZNfkncdjud9DrGzvP1qfmgPd7VK66gw" + "/dns/coretime-westend-boot-ng.dwellir.com/tcp/30356/p2p/12D3KooWHewSFwJueRprNZNfkncdjud9DrGzvP1qfmgPd7VK66gw", + "/dns/boot.stake.plus/tcp/45333/p2p/12D3KooWEFQapPJXNyZMt892qXZ8YgDuHWt2vhLeRvny98oUjEto", + "/dns/boot.stake.plus/tcp/45334/wss/p2p/12D3KooWEFQapPJXNyZMt892qXZ8YgDuHWt2vhLeRvny98oUjEto", + "/dns/coretime-westend-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWK7Zj1mCPg6h3eMp7v6akJ1o6AocRr59NLusDwBXQgrhw", + "/dns/coretime-westend-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWK7Zj1mCPg6h3eMp7v6akJ1o6AocRr59NLusDwBXQgrhw", + "/dns/ibp-boot-westend-coretime.luckyfriday.io/tcp/443/wss/p2p/12D3KooWBzfzNhvyRVTb9KtNYpkRf26yTRHorBZR2LmYhH5ArCey", + "/dns/ibp-boot-westend-coretime.luckyfriday.io/tcp/30340/p2p/12D3KooWBzfzNhvyRVTb9KtNYpkRf26yTRHorBZR2LmYhH5ArCey", + "/dns/wcore16.rotko.net/tcp/33736/p2p/12D3KooWFmGg7EGzxGDawuJ9EfyEznCrZfMJgGa4eHpMWjcJmg85", + "/dns/wcore16.rotko.net/tcp/35736/wss/p2p/12D3KooWFmGg7EGzxGDawuJ9EfyEznCrZfMJgGa4eHpMWjcJmg85", + "/dns/boot.gatotech.network/tcp/33350/p2p/12D3KooWN6FJDaZvWbtX1pSc6UdHgyF2UZtYxPp3UkXQZa8ko7uS", + "/dns/boot.gatotech.network/tcp/35350/wss/p2p/12D3KooWN6FJDaZvWbtX1pSc6UdHgyF2UZtYxPp3UkXQZa8ko7uS", + "/dns/coretime-westend.bootnodes.polkadotters.com/tcp/30358/wss/p2p/12D3KooWDc9T2vQ8rHvX7hAt9eLWktD9Q89NDTcLm5STkuNbzUGf", + "/dns/coretime-westend.bootnodes.polkadotters.com/tcp/30356/p2p/12D3KooWDc9T2vQ8rHvX7hAt9eLWktD9Q89NDTcLm5STkuNbzUGf" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/people-kusama.json b/cumulus/parachains/chain-specs/people-kusama.json index 7a55435d12e895f1544dd338b2ec168085569f9a..518a7be751509aeeb3973f654b371e3498355949 100644 --- a/cumulus/parachains/chain-specs/people-kusama.json +++ b/cumulus/parachains/chain-specs/people-kusama.json @@ -3,10 +3,10 @@ "id": "people-kusama", "chainType": "Live", "bootNodes": [ - "/dns/kusama-people-connect-0.kusama.io/tcp/30334/p2p/12D3KooWQaqG5TNmDfRWrtH7tMsN7YeqwVkSfoZT4GkemSzezNi1", - "/dns/kusama-people-connect-1.kusama.io/tcp/30334/p2p/12D3KooWKhYoQH9LdSyvY3SVZY9gFf6ZV1bFh6317TRehUP3r5fm", - "/dns/kusama-people-connect-0.kusama.io/tcp/443/wss/p2p/12D3KooWQaqG5TNmDfRWrtH7tMsN7YeqwVkSfoZT4GkemSzezNi1", - "/dns/kusama-people-connect-1.kusama.io/tcp/443/wss/p2p/12D3KooWKhYoQH9LdSyvY3SVZY9gFf6ZV1bFh6317TRehUP3r5fm" + "/dns/kusama-people-connect-0.polkadot.io/tcp/30334/p2p/12D3KooWQaqG5TNmDfRWrtH7tMsN7YeqwVkSfoZT4GkemSzezNi1", + "/dns/kusama-people-connect-1.polkadot.io/tcp/30334/p2p/12D3KooWKhYoQH9LdSyvY3SVZY9gFf6ZV1bFh6317TRehUP3r5fm", + "/dns/kusama-people-connect-0.polkadot.io/tcp/443/wss/p2p/12D3KooWQaqG5TNmDfRWrtH7tMsN7YeqwVkSfoZT4GkemSzezNi1", + "/dns/kusama-people-connect-1.polkadot.io/tcp/443/wss/p2p/12D3KooWKhYoQH9LdSyvY3SVZY9gFf6ZV1bFh6317TRehUP3r5fm" ], "telemetryEndpoints": null, "protocolId": null, @@ -88,9 +88,6388 @@ "0xd5e1a2fa16732ce6906189438c0a82c64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0xe38f185207498abb5c213d0fb059b3d84e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0xe38f185207498abb5c213d0fb059b3d86323ae84c43568be0d1394d5d0d522c4": "0x03000000", - "0xf0c365c3cf59d671eb72da0e7a4113c44e7b9012096b41c4eb3aaf947f6ea429": "0x0000" + "0xf0c365c3cf59d671eb72da0e7a4113c44e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2aeddc77fe58c98d50bd37f1b90840f91f7f3f3eb1c2a69978da998d19f74ec5": "0x1801c674e09ef751ea2fb6f9eaa6e505f5f90e0585b1f06d9d774449c90c75266b3c00902f500900000000000000000000000000000000000000018ef5289702f6b8c7d22b3562ffda7d5593a5f6414226925e72097efbf9b2572000c8e6bc1704000000000000000000000000000000000000014ce421370cf0257d869618ec25c324ed4c6c7f65289297a3c134332c212e350b0010a5d4e80000000000000000000000000000000000000001a6915d6fb30cd30367f23194c68842a6018f565c773ea0c544eb2a62597b1b340010a5d4e80000000000000000000000000000000000000001b6a0389596b472840969a9088eb5852fa03a5b5dd7a3c2fc7275d7c05563a90000902f500900000000000000000000000000000000000000016c0197856b35c7f631f5aa8d9cfd83f7e75202b0d821e67d2f344e4e4b5fc10f00902f500900000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2001a999956b512c074747399c0fbcabd1076ce5a68ccc3f21da73f2b8747c87a71aec14a792bd55050a44cbe58c7196f": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073039f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20027994ba957c6ec7138a4649f05b9bd80c546b7e44391d7f7832d8cd5456f7ca1a76a73e73807544a4184bb59ce6048": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c0cf09fa69020534852494d50", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20036af6dd10e8692493044fc37feec1412c0e71c578bac3ac4c85fb1d9f0645451aa4503782c3f0f3260486b8d3e6123": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033636", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20068043e94d92496a755395960c92c01727dba627f34c210eba395fc7f60d28b3a58c5dbd6b63fb4f9788ee764b2702a": "0x443c76dcde19df9387486ded7845c6d85ec2a4c17f38f8b1e7a0a14de7968d7d0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf200e420fe7fad43e6112bdc886600d40d5da7c5df13916304befdcf8c879f5a35c7d65539711eb5cac00a9d5176b36b58": "0x5a9e357de87525b67cf9ed1d0f06a15a6363665ca1c9f43ff527c87c0945597c0230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2014247ce055f7db9af9631b382a7370a541145a8a9d8b066ecd0c7dff89c9d397a18e2e0e9d65a36cb2c1295c768e376": "0x925000bd5b83d502f56c49f2a91e3532af9f919d6eb52d750b72539c6b62d45b0544534b31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2014446e470b0ae39ab405f9d1d71337112c0e71cba3dffa43d603a1637f373c134f4eb3b0ca902a937e218cf992b4f1b": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033835", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2017185f0a21043525d99a5d934b4322c5883a7c739d00f1d125475cda89e7ceff0f406badf56a7c1270c16f850f62cd5": "0x89abf449cfb7d9b862b775abe556bccbe647820fd4d7a50b63872b657c96506f033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2017d70cc4f902c5ec93f5a80574ca9bc6621dd4e5cdd0ba737c572710c13df35b316d39ecd12c1ae1320bd6db069a07a": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d60945696e737465696e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20183848bff64fb39e82b8f09455849c2a24f97e96ae4e213d8eae1f35213c986e0ec03126812b24cc1bdc99484430440": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff21606456d696c79", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf201a590f51715a01416d8af71b8911f72f2395f3e80b47fe6ce9eaf63553371c59c73b403bdc28862c86ab1040e62226a": "0x68f8bfef657c69a5c34721cbaa618ae9eb2108566f9a2606cf5055578e0c251106706f6f6c31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf201cde46327cce392512ad52e8d16c8ad7a3a98a1dcff1349491c4de950bac2427069580f45cabcf5b57e645d0df2882b": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d12444941424c4f20434f4e54524f4c4c4552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf201cf563ada9e37a12b43c23c5c0a1d5ec8c3dee0510e7e05a5ac3e8ab4e13befdeb0366408b0c47c5a41c887d7dfdd58": "0xaa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d0e48797065727370686572652d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf201df75237d9c28749ff88c3629f478abb8dd36cb05189e12ff133ef1c0f3ddf97d1319dc737e4acbd882d17e143bb083": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf201f67bed5ee86b1cc1704c54f75094ec587fc2461b55e47619ef522b4bd986f71f7adfd207166e6dd2ba381117a2dd08": "0x948223bb2e7bcc8a55be248add34b625c1c0826c58fe037fa5c8e4591440dc59033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2020a67feecfc1baf4b326830fcee99ba800bea28742b7e03bf213fd6cbd84e862ccdc18e30b94635f5778a8103133f36": "0x6aa7f16d0ce7a6288dd1d2f1779fafb18d4c60ee78e89ab3dd3bc0979aad386e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2021891a9f30fc074325596c84c3098be702ffebbe8d46bc7b2d33457e61ee616e16c56d726244a6ee549a25723459873": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033636", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2021bc60d6ce58079c69164e9cbde46ae56c33c3e6261199d162ed7e756297752416cc7f7dc0eec30460a12a0a7e0c577": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512353a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2023a20efb3ac4201d658271e83019ff01c761954d8265833c4b21c7296a314229af2391b34fc090aa76a817b2e79836a": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20249f6186526b3c5a73b2550a4f77e28305b1665aadfdadf6d13f6c8eb36db7e3868ba648e86bdb7d60f23677ea6b337": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202bd65d7890fbc23149d026366a2cdb712c0e71d208c668db313147edb94aa31af86ca4e55d4900fed5eda638862b803": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202c366188ecd4b59e0e9ff5323286c19e212871311a823c9537b3f70adf0a9697c7286c84fdefe5603bb2fc49b0a7b67": "0x187c76f60b8e91032091aacb1ec79764af51e796a0c962bd2f2e766e9e5ade450854415241444f58", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202c4c9771014895723e5f0e7e3b67499c2bf131a9bc49208383fce6b0ebd78517ff563ff812f146c441d917dbe726c4d": "0x584d715bcb7a2d3b6a3120891dba91b19b12df42cd50f1c76103e2581d5b42740767677770657a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202d3730801109c284b64f4c750dd62b9e8fc1e37b0b57aae49b99fb66be1cd0454d275d34a1c031ae4b796fa30d38736": "0xc87dd7c321ad3dca39e53d05541bf9d17306d681ab556029b0f172156e12b6030a434152474f4b534d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202d86f32d2aa798639cfad1f0a1327a9ad17c83beb46308e21cb6fb45b9587a826addb8c001e01bc2280847982af1b77": "0x600e047c97181ac8d0b9d5a6372f6018f556d68b2b4cdb529d87da365f718d4006f09f92b031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202d88bc643c0481680c7d501c743c722be0bc39e129f4ecfac3d20c50d78472dca69f693150064093df5edb3a0caf14b": "0x3cf3f47f611c9dd952bd9007a85b0d84383f91e2f25edd0f13d6be20b5805110033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202e7e87a05e6e3d188d4aa12e16595fb080bd036530545e5e07ad813a408fa757bdd643e76b9d1171417d7eff0d7fe4b": "0x0a7ac5be69a8243f8880d5fd015b2e8f8f30ce6c7162f8bcb5ad1a1fa4246d32054d617263", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf202f1ff1a76fbd652a072b1553bee7ef332ef9a68234eec37684bf683d6e07e2deaf52a336ad7dd7e124041baeee37368": "0x9ce84f6cd845ac3fb2a009aae8e99b1a2fb64aa3e7ce1c7867f3ab2db0c9bc00105f5f5f6c656469727461626f726573", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203025c67a37f9de0530e46911b31a55b9801988b622814386aa36c7aeb697cc35596ede2bcc7e3c7f7c83d99192c611e": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31335d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203371878c11a0f29fb7eb85d26e341d5e4f861ee16e48158f3a84e6e04f1959495fa8b39f13b39c2d3a9a464151f595e": "0x844152eccf08725bea8ce898d6fc5362ff2d0bc9dfc21ed15fd138438d1606220c4b436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20386428efa585a36020d76528b28c3458886a23f6aa185a4d262ade722584c6f1e384ce10b269bfb898abf8785cd934a": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2038da5dd2caf09bf420b4f1d62838b37c282b526ff533bee49db3c9c7ecba02b951f63f8442cc33443a78679d5246829": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203a89a47bc0b8695d2a696b017df9249663b801c02f2b76565f5b60d817e7dd805babdc276b53d20e19cebd199c88555": "0xa6805c6dc7757cea227e11839257d4e24ad39520621e99e6016ee0e1907c3315033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203adecd29d62220c01af1fe296ff62c7eaeb9d2bee9133ac09633b0361b04567f3997d6aa139a401c12f929be161d9f6": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b07424159414b41", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203d084fa8c88a7030eb111d51f9e56f086929ec01fdfdecf2c5ad0c4f9b537e65084f053980fa1215fb9377dc325f52d": "0xe8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e0a506f6f6c20f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf203db2032eab02e544102e8a26522b190e0fe63b7c5032e2437b3f8327e95b07eae600a8ad4f31e17db0f80a3208c4728": "0xfc659bba6d3985002708101d9c2aea9155bd520c105688751281cb40e4d37163033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2044f6c8244ce36a76ad70843294f01cf26eb2cbbeb40e98cf9d5f39918fe54290600520ccfc9e519efb5779ddf48225f": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2048e9d4e54980e7e80db4c46b84264f2ea4cf3795941a47d46c2b433ee328d7d2a71c85007251569a6e1fa5535af173d": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b074b415a414b49", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf204a1456c707e805462a0f595c16a950ab0b7458638e3862d435924db213a27b64b5029bb2f06f68bd337b1c3de43fe44": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033738", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2057032750a00050f18d9976d6090d84860384fabe173278be399e99aaafc7d5b3eb2547af81fbc8039eb6fc49ae008bb": "0x0456840228e994122a2750c966571ca20d2456db20a7cb84603ed8e2d550377604303031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2058830e2c4e4dbe31045ce28fc980a8c3c1cdb7f10555d9e080e83ac20acbb4880b32d3d30319f055e37652c7ef3d36f": "0x12d9c0035dd422388e6d346f61df3d9f3667f8ab761c8c57120dd61917976e10032d42", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf205b2dc427f2aecabe11a2ceca1f7a6349c2df8fb28c6749d31d1716854ef3548aff85aafef3175c5e49030715c00fc25": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313438", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2062b0a5a8bc99462cc0bf8fcf90203cba830e5f0091c9f1c5da8a2a9a1a7a0de5802c6bdd3d9e23175d8c116ef226251": "0xd60cf655685824e9966b0a10c01dc8b17b37e24944fdd760e4dd73ff1dd4ac140574726573", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf206574a0ef09abd6ead4f5761035820cbf64689da7688eec693a364879994be8568da0f7ff5223c391b6b58626f827527": "0x0a71c6a0fbf9b63ac089c5395bdea4917a84aabb3475d4454147c4d24ce1013a05706f6f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20674e3388e2e1aa4aaa342a8355ff3662a4f829cfd9c12a01da70549643e5bade2829684c101fe7c1362176c884a3719": "0x8433eae795936e63871cbcf0410517d1dad4755f2da4a6d88c1cc1c589b8e86f14535452415742455252592d5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2069112c1c85b4d5d7a1a2e5e98b946798e21a74a8d65c99c228e22e79b3e016bab0eb656a5235af8132c2a9a818c7a2c": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523439", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf206e8846cf7d041c8a528c5def8819ecfff07f170fb1e51a81ed96a4ca36d82decd18c5aefabae24a03d36ec5f8ffb257": "0x1ea86f3c82538c486a25d8abca26760e57e76a01212419c7f1c8b510121fca73042d5242", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf206f8e4b397c44dc3b1b19dd0dc7962d84729298bb2a53d0e5974d34d14932af4d4905334d5f9a57d7931ed1eb04eae67": "0x4c4769cc1bf4774f19c7433e31a5b8cb686944cdd758e193d264410d4918b1200232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20717ea76d2755ba7508819bbb7aed8bb12c0e71d0d3a5ede1ed512ea065c3970ff43788f057c99ffa3afe8ede608da0e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2071d474a3a0dd340668c44dfa1a3b906a63f88c1fbb368cfd13ca5e7a68e16da2e80b94fb382948eea95616685598235": "0x22fff76bb4a0a5d66cff0392dbc083abbac3b3046f6fcc328abf0ddd16ca08370232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20730e29b5c9c55b9ad22e208fbaa9c8170d4121446293f928e59d4f8a5eea096ebe1c2538002fcbf7b7845dd2e19ee6d": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20743b925eb1b48c3154a37a00254f8c5e88efbf462925faaafc04b00555e946a843a6a018de2e47cfca41b0804a9f128": "0xaa2b3e0a8702aebcb83d552838a17902b2403b0f16c4e52a4514fe02df532e3c0c303320f09f908f2052414d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf207871568136038f8f6fe7b31199f4eda8a74d6464340d1e60feb30c35ef63b8e48737f225e6343b1875e352756d0160f": "0xa8a2e5461f346cf0c23d1ca613437432a160525b6487dbb718afa51439d48d040d56616c696461746f722d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf207ac57824770a9bdb269d1db618967f46d6f646c70792f6e6f706c73004d000000000000000000000000000000000000": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf208a202c55ad5022a2add3835e2998492fa6c823ba7c33395d2f298934f304b44af030504cf1af0f1a3f29c78442e0750": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf208b030a3e4385a9eaa71ae95cf3b4df5e50c1ab151d60148984c5494bdd23ddd7e5520a8b4873de12ca413a6f37bc3cd": "0x90c7f4e84347dc6e4e176f9156b2347378faa9b538a857b404cee3e3417063050a5374616b696e672032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf208b8c566be5926cd348648d055d052cd07e8861ce764f34220c198710b60b72f8c59c617fef101bdba96bf6f598016d3": "0x201f968f24fc0df93fe98dab905ff103d00a9a232329bfe78c22663dbe60a12d04303430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf208cef132f46d5bf78fe7bfdf6e7cd9405db58282171c8d2c73678f13f3c61579902ea4572ae9e9158046e8e820bf4d82": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf208ec1901955f6a8ba9fcf40920b62ccf48f5c152ca97d46d67467f3b6c7e2fff11e1f95abc0ea7298255c026ff65d92b": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303320f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209163a5f2972e9c2ad31a6a386bce8bf5c9d4bed4df1d87e33b03c63aef108b00b23253cc0cda93b528ea9f95c33f522": "0xe643e4515fa656d6d830c088ec251ab76ba6cebd85be7e7d6362eafff654e2220f534f4e59412d5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2096e0db1cbfa92374241919548f80bb3d6945be0cef12df3e9d25d4bfed7c4f6fbe980487ccdcf13891998454d4c7d3c": "0x5202845d849d9eb6a7e5a414492a86d205be4a374ede34e98fc2440de4809a3e033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209acd96884a49ebbd9fadaacd9136d796c8bfefb8ac4b47696a47ba939ccc48415c02fe947afd32437190cf5a3644002": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209c5e5eddd7408e51c125433483eb9177e437bd1edbcf02649eb8a4103c8668f5903ceffd5b2a4215c0d211affbe5f6c": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209da7bc8ea2f3eacbccb7a616c4bb60db4adbb4e711987eb53c39b12dfd79435736f1317a869db5f50d5a913e4045550": "0x46b4eca928ede3e8075d86e25581d46adf3eff915646eab110d13e2fbd947b5e107765623376616c696461746f722d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209e0feacd17dc8258f8d124326e8e79ed047791087bdd0caca708a478371eb8dfc056a36028504ea64f4cc43713fa918": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331303a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209e61fbe0b11a8469a72a9bcc3a79154e2623f940ce24961b8e483b3b00c94e84fd32a5f13a67a09ef5a19d28af59435": "0xca42f0b5c7957571706f29d2828291b148b4b162100ddcac72c507fd8ab69b2e073033f09f90a6", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf209ed2ad028c5f938dede2fc8cc8069b2565e801907aa5ceae0511572155aaaed09c8ecc03b7dca4790609ffe26bdba0c": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20a0833d62ff297dc2423ea20aa9e2d7d9e62629f1f1b6e219c95d80577ba4215ffeee870b4c6f6672e2191bbc3a4b750": "0x3674aa73951219dbd27b3e3fc5847b806c68c1de38fd4f22f9493a461c80e903124f5247414e4943204d494c4420f09f8cb1", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20a08568a637562705bc4fecb1d33c4f012c0e71cc0578209ed2ff07931f254566de682bd7407f07913ca1c4a30e7a633": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033831", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20a50a0c42e458db074cd89e3140a971b8e9871679378b82009f51f30eec29bcddfe60c4f7d22c24f74883b47d935a565": "0x2ce1929ab903f695bdeeeb79a588774d71468362129136f1b7f7b31a32958f9810494e434841494e574f524b53203030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20a73e46ec9da49f29fea3b464d77109b12c0e71cd31ae09c2af44df1c49f572234348e1637127de385daad38c2bd3632": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20adb7651bea6d4d81c019977882d63f75213e3c8881ed30ead22d177f5c25c4cb8bf46cf2d04a8ce55ddbc06118a9516": "0xe4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f721070617468726f636b6e6574776f726b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20ae46c66639fbf674157c4a9171cafa778905d56c02810911e1ebaf201ac246eff919f4e71a5bfa5b29eaf6819663944": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20b0f22c210fbf446d674b51a6e05f9110daa7f988ac07541286ffd6ac83affa9d4f0e119c04eba5f1fb74e51719867c9": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20b432ff63b59bf96f318de5ffc7832c1a00b6ded2d4d0101146c5f76452f6900532c39cfb36b911e38776c782cfcef59": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033537", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20b90dc8cfc3e699a2611c7437eecd07cdeb5320179cd1dab5b17c203384b7ec2fa9e73577a82954f9c526ad535552422": "0x5247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20bb0cfec7089d8b9e17ca192fae0a4ee0a9e884e29b1c07ae4918e17e7ec48bbfe9622cd9badab882d14064c8d672b3d": "0x6a0051ef580a2b9dd19a368b82ec20f9a605b0207f2e8d364e6c985b5b2ba8710232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20bf5e86edbfecf7c34436cdd4fae89db424ecaa1e5d069bb89c743c3ddb44d9cb023aff0ad78e3c502bd39b0abbf7715": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd768191041737365744855422d4b534d2d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c07ed359e65249593e99ee8fa2bfe3e2d2a9ef6dff17530bba04671deccf9754c7cdf0b079e0ac825a43c5c0e274620": "0x90c7f4e84347dc6e4e176f9156b2347378faa9b538a857b404cee3e3417063050a5374616b696e672031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c0ab7f0e067fc048e2d09c4b539c63d866f40b96e6ca6405ed0c44747726b3972ca4773aac5273dcc25ffbb5003b075": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c1af3384ddbe14bb73ed1432e7b2ac1bc97eeb4ec96658e0ec1d15b07524376ed7e1444bd35f3c4fc21526176f4c979": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b75707636172626f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c5277389a76828673fd42ec57c47c66a26c112ec96a277c48e91f46d5385fbdfee248c6ee7c3a66a9f8e640b31922a8": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c492770574656368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c598f045d1f5b180f40f1d98146be72e04176c772d8e5b3758231c8155b2265e9522e5047b15f388a23cc707767923e": "0x9a2cb674ea2f4866664769a1663fd6aa321d9cfb89b67c402c881891700c0f571046726965647269636820486179656b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20c85d3369694863e11c43a04c68b3f96d34e07fff5d2c51bf316d91599d98e2e1ecc8bab38f57caa40a4206967dc8ac0": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a074b554b414249", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20caa6f5c0b928e524b323b57e1aa3469f16a6e2b7183e7a10f701d357d224e9ca87bfbc49a663fbfa27426a8f5e9b1d7": "0x38ae9a751c06cfc8b4bfb06f4d0b8d88df80fc88317415ad6f1b9bb6ca11494104303136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20d00278bd6531560df393cb9de7b02fc12c0e71d36450dd3d651da12ea3ff51a9f306650744f4c164ceaa7b2cc084546": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033539", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20d26eef7e0e73557aefe05256116b0761a7df77359ce352ba50059ec6e2635d7964a50cae9012e4a737f5e82c353aa0d": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20d461b6a1731b017b92cfee609c6e3b152e32efcfa98867081b563878242febcb31531cf4648cc496bbf851f39f31f6d": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073036f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20d70449b3466fda44840841f97768623522159de5d549c217b26deed24558c4ea6e33ab8daf73f5410665acc1d5f845c": "0x1aaf37daa4afffeb0d84c47f52330d8293ea648e1bba5fe0e35355057e63c1670f73656c6265725f636f6e74726f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20db0fa311944ee03f68cb14e3a4773a580ec6fb1ab57be7d791fa9bb7e711b2736c6422e0b66932b54f3e95f614b4b2d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20dd32323836d31919cb4cee6850e02135c97523bb1c1be25aad6bfb7a52d7e1a55fab08a78c2099daf42951adf713353": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20dd6a0fe0a25f539d978c7fefe2bdcbd74a0fe5948a9e16263adeced4ac5592a4e15ec77d223be684d9229ab3659fc70": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523437", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20e075b69e5ae02a46271d1b1294e5bf912c0e71ce93b3b5ce42fde862b4d609631d600ee1cc3f3717268e7b9b3e1467a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033834", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20e0ca2b2ed572a3b489c91f83993260940ad8a6c92b5be3305a78ec0ec67cc600e791fb2769b9cae21cad79c40f7c92c": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033435", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20e416e5b5a385055e1f692da0cf0f8b3d21f6f288702a2646b5cec6d0cb5f77d48638af67cf77d6dee823e2959ccb967": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033439", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20e495e95537e75e686c3cb9a975a87326e32e6b0a35b369455c50fcaf7153945fd6d92b850a593ea33b5c3b51d7e5a2a": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20ebce498b8ea6cb844b59453ebbccdff041eda8cf4ea9ed59862c6f5ad3a51e7ef62eff19b629cb241a10d5fd7f96d22": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20ecda764c9be13ae791ffe4aa9702d1744d50e5b2db8b483e5731d39c1e71f33d6ab32318c144f5dc41e57d1d21ee779": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea259385609086e702d726f6f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf20ef92e517426f8737223efd744536afb1ad58fdac86f68d5a3a9a8e07163426d717ef0426d3e03604ae3bf4ed481a923": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2103babf10c477bacfddf27dc23fb5be6bf7c2411b8362b3beedd04428317c3eeb3639379c64eaa724d44eb77b15cc85b": "0x6a2bd95c44c00bcad3fef2f7226ad90b8b93c3c1b9679236d5abfdb39c89584408636f756e63696c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf210769b6d502a8f0b2b26cf9be30f66e58e57071fe8c6591960d214a1100419ff2e2e92d4989a99646354df48ef91e664": "0x1e015452870e49b4e4c3e054556b19683e8895586bfa58638a74a5782ab4f71209414c4558415f3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2108c2734b36b8888f4a19edc8b64f422a6ef8a1f259f84d8e435d119d7c0b8f4d91c7ef95bef739c81ff66a2cad2cc45": "0xaa18b3cf52cb27fd19d5b80fe7982ff955e0d5124dae26ac360056f401dad84607416368696d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf210cd9b5224b78be4929deac8776e2ba46817038f23e3b1e7d91f641929205495b7be633fc2247d0bcc5a6f9709a8f82d": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf210e1d1720cc5799c635647b68b396e943f25ee912fc878195d9904d4474bf1ffa58d1570bdc39af3f8fdd88829b15655": "0xaa7880fe9ca2bbf331fc13e40525dcb0da661f143df506fed76d8ada3db8f55104303032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21160f447eeed0c082d88e23f3c2553b1c68dc89f99b0b46b9e3a10f9b115283e27b7f6fd591a9f6cf53fbaf1b1a4685f": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2116fee05fc8e4ddbb6958227b9c8ea44d5f8960e7af211c990e0d092ba6038772482a74e9dc91e5696c84fd079992ffe": "0x5a9e357de87525b67cf9ed1d0f06a15a6363665ca1c9f43ff527c87c0945597c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21185c189300056dde7eb239cf182b8ed223b081a343ef66eeb872caa2ceac54d75566c279627592362d2cd162bd21831": "0x2cba024614ea8ccd1ebf7a634f30b38d65c082be6aaa92551b9c3b4d1f15ae6e0a4368696c746570696e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf211af50e830a384d6cddff2c8765f5e6abcbb3c28aa69648bcb3eb9b493c06256abecc144fca20c90144dc4dc920bff76": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a0530322d43", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf211e4c6afb785c7c325f25d434d4c547340e30e1462871a4a8a38dbf705b96b986d699b62ed53e890b8f42544e3bd7b38": "0x1c7376c9f2afef25e542556d2af805dfa691a414efb9e0fc9a8e33f625294f670232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf211ece78f336d20c9df63aff306176237820f781b839533ebb3f3606d6bdb794136b3da9a8eab8ddb2f4b2c29cefb515a": "0x7add073714bbf9da81fe49db63778e918217e56c55e4f81f68e7d2e7d0e59d0e085448554e444552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21205a8f89ba76fa0d8e59d76f99e1366284e0442b44363d362b1194b107f46ec28e76932170fdbbf8077dbe87aa26001": "0x284eb76f4116f4b75a718fd1a374cc5b6e02fc18f37e02deb3054e57539c5328064672656e7a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21210f72f44ff8832d4eec2d9ec420b5354ba6fba820d02b4f0def9908ed99ed988d415d9b7c272a1d9394fd670ea8950": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21239ddf641b9fe0e1c4a22ce2f5a455a3c0bb72774583cae164f6f184ea05f95f90c8fa34203b9b2c5a2c1b6beb90a5f": "0x8429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee210d5a4b56616c696461746f7232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21292a4b58384768449837f754c99a44ba434a662f5ab9e81bb83c07ab5282538bafe448f142d2b6b119362b1bebbe176": "0xe26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd040b48656964656c62657267", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf212e1ebe0cf66f108c421c8aaec37e4f620430a70d2db1bf57c424e5e81de47ade7f1f0ceae2b568b9182ecf9b025aa35": "0x2cf0838b05fb182718de859525fa1e6d53d557e5fcf631ee9ff44c619810d43b0c476f762050726f78792032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf212eab7168c18605d270be8e19009c67d245fa94cbc6c035f58068a57aee59359d7d464caf058fe55e30623df66dbca94": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083330f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf213783372b26c4b0f21d1ab58ab4fcee312c0e71c508ea654da98971a9a27caa027e9478b84c319ecc1fb63288ffd9b0d": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033933", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf213a6aa123ebf90a2d40cb44290bcbe5e4ac0609d3d326fa83a76b4e89a445ff2c0e6436b338481041af7500057c870a6": "0x6aa9e19b08ef554ef0b123940b685c0d64eabd9a1ec487e43bb7e1f3d981c06200", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf213c3b27ac47fa89e8df1b00c8149ee6b8278ef29ec5edfc3f2694075448853b34a387e0299bcc326c41e9507a5f0ac2f": "0xfa65ad25c6a51ba28504fe803d9e3d542135924ba9fc0736cd3f1d9b839017780f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf213ea12bbf865f261fcf67c0989fafbcf3515e1b78389f5ef86a9b5e739a0912d6cc4e9f4775698ac23458e8fe8764f89": "0xa8a2e5461f346cf0c23d1ca613437432a160525b6487dbb718afa51439d48d040d56616c696461746f722d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf213ff6fa1d0e480ef82d3023f2bc505ec4ea8dd0f74def3f37653a2bc9932edbaa87ba9a185c55cd8b5bd733ea86c6257": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b356805504f4f4c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2142dfa9359ba3ed2b2f893e502c8b2390071d7ea9d85cf0a22365cd41cca3f63121fbef0e1eea72109db9b12af8d4860": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b355d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21430648e2a6c6137bb3f5d386e349ccd5c0db244fc6960005482b5e6c2896bf2064efd1e5be17e851dc8139f839cf062": "0x5842026fdfe358c9320e35012deeedc83c1e19d2b677eba10a1fad0d93c82b6607417a617a656c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21431c0f7853fa382a145bcca8ae92d7112c0e71d330bdafa9c3a6218dcea201399a6cfe0fa73c2692e7a83492614e40a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e731008436f756e63696c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf214d11f5a4090ba5cb906b055f30a6646100a7405e03b712786ff8d6b522fe258843ec33d366eb61379c98aa028bf380c": "0xc664fbde2dbcea2d4180fc9e285ac56ecb6f89a9b88cbee9b407bbceea7da912033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21509e5011f25807bb89b4356ecf60dc9ecd0f078418756af923fefc497d98efcdd243170af2694cb75a2becfe2811732": "0xf00272047a1369138c7948e8d193757bd7d6319254926d2b91175398d8250e30033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2152556d9023c3ebe1aa764cdf018f1384f83a66e4c8f4afa5949586c22ba0e7d73e7e4dbd6c1efeb9ccd689080834600": "0xd61813f456c8f11087d572921c67afff25605aa712899d6a6b04cc42c3d2d4170235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf215bbfd788ae2c0f9c9e0a225c0ec055cfe57cc05a0401fad57f17da9b903ef6d679b4d16c107a89f7a8c3da798d10919": "0x42f3c525c66f2a4eacfa88479f7537670d2e1f45f4ec25703a111f5f003ba15d033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf215cb25fdc3162fa7d0913e39788c78cde1926d2b7dcec1ba035361a2d58a3ddbbc4386ba5bd61d5dd57d22d508154dec": "0x30fd1beaa72357f61ba1fe7e90aa8c5080fcd49b2c82e1b8315bcd9a223cbe4105f09f909d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf215d8cc207ae11b542cb7cbb92097c7237c49a3654ea5a5313645948de60749792de736cb3870da7b401e78734eac3b60": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea259385609033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf215e50edbdf8f9c55d248be9aa8aebeb41253640274e26277dde50bc1d72ed0b3f627e4c6b66d8343d4c52ae97afd0f03": "0x6a88b4d1ab30ab4708521d6c6d480a858d92692c0b0cff67e1a6904e23b84112067374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf215f2fef1721c0c68c45126a895ef442f5c3e489388961303bbe308673f7faba33bae973af37d6ca444e1772a750c9775": "0xa43b2797bd4dd454d7fb0870a2a4edd62b39eea0801f6baaf09b05c8634b5a250234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2160abd6b7efddfa47d7721371053129bd47e15ef535a26d9ee0e3199ea99baf7cae9d94a05581316885d0b21549ddd4e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2167ad101f38ea67077b668a5004b17b68219020203f8d92b4c8ae0dc2a5a9c7c5641486ac27a4b591d3560b434650658": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2169ea0d85e46590c62e047babd2031ed5ff23e481785ec5fddb6178f6860b44bdaa0150ef473a91de3f1ff794b2b6fcb": "0x74422321a842adfae9419ecd3983c4fa2da6e879ccc1db031e54c742bbb9bc030232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf216b68724c80dd9950366d2a74bd473c9489553ecd89d7eda44e51d14dd217fcd4e8f183036ebc916ebb32844bffa9915": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523436", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf216dd1b48754a2a6bfc3757b772f9f01910a315981265a9951067374fb624c1976dcf865c9dc43d08e3031ead35a06219": "0x726ac63a0a6a700ad7e1178fef89a87620bbc152a19f74708defc7f08bbc6556032f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2170594a2516688ce8c96ad22c918ef74a28d12dd5c12e1bc0f85ba2935bff3b257089ef59869ad310056febaa5793959": "0x4ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f05f09f8c9f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2172e6fdcc7f8c128b419cad0db414c1ca6b7d31c38534c4c6dd648a247e5ed408172cd647084f554747823fe69304f43": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2174ab42842aa14b268b5d779ff1bec02d69631266f8f9a76413f5f902d59578faf655a0dbf92938ed749fee838c81bd7": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083234f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21768a70b5a9f93e434aaea779186eb691d6cb02740c7ed074385a93d27f0f9fe5efc113a8e5961d964c54b0afc6bfa12": "0xd46e6f10cd59b0f6d7082dffb33d27c9f29801233f8e28fe3f5edf2d51762c6a04303135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21771c10a29ca314e7ede3eaa2e2ea1cf305b1686b3030de938cfe6a01467a664fd1b42e4f43fab7295963640c5128a7b": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21782c028b4cee54e88a2a2f59b187df39a7994a63250d77c7cf6ea9f364f136dfd163cf4ee30d1fbf5de6808e443f25c": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b7570a626572796c6c69756d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21796b54cfe327241f52ab83de740e7744613a2044c0cc5b2f0faca94f2d6e7b7533c1ca3610cca54ba03ab9c5831d826": "0xf429460ae52548e754c712a7cfc75f1bf7c9295da165293ca52ccc686db5c02d033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf217bbd7d19db7a586a590ef36d2a5c15b9c4151f0860839590586185a1dd97ef4f3fa86a6c0ad4eeb24addd8bca2aa758": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf217e32de8f088da5a6950148d4e5914ec544e2e588c90a2e53e051d2f87d40e222e1f034913a30f95a9a2f39114e5be38": "0x0277ce02b2ac78ceeb9ae4fa0a595005489bf3f5f77898415e32a3e9504a531418546578617320426c6f636b636861696e204e6f64652031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21800c0ae0531bd79c7e1a42d62b5473f0208bf1b4851b0e3013141e274ea24d6a498412f2703e598e87b7fbdfbc2a72d": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2180c52a2a840db7f6da03a8f69143c170069c3ebd00f7ee39c7f8affd0d14205768535bf95633e60e26f8c8006c27f53": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331313a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21813670e858ce3d80abda7ad1d8d520c1ccc2a2abfdd492dc72fddeaae0b32888f3397860a31b3fcc88430f7c5338c40": "0xf0e5ac8e356d7a3867e9919b8cb1984ee5a070b1659b6195deb85039a3b699280f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2183128dc8292ea45b743287a6fee4c30005e13effb82cec8d1e3de31eefc750ea3afb8df4ee1ffc18a66cf56ae4fe178": "0x280221db3cd2515ba48cff6c400cf4624b9459eca62f30523972ee5b608e967b00", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf218327b1c3d72d8d4ae9355220d5ced9f06419ac9e6a0b6d955fc0274eb9911fddac424b804fa29062ea417f05d64803f": "0xe666c8204234e3e9dc671cc875c4f22316e6a7b67bb8b0538d8d77674468ed5007736869627569", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2185e775e2507305ce9086190859a2ee99bee35b6118399b673cf802455159ae282fa4a1e68368fb67cf85b00e4746119": "0xd61813f456c8f11087d572921c67afff25605aa712899d6a6b04cc42c3d2d417052d303030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf218d86490bc369378378383a66f630a33de4ea9ea77e628210eb1aee0c6816cca8de5235e04a861059b889c6b396fbf15": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47711416c7068612043656e74617572692043", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2190dfad73fafb0d1b45ccafde3be8ee05c975241098f4ce19cd95187485c1b0006584a560c101890f32d65a67e787700": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf219632c158fa4271ceec193c1107d6faa1020aecf6332d324cc8681199d469780ab81d8e87dc408aa96ca573c590ce344": "0xa0340d617b2e5fecf5813d12bf441eb025f610edf738af8f79a98a9e168f690d04303032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2197cd122a188ea3dde82c0e656be2377d45b3d8d71f6ca469454a375a951d272db9426e3712e172272f951d8b289d300": "0x1c39ef78e57f239200072aa865312f87edfcb4d4133c6ccc0a7e33f5c799e2010743524f4e5553", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf219a3c826e64c31486f97b2646f45669633815302aca0725e74939106884963f32a80056aba37aa94dfe6220c039cc87e": "0x273e55ba58de0184bb96e5e691dcc9171ec58658d2b94c42c7e4ca7574f6a07613e5a4a7e59684206461697a656e2e696f2f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf219acb7972ea18adfc169f255ba2a0c53d4fda909c31173d9691cf6c488ffe22b46c795d0bc95aa062bcf08f414c4655a": "0x629c17f4f4a24ec53f85a7beb1c70b13379fb8e4f969560704d2c25133ba8d2419416c7a796d6f6c6f676973742d76616c696461746f722d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf219aed655a0935ba8565ad4a450629a910d3fb75084e9d91405dffa8b3f1396968dd935308d4dddc0e119fbd6be444482": "0x4e3711ff0fdcfc953c9ff93355ed42146e442c256b6010ddd5b5fe0ee8b8ac1c0b436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf219e225f61a007373b152253cd4cdb5b1a4b5a3630311d5cf8919e20be535ded925f210724ef5c78f8e3754a32ed43841": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033438", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a0c5cc216d2bead2dd9a018e52181c470cfc338f687e55d944e8e6867f90a05085cfb5e15e2f0d5315ca27026d0aa5d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a165841d41c9c4e6684035fca91b67b0da80f8169a692da1a6a0bda931750ed897b1ef4b0bc9bc6e0cbc906981e2b6a": "0x2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57066b736d3034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a428eb19ff37265b2a0f3e9d7ac61e5b6a0389596b472840969a9088eb5852fa03a5b5dd7a3c2fc7275d7c05563a900": "0x0ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e116b7573616d615f726567697374726172", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a47fe57c5fa0349cec3067ff31bf4715c8186e944c4df5cbb64eb1080932db445d11f69fb4da145a98d0d6aabb4c009": "0xa6c5f0595d6ed85d6260bc682d4a68a4b4e605d43c67d56f2765d19698549772067374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a53113712ec3e23dfa7a3fbbb4a81f44033dc4a810332f94b2874b5aa564424b0583f0e866c908346ae4b2bcb4f5e0e": "0x4e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006054b563034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a562df6c0dda0f3b7c471f84b57be58e85a54ca5474be7ec4f0e149232199a19f1f962331e1ebd5be36cbb77d8b0c3e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a563b1be1c6f1fc691a3db82789b249a01f4cca8129d5e282faedcd6547e6676e91c46067489a28711f89da641b1737": "0xaa7880fe9ca2bbf331fc13e40525dcb0da661f143df506fed76d8ada3db8f55104424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21a92e3b3081837f84577ed9566d27d7efc2dda4a648f70d73746458b1109134bbda7b43b46ab3546d310823e36966d76": "0xaad8e905d4c09ac501fc3f74833019107288077bdaa77291588b5e021330657c10534d4152542d4b5553414d41205454", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21aa6ce7ec8af0d5649fdd942061bce54c08ef34fd7c513a00cc447d3a01368dfb0df9d3c84ee52182b8749e18573e14d": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512363a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21bc339faac854827df2a043f2074cedc6964958c102b007555e5fbd10a3f98ee67fb2bc270fa0d20fe2371916450079b": "0xe8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e0c314b5620f09f8c8eefb88f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21bd423f7418e9c1eb1d2a7a7be14778efaf6136c1b5c48e96fa266bedbb262f30748b53d9da7a435423272e1e67ede79": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331353a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21c7ee21f03ee09ed1b714b8d65938e596366490cf9fcc50f7edbecb28e3b78330a0e35d3e073cfb3538ae6540f0542b0": "0x7cdc1a6a5a7f23437b6528edcdf553d0685f940a4e6e85579727ef3dc574563a04563031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21c83a483946d3f1c3aa060b653146cfac2de6256e9ff0ba9b97f862290f69ec0f72b31fa0a6843e0175e9e81a0165d6b": "0x96e24e9b5ab82dc275b82318a52cebed1cae3e25be096d5f288229b256359e430232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21c88a35959cf7297788e69c0938357382e0c76ebaeb0ca61c682a80271d95abff7bd6249acb3f90cd702df6f23368b16": "0xec5909db1fe8581fbe80eaf39b4577c12a99d5abc87131bc3d4363f623412f42033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21ca9e5c7ad4fb067654fec77e3cf49d2e6f485794ef2701691b1508c90cb2d3bbf6186bff0716c43915936439e0645a9": "0x4284fa7c290fb6052b9437610cfb2e19b3b37081fc72140e444d5b57ca01924d033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21d0913a4692809429ee2d8bc2051cbd15c5c5a4a025f3d8be84fa9ea36383c2cd168c8a018d50c88a34154afe9ecf04f": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b04474f56", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21d2839773325d03130afbc0b9258596828add2af7269292c685caa58101bae5d78297eff522e3f6b239fd4fff6b52132": "0x845498df40e85e2ba9d9e213d1f476e7b147aab6a9098f1bb250e00251ef8f5c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21d7bcc3a30ea81e6b0f23efcf27793ca6d6f646c70792f6e6f706c730012000000000000000000000000000000000000": "0x04f3da939fa351c562c7e06e1e3716976b5e14230e83a45995cbad9086f49e1705706f6f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21dfa8f553250b1a01dd3029b6fb4c018c0d792a19684453c51324b0f2a420544d8c3378c515c85c6aad72b7059ed4cd1": "0x88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21e20801bf4118db9d2b9ebe8a8f6e8c8c21c287be88281cfac16666331518cf2820f4de9c29d7caf15ffb596f12cd953": "0xd49e16d1c4f6a051815c5865058cb218fe7d460fa893907bd0cf8596b493f45a046f6e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21eb9704b8e9a24c4db38498d7e24840528e3a8ec56f21d20789923fc326898987dbae48643c059d5ba9a8afe843a6f45": "0xe4d733aa6e16d24e220efa69687f6ff198317062ab5ee12a059d47b732c27624033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21eb98516eb454f77f6bf48524fb351aa72f10843313abdcc3fe2ab623e213c561d68539db6f9b47f72a41f2946c7fc45": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988834", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21edee54c7d3f913c6b5f680546f1c7272fa216946d71756ea4bc43259d6866958233f796bbdcbca326d684a840ef72f0": "0xb0d8ce5256f0b5a51a38ccaadc6d21fe930d8ff3da1dca198ebe1807802da75304303132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21eff94efdabbd48d172d1d4aee227d5dbf4221d5348a254fa587bc69297dd25173e89f25220ec395ec495e3df9c41d3b": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083130f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21f11459100d14c4bf85663adc622ad75f49bb2abd8dd96beaca34bd5bfb81b5edb5186922b92c3b1f5977cc401b79554": "0x3a3884dbc6806e8b4cccbf2c407d800c12141c3d7cacde442a649a6a2822ac170232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21f2e64dd2847cf975791908dfcd1d8c0cefcdee5940f8e74338264c625fd7fe4c671ce205773f69e8bf4cf1b372f8e26": "0xa89a9920a98f3591ccc0a1a4bc827a0adfba37b75fcc108ae3c7191bb9a32750032332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21f3b43aed9ce7291824c06d4892f051fdec5377d25559444879fa2dbfc018dc9bc4b574c73e7cc4ff17301e6f0404b0c": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21f42ea75dfcca5aa9269c87c2c7b16fe12c0e71d6034eaeb56b1637b948fefd184ecfebeffe8dab40a37c6cdf3971a40": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21fb6bb2381445273135be0586609532bc0020cde3bd8293eb5d5b61b072a9f6b19cdce1624a8ee4a27ca8c57e3ffa628": "0xecc96f0e735d4677e64728f5300b27c97c3413ba01e7a60dd29cb89123990a660f666f726b6c6573736e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21fbd2ecdc920f992454e24c102f0582fffd31bf694e0d28434da06abd3fe4febe23b25054b5de48ed94246339c51b2e6": "0x1c6681030fd4860fcfc1dfad9ae55fc0181229b007b6365dc4c8f5fbe162554c033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf21fe4da6599e579730de6e7246ab6547b285f7ae7cc2580d54ec3be6fb7fa3ab6f2c1a32352c793b29163822091839e31": "0xd49fca4c127d246783d23e388e34c09446b624d2d5e1f7773c9590823d45101904303231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2202b406165ae0b48a55036c390d6a7d45c899bdf0bebcb57f0f68da86b80f8840407e7388ee52cbbc1a60f18a7a2eb58": "0x02948b18cd5001e68a33499343bd8ed974fc8398bbfdc3dfafbc7c478544f67d0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22040599cad87ec0bd34f66d1874b3f1712c0e71cf3f161c02727017e5ce4f8f6e245fa61bec1a3a1ac960fe11e917c26": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2209e38e283473095a463778fd16f4db182f53c176ea7abea9092ab9b7ccb5506dd3c81de6fe0a5d2b29068f53dd3706c": "0xf6944b2b5f590f132203e5dd4f04c56e594f43b5681a48b210899382c3880b4e036b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220a577df28075abf403454d10bcde194fa0f5c211f7844143928941e88780961c972b189e6269ca6e0ad98fdae5c994d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523433", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220b79b5bba03d2686899e7c2f4fd8d57bb3daa994e809e4484afce1c63b8737a9adb8a91ccb78d7002386a087b382de7": "0x122ff96f07bd9c9b3961c4387d71362315d05addda58f1dcce642888a643f93004303030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220b88d9599c058872b21e4b3cdee8ea95a43b9d3a39997151c4d745c1513b73ea440fcd50aec480eb4ddbe65fe692477": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033437", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220ba2427ac987e1ef9285ffa826ccee506929a0b268c8a51c457e031e971ba6d1624b2ecccfc94185a8b593549ef7b40": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220bf3c4573e2e1f7ec7423d959ec2aa82aac721ff23bb9448f8ddec8ecd159961a23f604f8fd22d729c3390e9f36f843": "0x4608fc7527698d3f4d4cfcc6074f01c2ed59112ad670dd5206b3658bbb62a0730e4f70656e6269746c6162202332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220c19d30e3fb4f1ba4cbe7787f6ece10a227e750a30259349ff46ad36105156f552fedee92bc3b81470cea913d30d6cd": "0x3e3622fb285dddefdf8f9ac2ab59aa34e2abb5a316e9ebdc020317220e75f879033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220c7172b569a66d53b866ac6577a4f60f2b13a9cb72a219a88fbb88f7c5306fcccbaa21a22484a24bbb84b8acee8b50b": "0x26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf220e03524d700cacf37cb5192fd0e1f5b12c0e71c4b17ed34d92d3794d3cac294945580552a9200d74dbaeb0a17a2ce7e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033639", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22130193fa05adaee596bb9896b886a31c88752d6f18f0d5c804929cb727ce8999603dae997b121267ed59d5bb229af3b": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22132c32bfb3ae0cc31e4b119346fc882ba65343515a46a4aa9932cbdf0105d123c9d4ba9bef3be885c46f52c8c058d66": "0x5a1a549172a49f7591155007c51680ad8ad77571cea04acd1b0b84459e7792340f464f524b4c4553534e4154494f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2213824be956ddcb02bbdc8707078a0ad86cb4a7d71b52b87a0ba07d245f92cc52dd40259d14190cd15f36b509f7ff511": "0xcad4349f82754f223d99182a3f9de949c41ff94e672f7f548e7f4e66c04b5c1b036b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22148a915b086b8df3e3f451d5cfe83db7f90cbd721e0f6df172266f725ed45095c9ac42202cbd84abae8b5494119a938": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2215732379e61d4fe352771dd1f73b23b2a5a25fb22ae60a8a24177845715bb880e16ad84344e91d1269ea6940e929f5b": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2215a57003350bfe8b80a05321712c0b56679005100a874118c6c38e5b3183ef6cb71193480d1de0699f9bb6bfedf1f24": "0x8c20d46f86242eea89c400d5c478207e05c76bbab29a748af8aac90d627e1a010242", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2217cb5dc80e770e56301e3388342372f046511c11fc56b5492bf9fdb92b3ecf551ebb98b73241db611b2a44decbeb856": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31345d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2219bc92ff0195b58d944c87fa8c720de407ffe0ae098321e72b2b6fe6ba331285a2967a27430f04375910007010589c2": "0xc04f1633da0ab6cb71f71ece4d1a5c32926d3f707d250f66ab712d65eb374b2d04303333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf221c70668af2f47e52784ab207b66b07abbce0e01ff970a8d2462a545370e0b992e069db055e417820aeb77e6870f9d09": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073133f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf221f2017acea08193896886ba2d42fc3652ff057f98f0c1bed31b2fd1ccd8de4d4acf957e79b3f71eb69820bf0dc1d22d": "0xd2eb07f02043788e254d9e2df57be11566d241c56302b91199b4647947af30200232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2221549b91569912fd4013a346530e6c7982b1616f2b4b963fe2a8aaec915c4d3f90aada694bba3fa5924127e67a2456c": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2221e1f9b0353ab6960a7ad450d81b3442aa7daf7650583460d76859d7f4fea90eaf792ad9cc03e9bcc2667f165f00b36": "0x148a35cad2b2fe9cf6ffe0baf5f4f2f4ef894263baefead0e797a1e3e6d0a07f04303137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf222442364ee4b51b29758d2beabe55e6f92def6fae3d1c6c1598aaaa7dfbd7038c3e047da285f993929e25bfea8d04b40": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f08303150726f7879", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2225a8729dee127dd905734cc5723d49f2cce76137e2e2d9bb63e081d4074cfa4688d7d9781d2888f36634f646da62561": "0x02385caf9a08b92ca458a0b817a8cc303cefd5a0c6e108cb939e04242b9e007d14537562517565727920486f742057616c6c6574", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2229e03382361d7cce206587758627483faf6bf2c43d534d180a04d58c2838ebe73f3c98e0c3699f224ef0ac156c65e23": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf222a6b1ea3c39e6c998b84bf80a02a9461aef0e83444feabcf8eda628195f0d756082152cad2aaea5dab16de839b50931": "0x945e90a1afc83f0c74a3ffe96b40c4ebb5397af04126bc2db23036c043be4a630231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf222e875cf6d620f9a2b1c59ab9ab4cb2eebeb68d26988495f05130309042532d32304be1b171fba3f5f2ac94ef7d33dcd": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d60b4b6f6c6d6f676f726f76", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf222ecd11d7d3362f6706cfe9a27a85d258cf5dbc7c0ac18cccaaba93224d0c254df33169cf4d38befa64b443b6c4fb75b": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5105474f474f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf223263a99547c12f80c2696d7124ea053905f923a67cec79db9e1415567822f2c440e794c4a38b43144bfb1a044b2a2f2": "0x51f78769768fc88c83546881a768523b3c70c2500159047a970ac4ef16768af616436861696e536166652056616c696461746f722030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2233e4a764a53db1ddfe7eef21269a810a243baa53ed09e1a0a8879b132121047f10b53b52b4e8111292a196a15136737": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090b6e702d746f67676c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2237a4c02fe6a5829ff6b543bb92a7abf9a3e193ef4ff85f45060902986dd3ba10afd3e4a0749b6718119298be183bfde": "0xbebf5aa73bf19935376f19460dacf00bf0dcd021ca37d6a2284cc6347dfbb13b033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22383fc60043a329576482e8e243f133d8a0e42d190d3ecaebf11d3834f4b992e0fab469e6bf17056d402cb172b827a22": "0x08769738ff8d53c17d6e0f0344e52c50a5ef6b61a33389f4dc4adbb7aa2f384d0a546563686e6963616c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2238ca183d088243cf879ed73fbb18412b8e7e832b85afd9cac90cf30ab4477265f14901bc0f25b2142c2e488bce87352": "0x9e826b5434525d00c118f3f6b0a29b7f432be7bbd18659d472c5f07298e76949076d6572616b69", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22440dac4070e76a7c2b9acdcbde28b80e8e0ac0aa68a0c138a3aa84813f0accae4ed7d6ae4b4905495026f16eda4e069": "0xe8e0ac0aa68a0c138a3aa84813f0accae4ed7d6ae4b4905495026f16eda4e0690b56616c696461746f7231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22443462acbc703f5e2df878bba1ee1c24e7dac693f453f3c407caea7909b1f56c8385dd3ea46059c9b0cdb32c19fba3b": "0x1e76b9da6373b204c3db21d2a7097a79afcf32f642a516980ae26c910e70a35c0b4b5553414d41424f5832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2246208664a59c37b8232a108546ef20372c76dd7083bfe6b601d39dca6288bb8adaa0673c914f3b0c40ed812fa4b5429": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22467b0c1d946fb21de05bc940b426851ba7e6ae859516ab7792519d1ccc7781409bc58e534f54f4edd0981118d53405a": "0x2aa53f55efa82a9820f3c2569d4e52dc467475a1a11cfc9861ce5440316edb7a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22471b594c790c4a8ffb77218de909a518057b9f8b71f7e97f0bbb2dd94b1a047992ff072d07aa77f0a3fba1c28884025": "0x7c7d2fe83c4af79c49136f0f8c5f1a00cd8d0aa91c94fe74d0145cb96d688f66032333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2248c079ff9305a5205356a76ad501e4948edca59aaf9ec40d9967f298ab5a5a2bb7265eef18569d5c065f318da512358": "0x8c2625b0e10c7bf65f283c576878cf00f67478d3dbb6bf39ee62b3ca19ce893d0c54616d6f204a756e746f20", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22494a79e75cb38aec1af9bfe66916adb12c0e71c5200cf1cf22ac62ae2910eb3e485a104f610f1535ed1e844b78e2914": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033635", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf224a74414112e2385bd265ce7c5a6e384063dfccb3cf16ab95e3af6fa877724d2ec90697596897ea59069aefe5c223f58": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf224d4c97f800cd5dc7866d75f926d746de816b1ea4928a0d642ee4b4fa99aecfb717bcd47086edb11316254c2e5844d29": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033739", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf224e5fcb31802ec9ec4a03b048a2a3cefe6897f5eba9ec46ed569cb3c532d193f04bccc3971b065df4239a18a1e5e527c": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225213251c5514dfcf9906296ab7205d51907bcf63ee4c58723b0457cc8207bbb53841e33ce3d2876f8cef269c5d4d3af": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d6074e6577746f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2252377a7bb8a36ce28f1521001db8b4a605cefe161fa9cb1c1649080f78f9cf7943320746e75dbb4b1cbdabbbd6a6638": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22543fb90c7c06ed9092a68a20140a84a0c8bdf19914b8931589d6658da943de4de04cc1102902a9e30d3d3bc68892c02": "0x0a912cf4f0c7894598d81d26f2c24f6e5c2541f312462bb576593e9dc549146d0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225b4b7079aac7ba74397e3a110131c9af204ee949a256b7e81637b358f1d8519458e9b79cec9f1e345ff9d2ad4516370": "0x9653ea6fa2a3e4072178c4de671464a69d9c72c7ff7170bc76697b46b3947b0f0574657374", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225b6c8392d70ef4e5d8f3004f45443740e46029cb6daf09d2408e111ffb14010387ffbe77b16539839cbff1473a3a402": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600c534158454d424552472032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225bc31d7924c787aee6d2843d367cb517ab0ef4391500cf4634c08dcc0bafc65b9c787a651ca8679b8ef33a6b557fe5e": "0x70661c356f24a2cddc859fbae974cdff149661f165f5e622df3060bcb8e7b373032332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225c76b12c5310d71a248e2b47d58cb8514a0db74267a9c3994944cb470c48a9f4c8a01df05766b96eb29789e9f049748": "0x6280b912d54001e1ac0bbc1023ba9a16974a6c23d22e817e97d418ea94d29642033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225e2b1e96d72f8f2faf2e5c02063642aca2ecbecab066ed29eb6f04bc145a5fe6ee36cc0144f46a722862cf28dba2c67": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf225ea69f6ea3dc893c1ccd4a4f289aa91c83b0bba37f25f365e26efbe6c9ecfa7905dbdc0b0e3ae60b29980b42c509c6f": "0x5ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43035632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22606754377682cdf7d7a8dcb21d08351f8df53c69120d27f523d11d1704a4dba9448aee78ea4f1481cee14fa15124511": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2266a0ceb0a9776c0adfe016169dfa4d6e35a5bb9f11f2d71940593c4ff87fba89a7ab269825da6282025c43bf0b4c07c": "0x8ef5289702f6b8c7d22b3562ffda7d5593a5f6414226925e72097efbf9b257201c526567697374726172202331202d2054657374204163636f756e74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22698be0e43b2382133cc789436152a7208ec5cff0e253ab3a5d73aa4cf0db459f5128ed41f6b4d3dfbd99924f4346c58": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843066e6f646532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf226aa69b6d7b1b9e4d2643e275020a81f7ebadb760b7f8ca8280f493f1604fa76e90df43f3ce4b084ea6383315b94653f": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf226f32bcef343335e33d4bab42719c055e0169ecd64ca393045cc15687b0f3355f7c86eef2d25182c731a45e55f2d165c": "0x7042479798003022a5753c8547cb0de8ef25e2471e40889ff3909fe714e24c5d033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2270dc31da1c0092261b8550a52a8e63420cbc85619baeb354c068a5799d8ffa8b822505221d5357d7e70f2a3ebe08ea1": "0x2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57066b736d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2271a4d5b71d1e846e0dd6aa4b729046c4ad16debf0db0329b8fa6806c88a774c6d4873579225919e24c856728b575d4d": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b325d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22735323ae77e3c46dfafa9b41fcfef47f20bc9dd454ad586a9c7d259068e87412a8ea309a006e06857a0470704122701": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2273c980fb676ea9204b5119d81a5d1667243fc7f5f476ee7c5fad9de673f1ccfdf59c3e92530c09d6d584ff19452c87c": "0x7243fc7f5f476ee7c5fad9de673f1ccfdf59c3e92530c09d6d584ff19452c87c164d45494e20454b5449544141422057414c4c455420", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2275863690937cb22a4ad61ef020a6d7f021ac11f4e66c8e210deb3f90609d0be4335e8c434912a92fbb1f67d3800452f": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2275fcb0ed0b1f6f90708e70c6bbc4d423818c289aad92bbce3185cbc77619f99bb38a139fd9428ec6c2c97f964d01467": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2276390edbde8a9d2dc25446e08ea7a4712c0e71c89568cdf09515dad33fa70b04cb39e21d8be64dee93e17569f962129": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2276b1a0f287bb8a9e322448184a1b7d35c9752508d09c36f243da599f0e850f3bea8f0cf5c43eaefa73bd9c6a075750b": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2278444534ff3156fd33c6448afc51ad512c0e71d378b0a623f2b9eb1b44430061c4f2bab9da7943fd286326a98b54a6c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033530", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf227989d9fbd857434a0a130161cf82b32b06e4c7fa18e7887887e5b7424e8e2131e2a244163d4a70829f311a571d57c2e": "0xaa18b3cf52cb27fd19d5b80fe7982ff955e0d5124dae26ac360056f401dad8460b446f6d696e6971756531", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf227b5d660cf77fbb3ead82ec363f68f9338833de858facacb267fefbade2fe127da59cb1d3653e5acdaf5aaa1c0bb6f25": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b356804554b31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf227d5512b6c4425cfde8b11f1fb419270c6379520320c2c68f6e75938afa22a71c7f3bdcd1308ba1e7795a2fa2d9b9066": "0x9a92ad7c6dcc51fec9f6d98f8316406ca42bd04dbb029d3ce454330a20fac0770231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2281b941957d5816af49eafa5806d300712c0e71c6323105cc5215aec99c36c3931fabbe7dc4a439329be146133235a36": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033637", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2281ddc7d5bf747f585a24d4c7fe7a0bdf6be65cc16c65708bb6a0e4b9958ffe23d1c56ee5683670a69dbbbb70c10d507": "0x6467fd4e7038b925c2422357380d8cc0c5f17d272f639af8fcfd1f1156de7040236b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22851fff2a13d1fa403c185f3d398a4d752acbe4b065282c5b36e7c1b552ccd1bae6039f9e2abc5fa4be566a8f5f10e45": "0x6610405d8ddaba4dcfca1fe4d14f83496de1055fe97efca594f2813a82900e40124e6f7a6f6d692053746174696f6e732032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22896f4c3aa70bf38c325627742de4508b497cbcd9414ec2922ff86acf2e22ad1b49aa07be1182a9490c47d3170e6861b": "0x8a56b1da8dc3f4bd58630c15f5754ee634528a007ab510c86a7e1fe6e62f4166065a656e6974", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22916751bacf7a1c689bf4bbd6ddf0371e396927763007571ab5c30a835b67c150993def51b98681dd7a69e87d7125cf7": "0x1994df5bf0f44342b1719bfbb1561286bd81b6d84f577f55ef45fe7ad6f50e4a00", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2293eece183f6ea017f64f2d32b7f3c45669bfe047c0962dc3ba330b1fb1a83c5cb5262c964fda49b61e9f98a8c759c4f": "0x629c17f4f4a24ec53f85a7beb1c70b13379fb8e4f969560704d2c25133ba8d2412416c7a796d6f6c6f676973742d74697073", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf229481b0ce752c3130d1f37b3d4fe62df3a620493bb740849dc2f946560976cc5f8fc004b038cd61859f5be0b2ae3643f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033735", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf229bfcde621156468aea93db41e872cf912c0e71c536b024440ad0fd64324c6eebdc0e497207ff42489ca8a2489f6e327": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033934", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22a2caa522dfc409937d4315e23476e3fa08ca28409640a6ce8108289d3a279cf6fc3f0657b60f3c41f89d04c0e5fbb2d": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47712416c7068612043656e7461757269204262", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22a3b31e12f5823b68f1fee94bdcca383c83bf4af534e16af8aefbc56dcf58d3488c77601bb1abdebafc2fee50534af7f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033938", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22a691636b3a3cbef7b503826101e110490255910ad0897e5c6746e33cf138d8f38a6b46b685d06da2802f83917827c04": "0xb0ef511fbed15d88d75933d12bb50b56d1bbed109380b2fe0c7ec72d441191520232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22aa943c74840f4849588bfa41167504f0cbb4adb01af79c560636910430458ac44cf5fb9e24482279191e6ad8aa33148": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22aac3855e73925bf3eb8bfee2c26195e8d9511843f9df390385c97ef304025decc2d42cd7082db58f5b5e0523c58183e": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d07444941424c4f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22b4c364d171cae9e79e93ae2d94d1e623ea2629ce3574dc7dda1f20721f7d7a1109dea19ee434885d768c5c9f671271d": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22b52e9d7ddc972bbe306b9a3332fb9d2c09b9c71f2c39942154cf7749268d6978f82a55ab68d6a412c628b2ced7f9d3e": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38077061796f7574", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22bab81ede6f82fa5c2d8b7bd197504de679d98218b5d055c770d3a2a406e2e56a97083100bec05cb83f530632dc8c313": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090e3131207c204368616f7344414f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22c0fea6262a5725940873b3385106acab4f8dd9a19e72f2ae65f989872a96ee2e239a9e135a868bddcb4dd278ef0f97a": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d0b4d55524349454c41474f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22c1f0987ad658f71dc2e4ee60a1b701f38bc883d8fb7ae97eb3a7862cff1252172f4a901264c84b7feee0a900a64f77d": "0xa2da2913d7db19baf0a41dc40a73d75bc6001ce1691c3ded78e4e86387881b4c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22c26bd89a02feec6d62288a29dfd9e0312c0e71d43df157fee32bea33e2335ca841ecf4689f61b53af12109a990e8b38": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22c57288c177f6043c1551509c78494fbea073956416e6c3fb74d4423f458a028c9674f147468dc0e2ca6d2c140bcdf4d": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22c6bd18357e634c3d6411538738a0f0378c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a7024": "0x78c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a702408636f756e63696c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22cab4c1eefc06f688a24c634694308eee6a1e58c3cb43cd4bc65bc251f9c7a1a3de5bc3f815a643d658c8c018158aa01": "0x5889dcc187231dbcba0bc0dad136d1ecb09633bc7cd5e27e04daa0277009ff2f033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22cccb10f9bfae617e9c42d761e0bb8ea4c9f8b6c9bbd518b19a4fe57cb38df839f9d893c577a9106579de22ab1ebbb36": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512323a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22ce1c9b86fa2ec5b4854f8f77041d3be98ab313fb0a6faf344c680e6afda715f41179d993ab86f25e481a6259c976343": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22d09503a21fe80f4242378babcd8ebe7fefa1659ff7e86a20f110974463d76eb0238f0e02f6b526df7d586b0657d52d8": "0x54faa9f0cc59a977e73147865791a9272cd4980db5ff2eee27096d34ff2fab6904303338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22d40d3242214a6dbdf33b455b4c4b7a9ce2e98564f421ca69a64608d68480080f5f317f4de4e400af3c065181e0c8a11": "0xce2e98564f421ca69a64608d68480080f5f317f4de4e400af3c065181e0c8a110932446f4b53373266", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22d4c45042aca35d80e31f4e40f1f8a5dc2e445df84e611e629ded39f69fb3ed7877398ad5ce82ae4028b1cbe997043cb": "0x625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd4241e5b315d206269742e6c792f6265636f6d652d612d76616c696461746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22d75f9545b5c4b10fd50ca6508173793ca66d6f03e32d64a1a0b23baf1da3ee469d7d63c69ca26ccf3b47752d1171d02": "0xa26f9a811e752199217945e52bb96fb08229d7904bc030f6df73b5b4e6bbdb6e08436f6e74726f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22d846da596a776a6bd99ae5793e24c351015f23420ba4e90023e3df81d423db7fe2b2691657d45e98f02816e5a832b10": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22daedbfdc14657ae4482462d70f2935c300685aa838106c3737c9e6c6086481f3daedc1b1650b84cba9405389ade856c": "0x868cd54faea1a0e45836635b2bf658733436ec69c5567d651be592392cbb69dc0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22dcde81a7dbcd9cd9afe0b401bd1f79274047a9abeb7a65811ffaf6ce18a99cb02e092d317eead7302b23e5b99ef3c14": "0x366c1d734b33c714b0e0e9f164426e66e3bfa97b917b23e5d3674f4a2074f86f0b434f4e54524f4c4c4552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22e84a4a945b3b1e334fffe4cf4b0bb91645903e6212a6142af81631297af316fdd60dfe4f02cfefe20d20153e7945720": "0xa26f9a811e752199217945e52bb96fb08229d7904bc030f6df73b5b4e6bbdb6e065374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22e9e656ec5a3792f36a6a7868aface0e1c6861821c1863896ec24a799c6ad302e7173b8674e399251bcc571e4977c729": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843116e6f6465322d636f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22eb711fe51521dc536c3e8ae8fe4e841007f0252d2dda00e8007d8ba227234f9407f28a0584158c1a74b2e4401ba921e": "0xa6500e450888dd3758b301a0f99d433264362547ca7d0f7631ea53871aa3be350556414c31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22ee35136874b9ce15e28d8e9fe9528434b639041c549fb527faf54fd7e915d481955ae0bfb42842cfc3d63b5b98a0f31": "0x62f21f6587843801d599ed5855ae0ebdd2a84c822919e80cd6f12899e50887720258", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22ee8b7ed0b4a8d7af6b8a1dab4d4be4a3c53243e05c79ffbbc910d8df74e4d1ae0197db16b7f00662e2aac74c8ceb302": "0x8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22eee8ffb69a3b9806ddbd458373569a65cb36ec4414da2e8f8e6be74901ceaeb189e4bae84245b00640f96ea36814501": "0x38f45bd8f6341dac4486eedaf00f2357cd19b8d4b8f0271c7340d56fe02bca72033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22f34922e2a2922da4afeaadc44ba7499389af7a171ff4ef270fc5c602f1570ae7b818fbcd797ae42b5ac9f14454c5b4e": "0x8429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee210d5a4b56616c696461746f7233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22f46dde8630c188f0d344bb26d0798e012c0e71ca519959bc745598c859160abc7bdaac3949ca44ad9712c4a35e80c3e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22f4aca9679cdcab872802ffaf70676fc7b9a284d4e600ad4d23bcc2a12a3e52130d96586145ad8246bb3db4a7cb2e0f0": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22f6c74d69b0ae9e4be1134e0d1034f2f6418bc819ab0a29b18e03aaf851463e3718bdb8649f5b864ce9654febf64c950": "0xa02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d5505506f6f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22fa7654c4aa6230e58f65b5b66a6d4245e5167d2749eb21e8d257aca0e738ebdf309e9e0ef503e1184463de7db3d0b28": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988838", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf22ff897306f626450a6a589a03993a3d8403c772cc5a0320a23db863c40b5780a9390665df1e3b4255f32df1a0afc396e": "0x3a154cb2e55ed80b9b671b240ccf20a8e2a47a7097a61f156eaebdc98fe4780a033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23011684e56d54a238826b5a928963ffaa057612349296f2777068dd47c499f36c5caa498c22b48f26c09b9498ade826f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf230117acc9de61be2ed1700dd8e07a10e9ef20ea6b98e87f656d7f23e0b2a310f45d6a6550a211e7df67540cd8b9c4b4a": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23055ef7f3959318572f2c72f84a7c5df8eabb61420c17a6e92eb2ca99f0e2cca15015784552ae332bf2105a592b80dc6": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083136f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2306ae36b436b332f36093f5a288c59659a73a50c79a8b6552ac4628486f70e2efdc87020ce5460f6c7c5153429a61f58": "0x56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b11504474f56", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23078e3402bea8a74fcad86d904ad4337206c097fd6569064a918b1fe42c9a302ee3762daa035b0c44eb771d6c34d1d08": "0xaa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d0e48797065727370686572652d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf230b0a6a605cff253ff46e0b65f43a29dfe41a0fab97ce06654fe9813a999a9d6dfb51bc7ab1f35dbbb27bbb3eac4c164": "0xeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b2347763648033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf230f6e5348ce7d0c052619c0f815d14e9aacf425049b018fb55d17640939a6f651697b153bbc59a060a7f2ce4b4c5610e": "0x7ce2421f6b3c80a00c8fa9476eddad55f7bb9cc2f54ad916b4969c103b5fd438033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23101377354ef463b6d4257bf9070e62266f3189c8351e824c55ea40817590b776431599273c4bd4c853b255e8cfb1b10": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b345d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2310a359dba414c4ad563710c41387ec112c0e71cab33ca9929a6406d6634c55c8d28c63c99b18fb6a2c1eca3037b144a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033738", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2317d821afe57e9ed52fd1977812baa6dcab8f3ac8a49d03d47e037a2f63bcb5f38a180115c70db29ee4f379e2e04c335": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23180ec9c6e76f1efad95ab3371c1287b0036d9a09a0a63e987a6c67a59b52f9eedf6215852cdb4fd034ec99475a17f1e": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf231b722186de98b1feeda0be9e4f1c17b6804069db501a5d23ad862cb312892bdb603740707c1948b797d4d30dcd76d1b": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033937", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2326acd80f3ad3abea8dd2ad7fbfb7797f2453d14482695f0ec5b7ec434dcddaaf83e09e570e22c293906edad0ef967c7": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2327a1f18eec3576a5b0e4670c37e3d6415647f856e3beac82df2fd67403a0fbd18fa79f584646112d15d61a064a681c5": "0xbcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f6200744656e616c69", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf232ade47d0b89a6e7f0ae456172a9d04ce8ce09ecba19cbfda0c26fd052cc50a5365b22ced871d32fb6a2eb1853d2bb7e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf232c8c774a969e47bbd831e4ac133f990acf39cf23dd3530b4078b43141f0a0ce5c19549909b0ce4bc163984e045d9b65": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23334f94241fe9fb24eaa8c30bded18705611f54264f980f8d850f4fd87ab8eb7e6c86b99b396f50d1aed3c5cafcdfd88": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f37", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2333e579bf94f3417638ea707ddbd3a44e79c699eb894e1a203b2c6deeaad557fd51fa352841d2d178d3bf78aa0bb1172": "0x36b5dcb29928d8a462f493e0250e895158fc4fc54eb5d00a2a6701fe36a4283d0d5069636f6e62656c6c6f2031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2334f674ad4718de3cfdc31e0294ffcd5ea17387e7283543fb633e2a9e0f68d39e172cd5624c7095e6d81ad3468f35b70": "0x828618dad92559461b479508086bc781d88434e5372229cf66ffc887672e9b3404463153", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf233541aaf3b0b46163c153eea9269153b027d4770a8fb3ee70bb1d12b64f93c794dae984ed5e991267c7e776c77470f5a": "0xdce117ad72d855b586a1c7ab1e2e1400b00418037000a81a26d131eff8486b770231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2335dce23fcb736c7d343245e1d97abc904f231f52cd2a234dd3a72a7c920ea6e10a7f85abede1a9b4062428bc303ad7d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033436", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23365a7a90454eb5b2181b283cbe5afbaac2fb3fedf57f058e0c786f94c46f57eb68ad57982f0b96f56d5d438119ebf37": "0xeceb07c477bd40d22f83b08cce78f2375bc1e4cf188c0de1ffef592570383e590232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2337cfd982a6aeabbc224f3da01500866e81c8e2c7bc6a6b6de522487e8829344e992a3440f957a52c86d93038b9b3dc8": "0x3e3622fb285dddefdf8f9ac2ab59aa34e2abb5a316e9ebdc020317220e75f879033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23409b9d4359b7dfb24d65a40f241da551415a9d9719c249bdeecbb9b746639f743e2f238ef5a2b227ce206eb93724a6f": "0x5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2348d794b1b37ec54981cce9b89d308fc12c0e71c55443e88a1777244fd0816a9f44562ca36e5b9d95d45f3d79a1cb560": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033932", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234a57029046d165a045e3e0173bbf4d512c0e71d2b06750f95b1dc2ccf25272d0e77de2fa9efb9499be95ef938d6d766": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033531", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234b9ba15342be66c3c34fe0ec01d7333023fe56458783b5ac1d399ab49e8ecfe911d282cf645ecc8b4d9803a130f685f": "0xd88a4b558274e57737ffd3fc9741848596199a29d77fe511804d20810cb7605000", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234d09a76db87bebbfeaec04cd28c9bdb12c0e71cb214fffe90a9fd96c396cd776ae64fe664bd26e6072e7328b1df5756": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033938", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234db77d5e2b41fa43ab18b6c949f624eee69e45394d3fea77645868ce1992caf33fb25200b4ae2b41d1306a46dd5f720": "0x26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b14810416c69616e7a615f48697370616e61", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234e0b7a0e3a3903166e63810a9d2a71cee9862cf3f7401d7c82461127102626135ac670ea079780708e1ad2c537d9c2b": "0x02098b5f718885f0d6f0f18359a7d16b44c9229857934efe66daf4d9f0eb7a43033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234f4bb0d555326ab304d10f0e745dffd8c7afec700f1f0c83226176063f349c34c3b100f192e4bc106c3305c1c5e4c38": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073033f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf234f4d45fd1eca356f7713bafcba053589f3218e31dad244bf47477de316c3f46a721149ce003f4514eedc2042b854e66": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083139f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23557c6d2ce145dbe718e6e91f686834a5ed6723c4d9632bd0c61bf182c0904ae64fe1dde3f5f1ffc532d41fa14e28405": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf235cdbe003217d4cdb9e41b7122a7b63c1d3635e81c3048b1b2459aefff519b68d0100710ff64578709ca3da808412054": "0xbe1c7627fbc96a38d3a3cf746ae545f60e2510ed80961537d9b4924421fbb56204303034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf235e88ba6a5b07ce8a43b3b5d55da335cc6df02cd907ad64313666799a84023c8e8025e7f9f5483a05823a732de3dbd3e": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf235eb66f50ad20fcb207b7adce083d729c89604d1a2388771784ef80c5577fad1e75bb2362d5d578a94e8dfb3d982e938": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033730", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf236058ea1f2c5cadae73f75ddb39fc6cc9e23e3588757c7744916bc6b65d9562fd12f807da8bfa23ca354ad5b40bece4f": "0xea524b9e0dd9bd336d31e71bc1a172388b10d4b6571ace5e7e6e8364831102160231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2361c4486fa7b6b3d0aa538738cb50d3a527638f35f3b999cb645e1e70a49e7b798a89c36b289bd366056d39115c18ae4": "0x2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57066b736d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23621938acaf24de980da0e9c3da0446b2c527cb7d17e0fe6df0e0da303a71f3eb46ea5bd309858389666ce6dad8efe15": "0xacab23f327e732756f5d76a43cd32830d5d8a9a489cd9c5c6a8554a3374da0561cf09fa6bff09fa4962057686974654e6f646520f09fa496f09fa6bf", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2367cf7925f6f916680a737f9a92b8452049590cf81393b2630cb72573fff37feee32bc143021d79faf80abf0356d5450": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b32315d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23698eaa4401c9aae8e9fa5d181e66f6c3c0579545b855f0070c2ca5c79342e333fe698081f709b7da3c9117b0b6b3e66": "0x56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b1150d494e4449474f205448524545", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf236d6172bf7cbe1ddf739ca148d279129be86d32d322797f67dd5d386d29d8285cb32504a767956fc58ed8f04ff703c4a": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090574756779", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf236f31208a33c3240383aa8dc08cbdcffb06c021615bf00ced6ccd77c0bc8c820a71e819bfc48dff36ffb12d7ba044338": "0x74c76b2bb6e2e4b16fec1849aefadeae913aed26e72e2101a4dc34abb3e4077604676f76", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2370090c69e14b2750bc45822b5040c3fe85558af1d02241a456725d7ae7370cd1a5299713a970a312c99d9b14d90debc": "0x7ec5e89c029a05224b2759566042a94c54966d125934a8ff8beb8e0b017cbd67095472696173736963", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23712d1f525df891e11270a6023f81e645263f205d321ac0063c4275a7daec9c6b5a34b3f0cb835ca2f4fb22bd9e55e5d": "0xa8a99a7f49f1d3d72656674fea67bc18454325f00c9a5921ec6010c43409d43e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23786e839ef62a0a379d944c73fbb9273a471c7aa909cc665212bb36003c52c5d3eeec39f96556a8242e861c5dd7dde41": "0x5ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43035635", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf237bcea3b60ff6afe7745cfc235b10c39227d3663b23d3565e9f07343f2218b47f60b3221f8bc32692ac60a22c7fb936e": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf237f13f1af7ea279c40b76b426c29d2e112c0e71cb1a9c147998723d2dc7ef44affbf359be54830a570a5840e2734c47c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033437", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23815b690fb1e6c01eefa6eda95f10e6f6a92b1cb54e218fd9815b34f7a3a35ed39165a29edae89c7086040b59d074c72": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843066e6f646531", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238186145093d353002ed83a10cc0283d0a88006a747b712bbac65dc015105c9cb6d29ba60dde6762a881975c6b1b1a02": "0x56aa4370ee3d21b98ec19f0cbf2106a036215937a15bbe517b24ae5fef4d38700f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23844247ae95268c32e9dd2d7b8b7d9a532e223d306f0e5bb9a9d6dcc9023ef06edc7717db691cd8c5d85d33b3a1fb136": "0x36e132f4b16bd325ddb6a3c63562f23c18dfd20bb2c785d391f625f481097c1f033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238741c2654cb50f9a002f53a367ae7f06eaa97150a12560dfe00d1cb77f161ab7c29b6243193186f2d02e933c4c4067c": "0x78c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a7024036b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238931c8176066b77f9aed90f86b97084eb14462cbcddfd07593831e6ebb7c4a2e5f0acf8c052f6d76aa550113bb72b68": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073032f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23898592d9731c762b9acac9d21e88f7af45cc1889ea605f6e375289fdb22c1acf7e99fc60cca3ba5cad46a21661a7720": "0xe683743954d0cb555a54ab21cfb8161f74e689a051d1ac1dbbb94df70be3d81e034b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238bc4b013bc95d20f02635b88b7009fc204c52b467988d585dd9cb7cebc94d6e56d8b89042ee692b5739f7d78c39a554": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238dbbaa13c7969b4a463dc1b8a0ad7146a3770dc90105517476a48c8280337f2c1e39dba204c254f7bb51c8d4ebb435a": "0xaaa635f88e75ad58af28925d0c21a804d87a449469e45970c3a52f57aba7b366033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf238e589a4f59e457afcd8bc58a8e109c25c97521b3cb9261f89f6b05b6ad17e9d148ba5f2cc03daabbfff35e0bc2e3f0f": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf239385193aa9c5a517717763b381e47a2fdce688a422833948306f4aabf043af4be9fb2be40fc763787f30233b2510573": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf239e3ced1badb912f71c02885076ac7979810e91f40b4c50ff66c7d228a9e4109e677c406cd6d2417bfb11f0899345e00": "0xd6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c25065061796572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf239e7b84c16f204b681bb1bdf953ca0da0e8b9d19878dc5c50ed1ab180f4e76cf7e208851fc6a869b28dbc1ce6208dc0e": "0xa49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e0e4b534d2056414c322043544c52", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23a4fe5f633342995c5aa4f049d03a9a6982f4a55b705be63aaa88e069f4f93a955cc2e1c7dab295388d4a739ef6cb34b": "0x60b791f8467410a5ce2e880cc222933ad50705664917bc9d190a52596b9871211246494c494752414e2d5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23a7f65fb5510634d37492a50975e87b00e794356479178e2d043755c671a3db6b1882700744cc0f570a84fd33e257e26": "0x6883b9f834076b9c1368e7692ec0a01ae97a52c5cdca957b5d31103423cfbe45044b5632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23add3f6b98a0545125042fb29e39d33968ef8bec8b0e59e7c456392b9f560a48c0abc26faeb75715b1ec4a804f469f10": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23b04c507ea436bb9a9c93d64e7af6eab55e8dea9080f49b00804005fa39712a313dc6bc21c3de49f172b3f46e9f586e4": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083038f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23b3a63572e436f0ecee136c0fa58a4f1809275c61d0a44ede0bb18a54adf2b684d44d1759e516e46634aad562fff1c2f": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23b418ebcd97f2d989e574d67b34c17ae8aae19fba03bdb71cf735646aba2d56fa5b4b83aad3d96804d70e9559ed8071e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033835", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23b9d8487e1e99c39710593982ada7fc3caad545c5c3d4c99b7866e2bcf2483dd7cc7cf578886586663aa25a96bc64205": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23bbe3877e9759bc837101da925889396c34542e51274a1c23c1293574ed5da6a1c28d092ae4362cec0eca403c02244d0": "0x9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d2775507536861737461", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23bd0e40608da57a96544da6b957241613051ea9c01a7134f6a3223ea95a09c4dfe0bde5b0eb9ff7169fdb85d7a9bbd73": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600c534158454d424552472033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23bd344c9ebf5e59eedf1843847c871d3894b90350435a6f04536b6a1c0f50e83344ac230902f07fd5e69953e8824d63f": "0xe2b3d30136a5bf1ad99ed78efc1c0cfdc6a2c65d3e30d86b3303f3533e155032033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23bd81eff8cbbab65308778f5254bf30df836649df542b24a1b63d80916ee743d4734640aa796648649685dbdd430c362": "0xa02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d5504435331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c31353e3949df4431d58a36717edf39c4ceb4225a9a168528d1264733d5b6bb5176c0eb31bb4ca3c962be4cdcbacf71": "0xae0ce04d8021516cbf0a10c00c4e721319c1e91c729402b232942f9e2c1523200953544156522e3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c42ea17d7eda48361e37ed8dc6ba82888508e0d4bb18e50ed1435a4260541b1c53ed009a64801727c195d1f81c08fda": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c4cda34fbf68b7405466cdd8a800b49c48166c755e708cb83a61db9dc635e91cb496e2659e07fde8aeb09130802010e": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090a6e7034322d726f6f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c6bfd44c6719b63b3f647bfffb348161ff9f838183843605f88f6b88971f887fd069e00f4a2894ce4249a8a70199a05": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c950a22bbbf9f095356cc70ad523f2bd448d47466cd9abc75c90e52f3aae5d03e772ca2f13db8516aad2ec15d341d2e": "0xf4492a28ead0b315fc68069bcc39470c409d12b4e48259384d63da411bad0129033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c994e4d167380e1e4c0bc4c67a284c7ceda44cb74eae64cceb6393fea849c84b6e7c0c00278b6339b14f882fabae15f": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b395d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23c9ef9777fa738330ccf4d6d7937dce0345e9fdb6c477d50a5c7be50ff581405ec6c151ed4ca2c25cf21a510e6bc7e6b": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23cb413cd5bf22ff85f90fa1fcad2e322cc6bce54889ca98332b8d289e4ab347234a96a1d5389bd183d7f991791a79f0a": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ce56b1ab8734c5968aceaf9245ee3bb426cf52dc5549d7f8fee37c20ba68afd3443973a05bf692185cb913fac808873": "0x2cf0838b05fb182718de859525fa1e6d53d557e5fcf631ee9ff44c619810d43b0c476f762050726f78792031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23d940ea66d0242ab8d2981970f3b3c26b18c6f19f15297b4a80fb9f6f29a37e06bc31c723be672d54b45ed42feba74c0": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d60744617277696e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23de0201a5c3de13ca3540b4aa7802dd139083183c6b196c695c642c6e521ecf55a337cc2bd5df2df8fc6d6c0c7d49c7e": "0x845498df40e85e2ba9d9e213d1f476e7b147aab6a9098f1bb250e00251ef8f5c0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23e2605e31335e2ca4270fe35a899521490f218ede5ef0e08fcde53a9913c8c01d7cc28d31d21d89071b6a8d9262d8376": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23e75fc80d0f17eeb8214e932c319f810dc0ac1271ef05bf490a482a38512b68548cc3c244285635c32ed242b33d79dd2": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d6084861776b696e67", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ea273d4a190071d6fdb797818ffd8f806bd7c7a1535c6be092a798d558a5757ce89567f7cd939fe203163a8c4264e6a": "0x6ee5ad3ea0da40510f11f42c3281fd543f5a6bfad54ebef7381a7320bb509a0d0247", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ebba5b303f76f66c0b5a99aa006a1439ef2c74b5a6820a16eb04205a9d177c4244a94cdcfe1275039ef8704480a3905": "0x9ef2c74b5a6820a16eb04205a9d177c4244a94cdcfe1275039ef8704480a39050863796265724732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ee00faf9f453ad7378336788066e8aa00247daf7503a9b41fb6c52c11c760f769266b44fa97bfeea3e0c68f0e3db04f": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e510550555a5a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ee0f7de312bddf6b51e8beff38791058ab2f02be4ea327d42477029cd7e8ca99a1b1ec34a9502cbf42c1701cdeee774": "0xa2da2913d7db19baf0a41dc40a73d75bc6001ce1691c3ded78e4e86387881b4c0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ef44fc31bdb69e29b9d2a4ceab48c96b5adad0de4385f3ad6516e39fd6479b85c22886cb0cb9fd91ce52919fec98bbe": "0xa763de880dfe6c4bbdad18fab60e27002f648c221df5248b7d44a575b4bc734200", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f0cbef457ce226c833eb460b5f12fca75a6c848edd2d131588ed2fb322ef45909d4aed3b7ea1197fce14220a68fcfe3": "0xc43aabf384c6baf54ef9712a96be7c46533b538c05d4e6c687fe09b109664b28032d4f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f21975e0edf8d8beb4ac44015a4d67810002bfd652b0ab50a36adb9bc74163a4385c6b4ad8d3cbef794c07716ee0d6c": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f23cebf0963a38a5c625ab1db9c035cfc44a7371ac4b798826aa05df8fd3cd5aa1b62f4a1a7cb9c95b7e83e99633a3e": "0x625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd42416f09fa496206269742e6c792f7061796f7574626f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f36d3a747da18414e4ef43993219d4cf40703cb81f0aeb2691f6069bbb67a5a84b30d392b6c5906100b5a6cc57a781c": "0x5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47054b413032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f52876896e0a20445e445dbc940af4fe62bc1402d84b145bae2ce9ac2e50f7f613b7a986734a896af65be8f51244c4e": "0x3a81aea610fd2332295967d1c7846599774a112f2d6cf7e3ebe92392b7b177790ee38182e38184e38186f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f5490f034ae5dba86ba90274da5454712c0e71c4fcce3bde2baa598b4b4b15e3674286d0dc2c03441be1bd48408d92a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23f85806e0e25965e177bbdd90fefbb705a37c441df3f0fed7ddef5581ff70437b00fb071e0b09537caca8adc4354913e": "0x5a37c441df3f0fed7ddef5581ff70437b00fb071e0b09537caca8adc4354913e094e696b6f76657261", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23fcfdc11ec0294abb86dd5aef563da3eeaf1654d9143d99dc782d03b496b3801e06a4c6405ae954f40b7e7475f9ddcb4": "0x1c6681030fd4860fcfc1dfad9ae55fc0181229b007b6365dc4c8f5fbe162554c033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ff37d7df58f34e416370d6f61c5cadb54bcf53ff5d97b41b38a3a5ccda86b3a3b1d7090a20747e2bdfb2cc46a38d514": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033733", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ff6ef5180de4d2caa0e1267bbd89cda12c0e71c7daf0347415ea3623b1441a1f89b5115bfe82a57a132f72d186a2469": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033930", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf23ff8c3f77cb008c342242cf0f5b7a81c0c2fb774bdca7e1b4627e9af2a9a66a0b67e7164af0fa26f20781e4b5fa2dc42": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523435", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2400d52bc4847da2f15ebb92c161aff8f78283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f525": "0x78283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f5250d45524e2056454e5455524553", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2405808113ad68224168753ff4cf07d3e086f2422947fdbebd39a68f8708064bd5d9caab70d1d6a51abff895db91f5655": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2406cb41ed80a5299e6f17281fed8e084e2612e76480388dcc8dfc46219130946f276496403ecbdd37a6d1a14c35701aa": "0xc8d887817cd801c256ae0adad712737a18a89e23eb061b7002839d16530fa0d8095472656173757279", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24171da74e75ab4be68a2140459a359b6d0accc7028daefa6de2f047e4650d3ad13d5e25bb0bf2fae4eb8ff8e21674919": "0x3674aa73951219dbd27b3e3fc5847b806c68c1de38fd4f22f9493a461c80e9030f535550455220574f5720f09f92a5", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf241aaa00e0d099b674905d2fa0df29232b53bdc896b61a0c3facca04307105b99e44841190d41b655c127dce9447ce2d4": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a0747414c415441", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf241d1714dce242e34ed024d261bb002c94e8c56b618a0c3750e9f005d58590bbd6b088c326a1fdb075294a8565b4192e8": "0x83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f58906546f646f73", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf241d616e843f204ac501ad5ed7c39b27caa672cf29483bc35d2991a17f143213bba4fdf81050113c483cd205f68903236": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033834", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24216e006c2ffda91e61000d30dcd90a6e1cbdb5c7c39209793cf71d71ccd0a5eec8ee530069837073032da3ec4a5a714": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf242499cdd4b0b387526e607e2c992123950d1a6eb9d16f107a16aedb586c8d08259b212a3c54563f183dae7e1964d931e": "0x8e06bfc989509d6d625c085209adb405867bdbe4f167ded7e61ec126c683165d10416c7a796d6f6c6f676973742d3030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2424f2a95714746e854f8c59ad6890acbccc49a4cbcaec6b03737d84c907628a2cc104cc75ad817ad38292e5bb76c527e": "0xf4d95d4c5c0131969148d3a16b3d95ab3d051771d971a1955d7e745b0a3a4f1600", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2427bea476838de38dc1fbd13fe407ff51bb5e480e154b39b0e8e272ba015da6daf3f9f634fd357cd5f8611b29b7d4e51": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f063157696e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf242a32fa84d9d0a0ceed103e07e2094fc62a791daef6863829ce7969886db050a38050dd52ed6c1a685cf7897e67f165e": "0x6a325e3630266fda0ef7f7725ef8199726e29d569d609f3cf068c4db7e82591a0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf242bd09558096b3bc5a5d0b4375cdbea7304e4137516cc6a906f03158933c2430744e602d6549dfcbf5a0d767358ae419": "0x62a79f3b924342c4f634d8ebdf77f50ac051d41387a72d22f2f38155762c125f00", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf242d5132ec9ea541df0aa87ba39094af7645c0ded9084b8186ef4aa2d83ee1c5ab326757267c41c05444e15c657438424": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033433", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2434d1f1050ebdd3f71c9cf66caf7d10112c0e71c74bc9329f210cf3871cb0df4e3139420f8cd1260ed214f6e310d5969": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033733", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2435ed3017503d4c9faa796b59ef2fc8f322e857c9fc42bcd84f6f4e2d1f7f892baef31f1da5731d22796cfc40e4fdd5d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24369670bd3c4a2bd4a51e70cf242e900d84e08c6dda9a41fd1d44b01b65c7787b48723679a1d0c83d1d9a54798ccf01e": "0x7a8b217ad8d80016336be124846210559ebf720aecd25ea0d0d11c10f1839e7105f09fa7a1", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf243b41e55c99a7dbd2733640313257ffec82d85d99021f559a9a4f5387fca2bee170d488b97e00766b5ad19617c52c17e": "0xbcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f6200845766572657374", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf243ca307dd8b0fb706dac460ef965f751ecfd5be6a880094d44062af80777e61f10e15d6a8910cf7222bb10dcff874eca": "0xceeccdb6802df2253998f9d4f928b120d51110d1d2afd969b95232bc167687020e626162792d6b6f6b656e616b69", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf243edf09e07e0b49da67583ea78c544158e2499f22749aef04333796fe92b73c06cf4e358a552604ff3e550725774f924": "0x3d6d2d20735ec00c7753d3e6071ad1e2280288a98d7d89c2a2b7fe08bf6d05bd07576f75746572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2441059018251d8f7bac08ff27f40ba5bd7a7116db2d1bd9dd4c7b37c204dc775888f9310a1a18877ee913901bc95281d": "0xc8d887817cd801c256ae0adad712737a18a89e23eb061b7002839d16530fa0d80c536574746c656d656e7473", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24452eac7d15a4caa1515fdcab047ca67b0820d7db40e2a9fe96c7ef2e810cc51a7da195bc995f329ffde72fae04e7b3e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033539", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2445eb2c87a3389c40f9db79631e28362a08c23158a93a3aa7de94d3ced1c9e1b4ed1efbb1e29dab0363b1c8ca4904e06": "0x5c3739d60301126756a7510e34f9d656d4435cd4fe64bbd001f1f3473bc9c33304563031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2448cf37c141500505ea658232325c94412c0e71cf41a90f7205b9034bdc9380a95bc18669cd5b4d6b9452f73d468e74c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24490823f910054ad342b544618de7e4d545e8064f8898a29d4811e09b207cf3302e5cefef16615f8580fcd8fa63a624e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf244e69355112f106a0108abd7c2b1039c83b401968c58e31e421f96e07dd85ce91d985abbccc84bcea5e8f098d97fab56": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2456e2d8e634a3783313096a13937da4012c0e71cdeadb03446fd3519d1dcd4f690e40df4ab0d193b476a94a0b6588c28": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033436", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2457b91c185c520b91b93d213b77b021d12c0e71cac0a27a2fd30bc24907dfcf124197d52af6e9c9506f5bae59bf08879": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24602e5792f844968dd883366d34e6f36c6645597fb2f300ac88b96e8283b06d99319905bc509151e03dc83748708197e": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2462c8d5d6a95e7b844524b1286805b3af20ddf4f2db1f9f800d70ce19dee3812a5d72bc275f413de1ee186ea7473bd18": "0x7042479798003022a5753c8547cb0de8ef25e2471e40889ff3909fe714e24c5d033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24636227993340534dec219349d721d3486d678feab565ecb54f78dcca7036db237002aa86783283b8721de7611d7fab2": "0x2ca8e96b721f074e95a3f7d994c370dab688fc85134de7e2e7d4589d0a306c51033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2465c05d754aee83ce22fc6daf8fb9f3ff7034438a748412760539f824f38f3f9ecbf77ced8716de97c5ade5d2444c8c3": "0x66fae573cabe4172bdfc60dfd00dff703a4323854715c151f868293db828190c0f4a61636b20456e74726f70792032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf246644d0b047de0c1a671d2da7c3e2afbc6a8eba5ee9f02ca31a31bf5de2dd406adc9c55df94001f6efa28370b154544d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf246c867310f374b9379468cf750904427d07218db071b0b88f5979d57b52ad2b7706856f7be0021d30df75fc9ecfd2f64": "0x9cb0d4ddd32f9332dac7059de238b8e489afb55502d1756d7f50b78b58e20c700232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf246e6648c0eef3ebc76337a2a651e7f66faeef086f38d55942fa48bacc018724b488f46ecfc2828d879c7b780c8f57b0e": "0xc07040b1be7aedb10ffc0f136b7e147e4a1ad56944c1c76d6c2f6ca089cf316b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf246f2c5f574f732e90118cec8ce8ab2c86a7db4fd5d907242e97c2db57fa12f1eff6a103556f8e99f916483ac6674c372": "0x3073c378b0833da59cda1d49d711f37c9ae20ed30dc3dbb842ead63dde5783310f464f524b4c4553534e4154494f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2472d945308c6256e7a670fee7543b716fca8ea3766270fe9df1ba7a4a7298a908878ed61581b9769100fbdd4164b0060": "0xa845ea35913a0fbdec49687ebc5b1579bb632c080ce61b02919ba40bcf8892760233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24748b70df7ee0fcde2805f260815158e6ca5cd252f0f61e8a9c5eb72ad6d9452fcc1de451f7bcffe04cee9ce73c8ff0f": "0xd453b6e497b6a89979fb34eea715720d37c2381c8c51458be04296fd059dcc3a033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf247bbf49bc47c17666baa2a0f4bcca5b38ff2fd995727bb6c776dce0c1e127955c1f191db6aff56c434a6738fc83d4eb8": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf247d268a008a09e7c814a5aefc77010b5c83b05f03d7e0511d29dca7a11f3631f6a0bf373ee6f96bf99882421dd261a4b": "0xeed08a5b10b1835610d66ce4fa273c8e2436b978c9f65442efb6074871b48a6a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf247df7ffd2ae80267570cf3ff6085dd3326e1393aaa4e42b5d40f234eeeff068825d5cc50a3802e8e2e488694527b5e7c": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2480f693230d05ce7c07079ea1a1a47d0d2ec0a695435c6324bfc9b27dff217e5092e2972b0123529514006e278914c7c": "0xba0518b2408a0883ce26ff4ea90f8639ac05332bf82260fc45033d7b5baa0a200231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2485cb150126059a2b59f09fa05f9f39c5059875dcee1d4a9908203728cea5bc20ef93a366beac56fa161e04feca03443": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef48430c7374616b652d7374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf248676b154b078b376f7179f8d45df23212c0e71c47eb3e0eca577bc8ce7ec63eb978b1e36e73daea0449935e5496850c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2487a39066ca8313f9fc0adfa2e66c257d4c6173852da2969c43006a3806502c5f6bc23e1f3e8d5507baff2b5e2f1774e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2487c1ea83596ff698ee5c267bfdf1f2c8c6211892518630b6e583e09dd395211035a508358a80322614f9894bdceb605": "0x88b9f3a722747e8f637b2583963ea7f1215adc8c75c3957554fdf92fcbfa50340853717561726564", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2487ed75c2026a1bcfada6827c95c445442e37b2268e7e97d6345f7611dba1f4f58baa27382b87cf536ebdaa23c3b811f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033931", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf248b792e5d55ceda46fa27d90bf02ebd3dd2404caa71709d521271bcd64cb771df96abc1454c1bc2db5be8fd84f9f317d": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf248e0f76cea4a67bdec390bbdd0fec4dbe4dc1df8790688cc413fea804c4158d1142db0312e091578306e1ec9fcd6bb77": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2492e02ccc834cd02f4f10c1af60f8b706cbed2071a6b6848b4d170409de00af2da5ce2245166c9a5c32ae79fcf44876f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf249abac528a6bdd59d4bbb34a70ab50f21a2b2effb22453209445e66e170f7beeffb3b66c900fa8fd49cbe9efe9eb4942": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c0bf09fa68820534841524b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf249bff4cb902465a1f5ba7fa253223c4bf25f7a8dd6b648eac453d60b0052dee3cefce2ff56830eb7cc98292c8885f958": "0x9085297d964ea873a23b63151b4c82189c1314c31fda6f2d71f83133d0877c5c054b534d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf249d19d0b0439f08373f9bf84936e2057e57259886f2db2014f3bcf26e8baa581816f49c13e010bff9f52d5d9ea3ae68a": "0xd3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a2340644656c7461", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24a0dbb67dc3d6cc94f0995925c189848cc4790e6ee2ebf4271fffa10d4bcc2a4460ab377a49ddbedfbb647090c6a97aa": "0x76016fc20a6457ff8953bf29686c5698c28bbfa860669ddd07b386c910f1107d035631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24a30e50780aa2b2389a6fb3266118da5f67795750255b9f9c19a23a72960b240276a404d3c5fcb4fde2cf5759e88f704": "0x74422321a842adfae9419ecd3983c4fa2da6e879ccc1db031e54c742bbb9bc030231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24a943623aaca68cff5f3c9cc784bd3ee22b6c1ab9ef945b7279a730423cf50ca4e25feeefd4953abdc0fc8caa403f70e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24ae3d3d666ae697ff8678369655c590dc94a444165f95b45857e4bf1c4b0f784eb2e6f16054a87dce443de41c6d09c1c": "0x08b3b1930f36bf7fa336c7abc044e75fea45cf1c903081e7e0bfbd664a80093a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24aeb0d2ce707eab19d2c51b7e33da6486d6f646c70792f6e6f706c730163000000000000000000000000000000000000": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24b1c57136faa1b6758e7628008d14b7e5c8bb12c78741c7b0ff4659360c78bf5da3af34e842a60f58e53045ccb070302": "0x5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47054b413033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24b2797725c20d711c01159e65adc42f44ed4af096401134ae34367a42cf8bb5da1d3c878fe08b512baf5e9a4f7e9bf43": "0x6069548e7913a106991a40988bd63d25996d6788f9302ef0a86ec40b4e6bd36f0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24b4fafaf3feb5179324fe3643c74cdc354e0103cb355b3f6f357104c4cea54675909f687aa106a4e47d741dfde35e376": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47711416c7068612043656e74617572692041", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24b90b65f45d20d5fad5463d00f0112ec0f6987ec94f7c186a7c76fd7792be048d9e73494daaf0f86245f2f68cef20b2a": "0x2e69ac91dc2b3e54afd2d74736e7dfd95faa1e738dab066c80328980c7c9076e0d426c61646552756e6e657232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24c0b163e0fc8f18feb22619d1b45a5ede45d4839be5ec40b585c1f08ac284e656075327d7038aaf795d35789ab10f15a": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24c38722755eaa48ddee7115903105c0f30cca6318e5c3cea1c72f33f541532ab6609b50853627fcd587bd5883d52f75c": "0x7213534fb02c7638d8d7caf1f62b983225c5aa76b8c14d249f7a704b50ba850a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24c5b05db14954da4bfb354ff674c2f34703d07f2ac096e6b0b998fad5997c7c9b1e1f417603c350e76ad99e5c19aec04": "0x9cb0d4ddd32f9332dac7059de238b8e489afb55502d1756d7f50b78b58e20c700234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24c7ceb04eb2bf9b9876b7a27998fcce5f2ee0d3d7e3d57e18249e42d570e163d7f34ac68e81c973b41bfa521f2e99e0e": "0x3c7f40746d04d77628d886dfd469c9bf606232dedaa248f5c219d32da93f4054033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24c8b3f5740c3eb6a6128f0a0a7614c156cdac27581d1f3929bf543452b7da444e03457ea6424f84ef9a372ecfda077ec": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24ca011902e6e9d2b02349d69c7c09d462c249c9b361d3c490f66848e4ad2fe71438455108b3a1f0698160c6d1d27fb24": "0xd20f2ce6c2c876745bbb399c6290cf4e3ee75ce31bbc7ec11342fd5118b98e3c035842", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24d2c909b13e573d0f96340bcc560415e661712f60a13d05e0c478d73f3a2dea9766c5d4b54a84895ed8b7f6a3f950614": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24d4c23aef3f039771889d31878ec41333c982ec4375d3b3e9c950f540316fe84dc53191424fd073613cf4dea51cd156e": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313433", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24d5d05fbf3a4df1fbb2ee0c9d6b5069818a06c67746e98a3cc1680079a706c133d5e77d0c8721728cdd7c8525b42b752": "0x8c79cbd600c63f0cc90b34e7301b7cef8c93f7a404cbacecab96901fe53d46400232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24dbb206d3bcc537968224ed4ecddf0706d6f646c70792f6e6f706c73014d000000000000000000000000000000000000": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24dcae1b443519203be02a76ce2b1215410a89401749948f217611353ab25e1789474699fc06ed1dbbcf44b7035f48875": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee072020726577617264732e61706572747572656d696e696e672e636f6d2f6b736d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24e04bbd20b41540666f251d09ae526c10600cf06f1c8e912c9d968f1de9fe6ed32d033b8e87bfac698602c25604e2b4e": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24e2a67fa8f631129a0bb9461eaf8465f3eeebded302e53d488d9b063922447cf63e7638e60abdce4259c72dec9126a35": "0xe2a0a933d2b1e2dfd0c06baf42557bf4aa2ad84866859e6c869733d6baadf1520c637279707465676f642d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24e4d8f095e102658385486802970aa4254f79360caefa910ba4bc6e26760fbd44a07a9fd4244c6fc7f58b0ce620fe15c": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24e9cb3de883952c0688831aeb26bdd9bf60f07a15346b938937e245a9bc5f757c0a516b249d11c40ba8b0742109d573d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24ea43ddc5cdd8cfb0485d7efd8f7ed754662cd48d69f8c1441434bc2c80a825ded8eb41d2c360f6ced694798678af7ab": "0x2c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d41033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24ecc547cce29c45f440503d562517d9ea8bc182820c46f4dd6bd98b76dbff06f8565f0004eb1a9840ee3f3bcae1442d5": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24ef5bf1ce1351b456611366722a8515d08d3e6f92d4020b4a2a6d4dff33fe485f2883070668660980fdc064f12dcc129": "0x02302a200a9ead164617576a79dded74ccf9094d6222cdf93ed575422e9f5837134f6b74616e6f646573204b7573616d612032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24f17cba3fd8f4bd74cb6a2f7101b9c90fca5925e677ffb072b404634eb297becf53c269e32c7393c9b9dec8d256dad21": "0xe26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd040848616d62757267", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24fb8017980417d688bf198bf773aed92513b35b8d169fb8f713504d252be09827c6e9fa2197df14bbe563efe67af51d6": "0xbc486ed2f394da6e6b58b130687b48d3d19f756ba6d0655d37bf58ff0f59f9740f53746565626572204c6567616379", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24fc60dfcaf236a03848d0e7d3f2dee82fc8d39aafef0cd3cc978a3b1354b65853a12b9f4ee0a55af14311a4de76b7b16": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523431", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24fd2e33d55a8d00d82a2b2049384f672a83fc2798fabbdc8d93db99a27dda9b8f6615cfef0b16a3a0aca93a49e527475": "0xfaba4f34d61e2defae2db1f7c712007824c194ad921959efdb4a65dd174a590c0b776174657270726f6f66", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf24fdfaac0ae09eada38716c0b3212ee71407201429e0f6beb3a79213b46c4f59f002ff4da66dbb0bfcb66cae1cc1a5074": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf250794acaeb679fc61e80cee158ad5e26b3c0b3afec6c57fc99dc2656c38ecae97b5c01f2d44bc9da56714141676e3ff2": "0x5a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb99340a43524f57444c4f414e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf250879e5c19596eafbbf169c0b7fccaeaaee302e198305536eef798b55edd01e28516bfd2d16888597da705ee0e74df0d": "0x6e99996cc6c41e39696f7c3bc4248e548473b68fe2ba26567771be07b7eb5b190f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf250b6a9fe615c653477e3366ebb08ff9c64f9e43cd95c94ded79fa17bfec8a8d745932f4d7679f8b06aa9e13f915768b2": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083035f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf250c5e58a66490b175883ea10bf3c8cbb52e2931449f8d897dd10fe7f753414821fc90698d940050169a863db5093bc3b": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331343a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf250fe3047b874e3c5579f29b9e784955f6e63e1f89c023383484d1f16ea1d9fd66d46387f929dcdada62f8e5dcfcc9221": "0x2e69ac91dc2b3e54afd2d74736e7dfd95faa1e738dab066c80328980c7c9076e0a56006f007400650072", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2511494b67f932149a18b93e39dcb486788d38dd7b7e450c426b33bd49db5efe92e702e0c799a5adab42be4fb21ed7566": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25124fa226ff059a10fe8f24b98ac8b501aa9d3c51f17264aea16d04dd1b899fd311853b2bb2944487ac2c43f1e304048": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033934", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2519c4e21e4012a84648aed8d8458e90426acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d623": "0x26acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d6230e4c616b6520566963746f726961", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2523d931d34550f8428bb0220ee5d879ff02cd6695698754c7d8a82ef80e87a7c753c95c028557d15c393b9955fe74151": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b32325d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2529b051995d03c074da080c5a99828db98cafd75bd233ed0674c7493c67d589c4d7e78b69cdb409ca66c0f3a7391ec06": "0x2cba024614ea8ccd1ebf7a634f30b38d65c082be6aaa92551b9c3b4d1f15ae6e0853657272616e6f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf252a830b1ee63ed7d3f89561c6195b3d6b0495e49f3241a065bbf17983665997e582b1535c5410530897e3889993f711d": "0x1cf3e5e0a3f8f198a63f5f7284fe493c23e88161d92d2cd418e52d050e3bd22b074d6f77676c69", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf252e1519060862ad3aeca7db222e2424e12c0e71ca3fd568c3120f3c6eb7825d957104fd5e9bd9848ef36a1d5de03b008": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033839", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf252fd9557943d5bf1c9573d3ec3b6a98b4e9807808e2487f1a38ae21d64de700342dd7feac9c23a7293da4687e668e71d": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818076c6b736d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2532ab6f6fc026d4a6643dd68667133ce10230b53a6fbe58eb3eacc65cd3ef675e0456529cfb02a97eb43ff93bb6f8064": "0x0277ce02b2ac78ceeb9ae4fa0a595005489bf3f5f77898415e32a3e9504a531418546578617320426c6f636b636861696e204e6f64652032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25346ee68fa23361590f60872e6ad00dc15a946a44e88eac4fe2568b67d675983e9617e83d70d3ad6d9ec28707203be7e": "0x1ea86f3c82538c486a25d8abca26760e57e76a01212419c7f1c8b510121fca73042d5142", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2539271040b3fa17a151e18555982ae3460a8e45eea9783d521beeb12cb15c6e9094e5d755749b801ff1a532d0934a90d": "0xaa2b3e0a8702aebcb83d552838a17902b2403b0f16c4e52a4514fe02df532e3c0d303220f09f90bb2042454152", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf254338a78024ae39674bdddb5cd6abd43ea00a7167ab2ecc7f024e26e62a15b24c02f0b30e967cb91621169e3c780ae4e": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a04563035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf254f3e98bd9a69f185f1c099c597a8365bed497470a04ca4c13caccd69c7827e3ddc64473fd2d7c5d496c71061f452b05": "0x6467fd4e7038b925c2422357380d8cc0c5f17d272f639af8fcfd1f1156de704023d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf254f577657837a4e532147a687f23213f83dc7edbb29fe81e5e29f18ee1c35a90b6aad5637057e3087699d38e7eea7394": "0x3839e4be40e252a56e2d7c8e89a0c8eb990df5910714fea61c6e1d3b1c4c550204303339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25530d6e304ba2f8eff835adb61de17793c5862ed65c524b7bb3564776a81904218f44f3d7c35162a608e39dbadbcda05": "0x3c5862ed65c524b7bb3564776a81904218f44f3d7c35162a608e39dbadbcda050a6e40544b6172757261", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf255316268e460368587259f3f3af448352ecadcb36865c859f998d5538bc2629b4f4aea6e03dc4cc110bcf0eea4e06330": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2554e5c145db815f1f77e40bce8d396b6d41ef941dae80043db2c5bcecb8501ff3f159ce810271ab6fdcbf979de7cd373": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf255833fcaacae3503dbe52b27182d70a80ad8b4f94dc8e6229e2c448d995094cdc1bd356dc14c6155467ac07ede18b872": "0x2e69ac91dc2b3e54afd2d74736e7dfd95faa1e738dab066c80328980c7c9076e0c426c61646552756e6e6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf255924e4e69574c0cdab46034db8b6f9334fe2832004fffcc1e28aec7ac35d29142b892f10d8d0c301cd26c37860a0579": "0x0cce9e210c473fd1f20178fe889c178956ea1cf325c54b1a439a88bc62fe7851074e4f56592d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2559e7c86d0691c4dcfa3a682743b0611063e0fa2cd4f4b448d507f9d5b2ea8c85e8947a93d92d214be8f4b752807886e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf255bc1197df809de11d807374b141c3eac99cae7c82bcc7d4c6d39b376a3f9a61242bf4ff1225866f5f93acbbf8ac922a": "0xd65d5c1484e5faf8ad32907ab729add8ffc2ffe0f29bc18015bec2c3f8ac7c6604303032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf255f6e7b996756cc74c600c7dd197ff1066a4ddefa00f74de69a30bb8f6f87c50cbd2804768c367f3fbad5663a98fe48b": "0x1c6681030fd4860fcfc1dfad9ae55fc0181229b007b6365dc4c8f5fbe162554c033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256318734facf3f8a10bd6cf2becc981412c0e71cde22f076b79de5a6fc30cd47be3f5629d4be7fde35d769e7480f4911": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033638", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25671790e3c7a701b2517fd2852b03e5712c0e71d17404deaa91eca3e64e911f5e43ebbfb80fb21f97c4d453ed79bee36": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033535", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256752f9f8d5ce6b947829aafc1b19e944e1f1d2881471357ea697093e5e68d46712d2b0e5b650945c4ecb571ea43757b": "0xd6c29a7c39cee45b0e045a94081bc188ef73be2be086d66aefd850fc7eeacc45164f6e46696e616c69747920486f742057616c6c6574", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256819e69d1b4e0465ba4450aaea081ee1a746810bc697bd6b464f5115aef1127130712a70960abe590c8a6491f432232": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a04563032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256a45fb05964445f6dcd067c402615abe69aa84285f761bb1942735db2c3d443e29dd3f3da5aa7a00038bafdf93abc57": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a04563033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256d701a119a1507819cf606313cc66cca82cd9ba02bdf8241a35d6a434c019a6078547e238df7a55c6dde5c4deb2f12c": "0xbc63ced3f8fec642128f2aa9c37e989a9313a67e9635dd85e8bd689ae8d0ce1d0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf256ff03eaea16c8ebf5d4c014efdeee2e166a40c58fac1476b58784d0ed59ae59fc516a4b072ba8daeda31d638a53023a": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988837", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25716b10cfb50c5acef6d1a0858444291e2af982fd853bcdb276d9be46e6bad4cc8e1af153d82638d2bc829e6ec3e2a6c": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc6605504f4f4c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25716d5eb2b434059c3a47ed674f3c80e41593cf289a037eaf22bfa42c5f10c5325340bd4f488cb37fc72f65cb83f51cf": "0x44da8d011a0f821b2e39d6151f8e17c417c0e09b664587dfe2021a194ee95d7404303334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2573b583b387a3bd826c32978ea0ed0e8a9c13c25dc960c282ae2a76f4e315ed20c60cbdd08750fd45cf5b2790f7ef045": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2577c29443c8aa9c98a578dedce880fddbacafb0ea22a692dea279a648b8cb44649ca71629f9fce6d69e03a4869cd9383": "0x3c1db08dfc6786bee3b0e1b4aaf51e80b6f2ec9badbe3da87d30ad7605a2bd1604303032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25795523df7d9eb4aab5fb0b8b47f2a921f81e872efaf12f97f5a40b31afbf874bde9c0225e89511734f749b4b1d680ae": "0x8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2579585ee165f6fb748e8232dfe0d0f2ae541547dbea2dac6e485f82ea71b8b1f6fb6696aa65cab783b20f9a6c574e644": "0xa6c5f0595d6ed85d6260bc682d4a68a4b4e605d43c67d56f2765d196985497720b636f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf257d195f17fa6af701e4f6105769471d19406aac741b57c529a2b06b06124a2a9b8f8374e072e4b251b13a5c0cc9f617e": "0x5e0a4ca74bbb4da39c79954e7875519fa67049795c02a360412f3ee41a020506033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2581e8ad688578056d036cdf1f8d33b8520f949b07ac91763cef16c15fb78d5370271add31799ab7ea2e940a89af4672b": "0xbaf3f15b9e83dcfc18b50fe91e601fdf446c008c72c3d17799c21a64877e8d3a0b436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2584157afddf0916a8942604846c9d7108688b96ed623770a0b2712dd9661b3c1280da83237db214ba698be7783731b12": "0x482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a74512360232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2589cf380e0b82377485dcbba553646f4acd510542672c65c7c05d56c4c6424a70a0e426f3899f2eb86751cc2e08ef124": "0x6edfd181c979c11a1d853c8fdef7b18e85ec39bb67ce723130b25fc24232c3580f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25932753fa6c22debc1bcae3c80c551ef0650217af71d75baa1bbc577761208886a474cfe4c24435b0295586f2f66a571": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf259867bf87f39d463de936989455b2e82603ebd73cf850b644af5650cc070cf1328601427c712b21aa9746609de2ad447": "0xf2d0eed0f21b82d4b15802153cde2a229f257f01d003694b2973ef785a7347660c416e6f6e7374616b652032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf259a5cda96b7e066af61a618e2ec7113f106b2d295a9a3de6efade304e1efcd123cc66ec27ec92a075964ecac7229f54b": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf259aa4b30d635834bbe3b17ffe590e01bb08c0a54f1f153adae9df1b746cab08c40e3b949cf2458f80ac43ff256f2c17a": "0xb8a40f17f9fc62194fe1b12c10e8a2bfb5efc7057b119f4ca3b05ba96eb7da6b105354454c4c41524a45545f4e455854", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25a19a249f9a9acc87e47c4448779ba642cbc13e6be77e7af272d495780c1b51130e27e41e95d8d651733b53630b3900e": "0x2cbac2d6ac81d2169fa6e455b0497cf0389bd5dd2a11b24a53e6d94053765a7700", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25a31cf95fda855a49f008d4fa2ca66f8d2f17cc6203b5746b14c65b94077e29f02d0b1d56a0ba445458c2d7cf9d55a54": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25ab90ffc9708d1a3176157121ed81a65203fade9dcd70e45da97d67ec48f8c5d8176be2e27cf3a612b6d6d7473c05577": "0x76739ac0320c03658b64366855bd6ab037488fb23fa0d183f53b989106e25a2d04303239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25ac5336faba0796609159ad9c88a24206d192ca910ffc54858d1b7f553cae619803b55c69af50ee3bb1846f1715e6db6": "0xa763de880dfe6c4bbdad18fab60e27002f648c221df5248b7d44a575b4bc734200", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25b59008062bf10ecaec566e66e5af6531cf675676957827846bdae1e0518c92b31a6e0759b3616955445ba3cf8a8111d": "0xae9749dfdee466ed67835efa51f04d74db27d75e919d7050e4f5b7f481f77a14094355524154494f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25b6e148db97bae3ff6e9959f16d4cfca72020fdf0cdf3cd952082b52fd11ac0df4cb360850efbe0d096126efeefbb6ca": "0xa26c51051a9031ebcc5ae2a4eb9a72e444a5bff59b995ce4612ed8cabe8a2a700e4272616c65205072696d617279", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25b8db23b5ce4c505699e41e822e0455e4e3bd152d910b6c892f23f85469cd64bef5d7561d69475207c60f4542cc1257f": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25b982a12cdee42e465dbb9a6466dc88e92b53a95c31152cb0d95a968db4dc8e14cb7f4495f4b3215db38d0fb6b8a8287": "0x83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f58904424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25bc64ab2326698f1348a2d90fe95f824868615ece4f03d149458a8a54f26f7b3992f687e066d7c50e6713f72dcd6285a": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25c3f8ab5a0972dd662a3e2166addbfb0cc710cc1444b51d4cb4d22fc47a446df6d8371a8831a515040a52d7cea1fe70d": "0xa0c077265fa8ebb05329c968fe13efc415460cc5c379fb392a652ac07c9c2f7d033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25c54999bc9fd8464af0dbf1573af3117e2e0c7c189cf04f3600624f5fed3a2107ab6ccf9625663babd571b492bb27cf9": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f0831436865657365", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25c717292043b8b023d37d0055112c7278ca5a28e878867689b757883005b39b269cc76cffb757bc672bd9cb1874cd505": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25c997a05fcaae1f7f8c43f9f6d36f666ad3ef6399e4bf49bf0ed9ade88ec40ef21be714cf9efc112306cc85c194f758a": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25cace6b06122487f6899edcfde030e4e9e992661473c1dc00ad7f67b734bec003561ebddbb7fe0db3759b717ad20fd25": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600c534158454d424552472035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25cb0e538cd996389baa4717389419eb9b4105912d0268f239b12bfa0aaa290903ccbb52e0ad2126b73a4b20c9189bd1b": "0xa845ea35913a0fbdec49687ebc5b1579bb632c080ce61b02919ba40bcf8892760232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25cb2a48982d22b1a6679694abacd9244bca1d58132476c8e285668c7c1505e248d79821cc2244724f026d438a27d470f": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25cbfe699cce3ea3a42b238084f199e5a26e07a9cb1d3b8827960bbbee94197ad2204ea98db2d54da63b57bd9eac4374f": "0x3284bc8ce3083b62e671d1c5bd61db5b3fea95a77967341ca8834a69cffcfd5f0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25cd5604f22dc70a5804a812a435574025ae96556bd15eed67a54fe5f9191835994d94c18a764ea4280bd03faaba61774": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033634", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25d1943fc0a7b557c101e38228a007d3a12c0e71c9267977ff8cfbf27005fca3918833daf0d77537e8f879fb9fcdf2b09": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033931", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25d7fae57fd76b925f7fa0a9c2b6c4ed28689cf01de26619d9e77cfb38911661940f6fd4b6379d8bd5558b8b967d51db6": "0xae963c00a7c164fce3f4a8ed94ba0a87e83cc1a7b192726836819cf1f63c522b0c56616c6964436861696e73", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25d85bff0d6337213ea348d05c4c11c7f84c45682961f27cba9bc64fceecf20016338daf42fef5cac7fd229d7727db168": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523534", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25ddd4eff4ab0da0dd3bbcdcdae2a84495edf939d9f238bce8f74fdb215d853697a5a515b0f8b3a9a9d64390265f2cad9": "0x983c5a0d1f1e697c1a0f9798bc25543603751b41102d41c3b0e23cbc6e3fdc0b0c566978656c6c6f5f4b534d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25dfccd679a8f331c1ad6d882e30936b512c0e71cbbe5966e17c328e1a6f43729e44d4dc326af5ea40f9c0e103b19cf1e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25e40ec9d74f1117534a8fd748afed5bd12ba1a34fc5e9b81ba8d7e486f223a2cb47e30c8dc185888aaac0eb25c5f605b": "0xde7fc70edbc29190008415c3b6122dc6390b738453c6f1213b59942b2b76e54a0943757272656e7432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25e474e5cf89ede702aa65a076ba4571e72a136cbd146b0596b9cbf73f4f2e402dda2683568e33d1a3db791ddfaac6a4d": "0x7c4e144380357ad3e690e74f5b7bbbe4b7d6ab1579d4c6d7c844ef003cad9a24033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25e5c57f7e74cdafe635452961c31d13aa7f6170f731a0acda2c9edc8ac9fc21a0b33e448378730b2392cc0bb76b55546": "0x0e038990f47761a17f45c2bb01c4c7746f4ad67c7d0c1dfbd6915372faae911f09f09f9a80f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25e748e847adffd35d3d3855748c2aac549f2baaa065d3e927f265702cfa8d8eb83cbea8c64bb01d19c5c184b8e2f5d10": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25e9a622d499eca2b47da48307f31c02a599aa7c71c2716d534f7f4ec936d9bc547b4e32fad199466a389b09b139f3f8b": "0x1c378d545f64248bedae80ec34f8f29551fc9f814f8491f8fea50f10fff6e22904303232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25ede6d686847e552985919cf30b1f997af5a44d6d0b15f2cf84afdea4c76b1321f84da230a61b0c73d755d9cf5171a6d": "0xb8a2a7e1c5807c9b5241a00382d483537eeaac2fc756dfde564af6a368fbc27504303134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25eed85774e7cec34e3739c21814420858bfca4af1ecfc9a8af84f239f3f3198d12a666452d0658069c451723e7d922a8": "0x2c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d4104303263", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25f2351b0f60616b6095d656542dd3fc0a8070648f6e43b7d8a8f10418b696130d2046c10645f10085de80e6098b85f09": "0xfe56be5933800b45a21ee8e9817eae9f49099fdf4a20076718497092ed43c62b00", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25f6101fcb7a75c45db167543a3bca4c7f444730a05ea7fe71e53277384e8e78bc1c8b8c6858d2b177e16d6d1b05c1265": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818076c6b736d3034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25fabc3b9626c2002a6b0d28adab59c3c12c0e71cfab0ec8e02f65d8114492d2c9177d3add541219bd8ddc00ef4e9b66a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033935", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf25fd8f37d0ce437a9a9ed9b00ac09770c1244669ebe06bb78a7513e888ab43c70dd2f0c80e90189b02fbf62ecfdfdf66f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2600940c11f4d4aa49291d6c008357ef840de8fe2227bbb0358570c01c31ce0ebb4b7540c1302ab6a6d021cd0ae5d5942": "0xfaba4f34d61e2defae2db1f7c712007824c194ad921959efdb4a65dd174a590c0c62756c6c657470726f6f66", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26056c060af5f5b395e8dfd029bcf7f1b8c216c3e8fe71b422c34003bcb536257a3ef17928e93792f8d8de4748b81446a": "0x94b3d04ef219a8970ac5f76658fdee1005b4b7ffee3fc02355f60db1a778f8260c46494e5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf260a1a9e3215ec9f15089823cb1803a7da849df65d3f404d80ceae8a840ec60cdfef83ae70df3a6d681870c87d5a78f31": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf260b1ac8161a811c84a429eff2c631eb50ede8b484ae583e43b011ee69f561cc3d145aa542269304d76b034ec0df99f3f": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf260b68962a2d002fb573f996c7e0d736dfe0dcc8db8a90eed611a4510a8131240174ca310a563a343fdac7fc1060b0b04": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988836", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf261307e87e8bc1566f901b5dbed719573d85148f0fd5fe1eae1bcafc4f9d970f692415245ce7bb7988bbd76b8dffdf02d": "0xfcc5b90bc1891b7d905423f7a00ffb4e8f3d59aa97491b5a1d45b82548639936033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2613dd8bd2041dae29093cb68c280dcde8c600da2883fe70c639e6375b81f45d5225acf4777c4586a3672c2568b9c676c": "0xa49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e104b534d205354414b454d494e455231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf261df5bbd34ecc0ecd2cdf77f33ca1c94c24dc5f34db1ba52471ff7e38158a4dcc3a19b6137b8e6023b72f889cacfe535": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf261f0b29fac740e620484b5e17f2e611612c0e71d133bb870cfcff34b784d933b5ab71a4f90987f854522f076bd23f214": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf261f255051a4c31354a9d2001207b656246d59d9963c62e1d8f82335ec3768bd5aa4cc268abdd209b779d139d99eca26b": "0x78c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a702404676f76", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2621a5cf9ededa4315a266d7bf8f75286468a99f3bf7d3a5ec5cd3932ffbb436ecd78a9c635286d544661acd5f9f8de15": "0x629c17f4f4a24ec53f85a7beb1c70b13379fb8e4f969560704d2c25133ba8d2419416c7a796d6f6c6f676973742d76616c696461746f722d30", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26241081bcbf46fe6d72b580a1e76671a20912c81e6895f7b27bb4be5f6cb4750a326d3deeaba95ccce9a6bf6d1b9fd29": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf262682a6865b2c4c690d6bd023106732e43dde39c254993375b5d7905319e7700ebdbf57acd84e44b3025d869ba7d8e6b": "0xa45d1343d565c182e0e1cd3da2d6c0b1ab5b17a77ca165457d9620db19439a6404303130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2629f18110946927e208f5b411e43b06f6a4aa384952d2245b6c439c833edb350c0ba7e31ca423f081ee6a0d79596c658": "0x5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf262a75c46816254a83804a42ec946520712c0e71d4911dde07af70a1bafe6ae84ef07a43280a736d0c19395a587935412": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033533", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf262d67377e6d52bd6cb6430a85978e4b04a4ad21f7448e3183c18b8314ffecf0b382098635efdd056e0af7c53228ba426": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf262f7a72b64f01a4727f71e5fc6274dc2d618111c1eb2afe48d95bf0501243748e399e23a538bad0db61fe474f4f2b90f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2631c0679800402b1fdd76bab9f679f7ce26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04": "0xe26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04074265726c696e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2637c3843530e14f1b15fe989582f41780ee022b7052ed281ad71f8cf98ddc2efd5b5fa45d741e4861c225a2bcf22731b": "0x5a9e357de87525b67cf9ed1d0f06a15a6363665ca1c9f43ff527c87c0945597c0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26389048d2b55b0c66fca6515bdec995f3ee307326a809fbca23841d62753a3aaa5d3ef29e45a4f810ea1011c178f302d": "0xd6c29a7c39cee45b0e045a94081bc188ef73be2be086d66aefd850fc7eeacc45064261697264", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf263e1a0f7f5269ddf76106255a28ee08012c0e71d5287b03cc78c4c2faefffc4cacd47bf65ba7bd0bc5d4facc08cf9323": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf263e842b733bc16754c05a3c4e27b82717291c36a6b23990b023acb5bddedf227b9688372d4ae99b442b031cadf13f66e": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf263fd21194b7a0ec0fb9dbb1029a23d80f4c68c01b58b381bcb8b1fe58cab96f90271910ec55c23214c68815130b5a81b": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2640054d8fb17c225857ab80a22e4183126842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148": "0x26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b1480458595a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf264c092a725415d558ca5ccb0f490d780f45c6d9ac359665373662814fb3b30355638036ee2aee6807b2f2b228ec1d6e5": "0xd53c9c6e61431448ceef1eb49542ddee942dd3d6c81c19d53efbab8acb02f00f0973656e74696e656c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf264c398d291c5f649be6d6d75b4781aebf206c1276f16bd43aca4fa9d596a7164a310b83bdf34350c1480ed4854cf9729": "0xfaba4f34d61e2defae2db1f7c712007824c194ad921959efdb4a65dd174a590c0a6669726570726f6f66", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf264de414e896f1d1d91e9a01ea473cca0d0ccf4cb7501417f0d7bdb6d577e026612d02579686f0ff1137a10c843f5c963": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073035f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf264f2cd21692bff61795cb794b30944a21cbe59b1e375a52b9131fdb7a85c0992b8c5cdc3f4b4d90e19185972cef58b2a": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a104e4f4d494e4154494f4e2d504f4f4c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2651fedca233a66d0898b07888f9526db8478f51feef5a376deda20303e61c855e0b96451f692ead53d838130bce9cd08": "0x8a320af9e031a3396f15acdcc65c43008124068226505ee7e12bbb0a12012e600c546563686e6963616c2031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2653d347f7ab0616e9312fe3ee15167d1815e86a39ceed754266101e55e352c131c877e72ba6f9652dc45fb3fd3757be4": "0x7cdc1a6a5a7f23437b6528edcdf553d0685f940a4e6e85579727ef3dc574563a04563032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2653d4fb685eca06fcb8b63a86aae6c65aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164": "0xaa2b3e0a8702aebcb83d552838a17902b2403b0f16c4e52a4514fe02df532e3c033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf265423f4616ddca5dd11b3260bf8a0b34e34c880765bf4cdda6ab2045979a9039544bbae925cfba4d6421286296cd9bdc": "0x3c1db08dfc6786bee3b0e1b4aaf51e80b6f2ec9badbe3da87d30ad7605a2bd1604303031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf265bc3fa2aa63b50cd345969f8790d552a42184be9cd7657a019c2624c045f4ef80df884576b0f2e1eece434410537a37": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033638", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf265c6ea578befcfb5b2d2affa63df3b05860a5fb3fb398d56fe3180ba927cc0f0c9308cac7f6af98d4fc7624627343c4a": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090d6e702d6e6f6d696e61746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26691bb6d27adbf3d894c5c905b40c202fab7ede8984030252e6392d2201f91bcd558470d35785c4bf89f6d7cd86c6e66": "0x040298f71f02d7b6a67c0ecee7d7a62ea51dc6daecebf4dd9ad72e0510537a580474776f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf266d79d3fccdc1cb3873b9f7bb80812bbfedd35f51de7e439bf432926351c41500f30fe78941f325c69dbb642f3509547": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf266e7b15209329fb5f45d8d77693f527d9f7951a3a51ead847837ceb367ad2166b0dd1411c860fb01cf7ce94cad08022e": "0xca5bc1915da74aba3aadd7ce7b809045d5eb5b73559259755fdcd85a40a5dc6e194a616d2773205768696d697363616c205472656173757279", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2671946b010703f7d896bcd837d623f0c5e4a7f6fd9a8525d277f96f3e758e51fb673c6c28a7203b1a57f6e90c9f81349": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313431", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2672fdfd5b424654eeaa13d2aea739ac0bc56d28e12b54fcca3e2c3e90cd0d8a991718bd2fcf9a65dcdcd1bdd04be4459": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf267482cc726f02add0a3f6067d99bedf2aee65bf22cdf1f98c91b6c176854d8072f1328e027d2e84d23607b517b1b9429": "0xaee65bf22cdf1f98c91b6c176854d8072f1328e027d2e84d23607b517b1b94290574657374", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf267833ac6e29d30a5cb45c4b75174411ac2e34786dcde41bcaf6c5c3dedd1320c792f0a0bf3c448e03275d7f9cefb7653": "0xde7fc70edbc29190008415c3b6122dc6390b738453c6f1213b59942b2b76e54a0843757272656e74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2679801cf4c337ea779bcd260fcabbcb712c0e71c8bc9217a6448d34afd0c1d226663a864a4141b65d13f8bbc743d1335": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033838", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf267d883de78b7fca5e136b2e623af15e9051e046a4125b20b4a9df6a8d1d5f81f6155279dfaa2050c7970d4470b890e8b": "0x081c465a655cf27eaa73bdf9554abcb46ca2d56fe7fb0a20835c1a5ddec4a32504303233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf267d9e84f6eae02484804da8f9eb7552e483ea32669fca11e7415c4e24e088cb3df49defae82f0f9d069ea0aa75839e38": "0x48745d28d9e9596ca41b7f7bcb03f874757f4f0716a7237e566662a6393bc1250232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2682f326dc001feaa0af173c9de66ed310cad33c225bbc550c7e1b89ff2feb2dcc8993f2e3a8dea40898fa8f54f754b00": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf268435ff8a551e9a6b809aea31b22c1650ac2e966527ec0e3076ac6ae05402fe763d6cae60a8c01e108dfbb6e92d0863e": "0x64e05e73625f3f0991e3062733ad8480c5589a710a24beacbaa555f1c4a7f0640232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2687be05f69f6f8f84f4b954a8981d6ce9c674dc7b750bf4d5d5d0db23578adbd9602cac61f6292fd788879a44c87256a": "0x66f7b3f3db597d3032c2d767568aa550249c946600a61276910b9c1d21a933710f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf268a30cdb6c7b150c4f0fbbfcb62333fe3e4473a8a5c626a2b1eab5002c13537480b487a04ce85ae09292a7c458b3be06": "0xee56126859de69a3539f0e8910ca7e775243f18c6257954a65e020eb229be9120de29d84e29d84e29d84efb88f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf268b65cc0f7d23aee0aeb082d9170bc585058c8963e2b60c6f1e6c921a3893414f370b48ad0c2d2d937c7786febb29003": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf268d8e8420dfda8f984220ccf7a9965693c84672d8f0f25ceea258d980ca234e25ac03cf2d78f925340ce77237844147c": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf269086b8dd50e6fc95ccaaadb185440188224620901db3a08a236f1417e7f865c079b41c0b2e6cb0084109e4be3fb1d0f": "0x707c9246c1c227f1495885cb2f4c59297248ec5abeff2d0f68495075a16bc17a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2694dfeb03523adb4381226d98475f9ac12c0e71cad505181147127f5267ae6187fe470ce00c91bd1d1adfd0227a7333a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033737", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf269c4dd017da84e735cde3739503ed184821bc7f162ddbc6418c08a018d072e2980a4257c8584435e5b6251f6e27cdf19": "0xb08b555a5a3b2725e01ba15eb40aa32dc5b781532854b797808ed45e752b047c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf269f011c50eb507802ebe2baf74a0ea66b6d4569e33bc6763785b94b98ec57d07573650e35e682492dd515e0a064d8958": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927706706f6f6c31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26a078f9501f9c92fd33584a668e8c3a5845c9d99f3070604aeab0b883b0f8774de633c1e7b91a0376df2342122fd4148": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5105434f434f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26a1408806f270ef20161776a9ce654a724102b17c177cf80ebd64796a17ea2c44b68aca3a03fc35be96f6d3ffc60716d": "0x3acdfb6cd734dd3e624b6512e0903724c1c90a516c03c81a9af756491ea8e15e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26a56028c7f51d87f63a6d86e42f64be3d296d443e8532e4977e9d78145f6ec9eadbec4fd2b10158e82985549046fe568": "0x882a9309f1e5f87abb745dc51d5dcc338e3dbe7b818fd8a9768e27d97e57ec130232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26a7ac804917fd14c1c58048ce7e065790efe4d35b7d336d66f5ae2cf6969014428415b9d32d8eb2c17b58829d5054667": "0xbcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f620134576657265737420436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26a91019b51c62d22ad66a4f15dfe72742ab01782078bd1515a3027895439f31237792568ad0eded4af3d31cbf30d9517": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033935", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26aebc27682321ba956951a5c3e2e2d925c05d424a33d6e9ac92c3863c26aec3515226a439192e9fb28dd47db38dff05f": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26b67a834ff44be6104f436a0795450ce12c0e71c651e27773fa58160878f81a68b7b054ccdccad776181f757e763e514": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26b6eafdd82bb367c496ff30495fa001ad6c6649ddfbc12a755845a05072148efc0d82ff7cf4491ba4e63cc97495b3735": "0x80a135db57d4d35273d9a4f661d3dad8f153a1b5bad478f9b0e5223657aabc0b0e574f4c465f5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26b8a79cd1758e7292121bddc2d2aeb5cebb515975618eb35e252200dee0fc30b3db265686c72ca22708ad304084b975a": "0x68f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb96070530322043", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ba4c9db27e4bd17f30e37e935b673842cfde9047614f815e566dec170152a0e9a7b163f94d0a59e8abc4b84dbaa2e63": "0x482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a74512360233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26bb1d27c505d5ccaf1b88cd5511903d81ac5cc7855b95a4ea69568546a9e38214f4b6dc5de6cf1351649afd6b0bc800b": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26bdc0ff56647d1ce1c6a6d0b4b836e3eb43ec7322956d133d41e28758fc64d2da34d2888d93af64eb41f7afa26967961": "0xb43ec7322956d133d41e28758fc64d2da34d2888d93af64eb41f7afa269679610a617274757273206964", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26beffc5029c1f65bbdd549396e486bb52415e5310193e362840035d0283a5911d358c1553afeabd87ea4d66d35351128": "0x3674aa73951219dbd27b3e3fc5847b806c68c1de38fd4f22f9493a461c80e9031541524354494320425245455a4520e29d84efb88f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26c0e8e3c208d8a94bf73eb953a3c6e46688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045": "0x688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26c3dfe8ae17a27ceb9be0a86c9319a75ce304677ff08c2d76d65ad5bc3adacb74b685907cdf72fe0f155c31dc4c8b047": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26c75c149f8b3ad90d61d9519f4d1cb53ce26c4cd5d39e3dec824a79059cf0746e3aaed0821017aa493da14687d5e550b": "0xc009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af66033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ce6b594ad15fd471e6f5eeef2ce735e1ac452bda8e177f52bae23195e506bee27b7007bfbeda4f2010fa6220e029940": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523537", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d1fe1c743f8b472aee824e1f69711dec0d4fa6e65eb6e8de70d275bd49773f00fa1c385a21608fe2f94a13036ce8661": "0xce6e3dc917919ccb44e66c8a5d4c693b96265d5e7072433971fb38d083d0587e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d3f300520dc0d16c9570946cc6b670504961a29fdfab26086e085f26198e4839826299adf5158e0de4d266528642b5a": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d5112b75bf01c0d280bdb0da16c359812c0e71cb50b65d27c7147f5ea52a5a805f8f75301ecb5d9577244659659965b": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d5499cc650d3ff7095b51b827fe7ed1c0dd6bb9243edbd211dac2b9b37fd29003be77cf21455af7c2c680af8812b604": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d6154ebc6adee15904e184473e1bda32e05b8c395e198a2efa9bcdf3ac31424d984bb2b9a1cd6635a6e60c9b6a0097b": "0x845498df40e85e2ba9d9e213d1f476e7b147aab6a9098f1bb250e00251ef8f5c0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d6b9a24b605db49b90dfde2329ae9512cc63957be519774cb72783eef49a4a1dd53905dbf49a4a6f180a957e0563021": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523536", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d6c9cd04ff6a263d7cf4ec4b679b030ce384d806d03a4618c1365850015bacaab7b19a86849f627743dc2b1b6c90573": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31375d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26d6d8a60aac223aed9c676354ddeb9aaf8f71fd7d5dbabcdf5a640f194881f3f16c13e2bc18e54cacd08dd60fba0907c": "0xfef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db61033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26df4ad1e32752726b5d14d23e6c0f2b548a9cf978cdd6826ae8be06a8a4c2b5080eba18ed88f5a01cd4db7b947515d71": "0x482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a74512360234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26df5e87b58fedb8a32ae8c35334b088b5055807b7c54a1143ebefe17d711170a5971227a8a8b593c769fdce803812028": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26e16b58ef6482e68e69ecbdfadb1c2a52cd1a4b07571dd2c61dfa5ffd65b190a203d082e9176e791a25bcf242de28501": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26e268d93af6f8ccbe753d9d7aab0dc5aba823c07ebdc12f850eb5dcc7e39971b34d5fd6643064e0394cc77cc0fea6718": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26e497e650775b5009385bbae39687dba346c4cf9a3d4e2bbeeb47694406ec7bb64e9c25e695f5a9051cb8119ca8e216d": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26e4b64ce649099fcd204d308365b0a013a5dfb7d614cd20d8ddf555c4a23acef0a71bd8723463f36f89e603211dd99b0": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083037f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ebba2aea637e98146839de88adde4c4fd82c8f29cee3c6170e1f21d2d060586e2508f5a3dc977f2f179ed52d33aa923": "0xa80ea94af8a39eb7ba8d9afb913147e67eae84f48aad7b9ce6ee05094fe0394e07476f4f70656e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ebeacaba92514d9ce59b29ac9021c9bfdcd5afc6aaf6c47e499c5c21097386bf5eeda93a13448eb7b9ddc4fcd0e13a4": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ecf2cc935beea7b1c3cfe5594654765d10cd1c9ae335b7b25abad42b89554a8d9c9fdce81a11b856604cdfa6edccffe": "0x30fd1beaa72357f61ba1fe7e90aa8c5080fcd49b2c82e1b8315bcd9a223cbe4109f09f909df09f909d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26ef9e6acacfa82facc618c0deffd2d74547be45207a849ca9ec68e16de6964b581b36449cb04256febdfdad833e7e670": "0x9085297d964ea873a23b63151b4c82189c1314c31fda6f2d71f83133d0877c5c054b534d33", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26f1d383e98d0d081d44c4db9b00e30dd163c64722e9d2ead4a7d5d88e4a3e565737094f0d4bdca0fc90d6870a8d1271e": "0x184d701295be7bb38b2c0c58a35bf8edc592671c53d149d206e037dc7c9beb7b0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fa1bc3177deab3c13c2d8ecd2eb3706e81628fe7cf9e8c5e313f1d418b48778051a756de0f652496423cfb3f1be2836": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fc5b71ea1415c8d7c07961675275143463fb9341e83f58071dffd0feb3915815e4f7055c74f0e4ac002214cf06d6588": "0x0650a2e41ea97b60bbd3f87aa30d605562069075deaaf79559959230928a248700", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fc806dc65089ae91187a1fe690b09db24c295ae61b1b902e08f1b4939f83aefca9d3cf3c6048f1bee7ca71dc5c20a2e": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fcc51b405d6f6f727140cd71d9d06855034c3e43599377576fb1fb81c8410fca61070ddcff4484cae5e57de2d084f6f": "0x503551a752e49ebef1b6988ee561cbbfe0f442a56fe624a58ae80ff3b3b9cd7d0545505632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fe1b129c78493f32f9865094f231f9c8866bf5337468c1c81b265c4d9f352ad6b0e50b7fe77c4a660fa9ce31e45154a": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033839", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf26fed3a5a88d568338cceb3c0f4696f43cd1a5def7ac55b1ccf202ae5de75a02a224d939e1b8d84f54e5d03a714d49896": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2701f3befc036e16f64d48c6c8d26cb7deaa9db4e448cc0b93c4cc1d5059f9bb7e017c51964e21916f2106cf56b702f64": "0x83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f589084d61796f726961", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27051f48905e9a91b8c8c33367d55ed3e3472a370eb332c43576f14f315b219aac6f86795a580d50cf5454b4c293b811f": "0x868cd54faea1a0e45836635b2bf658733436ec69c5567d651be592392cbb69dc0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf270866c46dcd9148458dfb322e71add45e2c726e24b6fd7c2bf7bd253448f03cbe350cd0e36bcd621a82fd2732bf9c206": "0xaa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d0e48797065727370686572652d34", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2708de677db33cc55b0055884cb832c7a12c0e71d122033fe390632d7275542273a8afc911afdba254ba4b7f330879064": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033630", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2709054a2d4d5d54351c6d9732c95a37eeabbb97403ae010a1fcbbc9cf50529f27e0eda03efec95e29b6ed44dcb075648": "0x1aaf37daa4afffeb0d84c47f52330d8293ea648e1bba5fe0e35355057e63c1670d73656c6265725f70726f7879", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf270aa73d429acc44140f13964c7ac109c92a409f971d4db36b2d2d520adc5ea15c5ac9c012d22e4e551552d250aaae57d": "0x54efb33a98824d6330a8f074481df98b5123305473559bef960180791f8492520a426572657a6b612032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf270cdc84d725fc107ff788b254c7cf112016768f8ff56cc85e23810144f87fcaad260080c7547bb6d3c20d0b4929b9d73": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083239f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27115e3fbaa2944d93182c99cf8826bd3ae8c6dd7bf2e52a684bbda1831b6eea8040b7fa459da6a487a9988a9d84f6b0c": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303220f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27123dc060c010cb7b13ee5f37af3faf62c0f99b106126a14a19ed92af1bd9055ca4c39fd9ed5ed2305d18f6730ac5470": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033836", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27163dd1626fbbeb9a80adc352bda4ae55034b9af07130a1799cbdbfc0c2ff2fbafaf47fc4cf70d82dadd9e606f23085f": "0x503551a752e49ebef1b6988ee561cbbfe0f442a56fe624a58ae80ff3b3b9cd7d0545505631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27168afacb6a98d528a357138dfb05c28f2b7e775b59951428fefeac1c8f7f40b24103e02315552065e37d58ea80c7d77": "0x929aa2bfe7b52500b288c943b7c24a90928cd8a6f7ec8eec44763d9f741984011043727970746f2d6275696c64657232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2717475f84a4c9b87440120beaae13c364c70ba4d71065dc3bd0d11c1fff6bfca26d89b5c3f406eef2e5de8ac7334866c": "0x8429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee210d5a4b56616c696461746f7235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2717d75ca6d64dd31be997b22d763da311ae31e3543602bdd7fe69218e5c8d16c782f96969e2f7e323ec5096ffb294e44": "0xdc86d7e1dba377a90f087a942c0c2777851b447a16af68cfac09c2e58ecf7e1d0245", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf271993737254d0baa3517a60a30837c2f148152531de95b53fa605b79b786c7f16397d3226ccc2f0beae85e2d73770937": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf271a9519680428dfc91bfa55e8853a73a70f955feb0ffd847cc972e17e979619e0bc0739673db8604848204bf61af0071": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf271c0517588bb633aede2620df6d0989a20188a2097650af57e7cba4be37d595ec1884b69aafc65961210f295467a5313": "0x02b2b0de562a79b5ad9c666c3f9e7752955f3b2c2b4a17c71125b2668ea9ce5a0a617374726f63797465", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf271f70b1d97b96cb0f9d8831ab8e8ef2775c4d8aeb08fb3e8276a09141d8139b74d6a76af72acf6955617309dea176a7a": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27205da583a65e8897ab5db17daad1ba84ad44dc061d183f5adb794ba6708425fd6a3e1c306152fe63fb22075d1f7347d": "0x225c1cf2356a5a5cd7e13c8e5dbee6c4c89e1c5f610c1050131cc58b4d96e75a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2720c59a42b1a2b4c7d2139dcfb90529fbc79ba52668a29f5a5c62044bf72f6c666f2ea1347cd1d23c3e54d7a5dd0614e": "0x1aaf37daa4afffeb0d84c47f52330d8293ea648e1bba5fe0e35355057e63c1670d73656c6265725f7374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf272384e0b39da7c6140d723845b82629ae293a27231ba1550c3767df641d03102ad153acf8b4bdb7db7f180fa9d544d65": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2724c1e316dcad867c557f64623c896ae904f9054a49d973dc073e09bdb9c9e49213558cf7b5a29d6f2671d8f6999656a": "0x36d7b7a05501f3e93e7eec83c53739147dd9824554e4907136371ca062820e3d0e4d414d415f4b5553414d415f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2724d4850ebab3bd5702fb9c234ab0f86386d313e669622ba62d89b48b2d4e7be50308ca20ec56fdb89ca5844952b3953": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2725a8418b84a405c8889b8c32fd59d2ce28ceca047d61c081d502fb5b66527b2dc7438684d607682e9dc082640667213": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2725dcb5bc31ffd3143e49d886f5a357afe96b7fa8b193f73106d03bd579b5cc090cb75640ec8090d19d96a3c3d5d8c7d": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27287cb64c5712f2c170bb9949647ac356579df1779da496305c30a43dcdd9277e4984df2b941343e1086706c613db393": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083034f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf272dae82d2e62eaf973cf7a3da5592630769e87de4b843adb49b3de1ff29ce837047c48023aaaf9c6d3abc6e66b4ec34a": "0x600e047c97181ac8d0b9d5a6372f6018f556d68b2b4cdb529d87da365f718d4006f09f92b032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf273011b2d1b3498c3c4fc781f8c5d49dabea06b45bcad97ae3126af1a6e864197180af4b7e6513da3032228b2bdb26368": "0xda01077bdc025fd779cc21c9760727ec07e52aa132410b82e5fabacb6f45b0550232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27354a2780866415377a9ca2bf004daea1f8ef3aac7ddc528f500ac380bfec2dbe0c58caba4540adc427fd3e3186bfeea": "0xa215ba2d1b408fd5350b93f2566124331dabc06e94c16d7080d3cd5771d5995804303037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27367a138830fe89180766e60d91a6fb938684912197a8fb0da1f815281bb2f52f170d07b4d96450ac6ac06cb4bd42d6d": "0x28322946bfaec48af9564e56ee4134655dc1748ffc206c3694a9c6bddbe8332f0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2736afac49fff50e3afa239555b5dac3166e499f4ab6510c9b071eb403111b1d51b97195af9cc2aa65db79f3b84f09762": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331323a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf273a75a5cf4923c0b7ab99dc4eb485dbf848acf74babbd40295e54caaaf41e505891996968bee93eedcaa8e5b4105c779": "0x16476866c0074663b7d9046023a2b3fbf447c833f4fccfa3dd7a482235f1ec7f0c454e444541564f55525f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf273e7252fc1f23216876fa58e3aef25ea4194458149444dc0e0ae7addb00b669d89f3979309ef9eb635f148c2b879e878": "0x34a3f0845fecdf74f7aeb569953da8cf8f8217a9a167a4e7d6b3438d8bb6d82817414e554249204449474954414c205354415348202331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf273fe8b74e00be2d5b1eb774c777767bb4415d4ced8c9de7ba415022d5b356f25eeb4d9dcd522732b2c87520e29e66044": "0xaeffde5a4dc7117e4cdde2d3fb3d2afc7b2f710d5d66c55c5d1d7c5873598706033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27454aaa2b1424e886ce757cde7dcb36ef295175d63624a3f6e510b8c189db808a049704c4b99f49c2638e9d963d1a3ca": "0x105c06afbe01ff98801bf3e46b96d61d0d7aeadf7af7d6c39a20dbf946b0fe4104303234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2745f3ed7b0f17c656c3bae95e64ef524e64a8c8a0cd5301afb20483923ad8427c597ba471a6fa868947270768bdd2713": "0x1c82102e4554587f23cbd4bfdb0f43c9d2879d18feb6102bbed977930f695f220233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2747c62d525d486a49a8f716dc64ddcd512c0e71c62cf1da0300cb62510765cc22eb8eaf487bd2abe160f4c231e28a340": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27491b968ea371852883ad125704b0ba48e81ad73b19ae9a28e6e7020f70d862a8e379ce88dc1546a2a8724a7c4b5601e": "0xb8a038b439b411fb7c6cc2d7315292a3d1649601641cbbe0825ab7fa90ce30020231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf274ef942dc8366e68b9e82fb8def4a0ceeccb809fabe7f585098c7e61345f71c2e651c9fb61f16ea74a5ed6279a644d74": "0xdcb38c186bf97625f108b4832981d966ebed50d939349d4437a6f538d40d56760c56616c696461746f722032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf275051bd70eaf7d2946e25174a25beafc1ea9ff7a769863d12182a9439c3666f3fbbaedec8b5427d3c3e93633cebb4ae0": "0x2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57066b736d3033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2750913f60cd84d201ee1959670fdf4bccc2797a71c48e7e7f6defcf2dfe8c379a521c8500c9bbfbc13c8513cd5cdfa3b": "0xaa18b3cf52cb27fd19d5b80fe7982ff955e0d5124dae26ac360056f401dad84607416368696d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27529ee72bd431508bde3a88f3aadf4282c35a5568d679cc0a70e5b714a16a87450270f8ed184d35e961629aa7c364f72": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2754b24bc7acd0d7883e296a775c5b9002c85e23060a9c8b4598f2927a796f8062aa3843dab76f9eadd8b2f36179c263e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033630", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2756ebea7da8902d2c48177e3dad442771644a3ce3456b8954eeca77a5b67d7e9d26eba9f922b82daff95057f543ed03f": "0x447326399643ec639a0bfde97d8b37f8dd0ca9fcb3c74a1ce017f0476f3e2770035631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2757504984d0dbf6cdc735ad4736bff8b1560de907974c342ad34bd99ba8b530cbf89b39a10be019f9abfed3649470718": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a0b4d454c4f44592043544c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf275935d7c517e7fcced318f2d4a6e422e92f63201ab158aa8283fe585a2bf19ceefb00c45eb7b9eb6063b2ee66a108532": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2759f06bc58e1ae9850fc3babcd69da0278c0205b88370e3af02a0d22ff0411cb0335a823f02f604c692a9bb1914f2262": "0xcecae006fbf10a81337d87455340ce6112b125a971482490e02d75a27bb2c33c074561726e5832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf275a6fd6a3d6602dc9139a95d8168f765dc19a1fb8d9519f281e155457a5ae5e30ee6cbe81b70db34a18c3bd72c67244b": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf275d6a7d09d797ad493c7ca42a7857db7461021bfbc5b35676c92f37d8cc0205b39ca70fe448ddf0fdcf203e2b4ac4d07": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523434", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf276051d7964744016a036afc75a97fcd2384e257ac2372c996a4180f6d9a9a0e16631cc76929c600468583e8d798c1760": "0xa43b2797bd4dd454d7fb0870a2a4edd62b39eea0801f6baaf09b05c8634b5a250232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf276221853e4c1fd94a1341840328ad4fc12c7ad0576988c680601696eba2ec9b035e6f99fc5579637089d06a24d3ff650": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27638143342a9b45d19e9cdd58319a994282272e3e8b07aa02117d8a80fee926dde3a9417a2809b971623dcad89445a3f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2764e423366369b346b5e82456f9d99d1b8296804203c1734a4dd445fde8f702f106965c6a6b33e44896af15ad093c069": "0x82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e745034956", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2769ae8816d1222b582a1348663326c6ef201e84471e485a37aa3988c97ad57db1297d862ed5405d864708654e430260e": "0x5a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb99341050415241434841494e2d52454e4557", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf276d8da789c2d622987b4e50b56a1e55312c0e71d3ed7229dfea16555ba040cce63fba1fa33cd5296c4393fa61114a86d": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033537", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2770d044f20ae77f080ccbe3e419c5ca706b7a79b3d933c72bb9ae21b97fcb67d5dc1811af6d5d9c412545e6ce7eb9a03": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313439", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2770fdb80ff3c5bcd4c5167cd26bd98751bded8b683a29a0938bbef126bd9510acfc57f2332a8009a305e94190da89569": "0x0c841e6aea307d8704d5b7b7b71afad58548ce47dce090e25d01b84925e5c48d0b43686565736563616b65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf277c381130cdc1fe938d65794a88bc78e541a4100aab4ff5eed5dbb5245c488365a4ebe149b8c3d5462a8e7609dff226e": "0xe0d744a6f291a2dc1e6d744d5ae0747e314b046739be170638ecc185ff4a9b5f04494250", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf277ed5108a91ff85f2261e35bbd060cee6ecbc9b76728dae4396541cd517384e9898d5bec4875bdd1971c97041fa28111": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf278090b2e15597b078bd62990fa1fa65862d4ad80a2a5cef99de5288c0f299cb7fa7a3e41fb2db1a4c23fa44892be1360": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083231f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2780bcbbc406269d4486f3e91d23769d672795595ce1298481aeca61391ee534ab7955411342e091fcb079401a784d438": "0xeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b2347763648033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2784b955388235e67e3cea884004e14e01ca9c1ffaaa251b220fbca62f28d6936272e11d052c4e995ace722bb6c2e8d26": "0xa8b5707defe6889dc178861ea7b68861fd0ab5427b54119950e6788afe1cad2f07594152494b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2786fae82b1deffc5248f74a97f59a999109507526c7136932a5129122ab622dd17ca59db69ebb7ab94ede6f7992fe854": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818076c6b736d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2787acc23b92595203a1f562dafb922c42d3568072e73e8e73a9a8cab58e10779bcca9cc9d3da70ee41af6b5682fa1170": "0xd8004911e882a05affdcf81aea45f611077f07a29dacf6b754bb69ab118ae06704303335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf278be0cd4c442d1e710bad9e7d0695b0a055acee05be3352c7d09340c8c6f76c87170f1072bc0ce873e529381c4f5c8a2": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083236f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf278c49887fde38ee6df46e120c93d927c2ec9fc5a5358c74ffff03b8712e8dd1e50e93ca0babd01dff5de303a64f07f3a": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2791c146ebaf5b389673b0eb9e407ca3f6e5b9e2cbd37299c34a07fe45c6f143aa715e1bfccc4db8c82814dd82a0aa35c": "0xeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b2347763648114f70656e476f762044656c6567617465", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2795efb02ecdcb5cae7e9002b6f14e18b8056875c26b0b99303e102f56af5b7cd6494578bfaf7eebc0f251a93a98c0710": "0x90174218ad9d5531fc97c3b347e073d347d157cc40a470ad89b75604b0d9dc3316544f4d41535a2050414e5441205248454920424953", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf279c598d130209ab0dea15637a5b16be71a7938fede32e1275281b3eee5708706d88444a6dc898a4dec463f1eb298463f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27a126218545699437daa58d9f25c746812c0e71c9f53cee8937a8a3a30c639efe4e9e61faa222953bfff2cc0a782956c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27a35572e7224154ac488096cf4fe0ab4c21bde30a8d12e4e5d4dd612ff510d84e23afe81bdb222e1037a7c7fafd8962b": "0x4e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006054b563033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27a4588360f2c57b5fa61037c04a5855ca4242b97bcc4600c1de9c6f1a6ddb74b69d9521127a377d2717f6d9fed5ddf4e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27a9c318a8efd0e10f68cdb5cf293f637f4c6e1ea78fa82de3a28d27e20c93b4b8109fd93489d864a73fe7bd4eadf2061": "0x50ef3cbba6eefa5127e662a1286c69c3f8cd10aa328d394df9e69919af449b450231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27ad4a6fbf90015403b4eca241d6ec123d8c5a6bb60ac4bf7517a02c2612d122e389ef4684a34b5f7be058113e9e74c75": "0x98672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b63160c4d41474943205441422d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27ad71cdca583260a16b707fccc1b613812c0e71cdc8163ee018634a900a6e973a87e8740b6c9c4400ca1fae2ac8f4e04": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033730", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27adc950ceb58a74605150858156784c4f69837f9346b574bee364518dfa08ec7723533632fbabbab594623d83157a67b": "0xface99d3401cb9b45ee1bc0ec52f4cb35914dc5ad27806230534230eedb8413d0546756e32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27b7491e2d554325cf8c4c05378618e11d6ba1aefd3bd5f72b993e0b6c5f9ab818e96e654e2500b1a547f5104896aa660": "0x2843d91b23b106e3020b7a903da075113d1aaca1db7ac30e119d6250fb6f5961075b315de28fa9", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27be6559229bff0883cfccecdd480b917822adab3c579b87a5731f551e8f311cefbffbf514b27b94a6af35fc23562c945": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27c0aa307ca274a979d8506afc7cab4d55c05d5f192c927b30b33c85470b53474f2a736a01c3c5da905384329a430f22e": "0x5c05d5f192c927b30b33c85470b53474f2a736a01c3c5da905384329a430f22e074a6577427265", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27c41a20a0334a703bfaa50967247e53003a56ca86460efa365897ff7affd5f6d280ab3a0d857b37709ce67f551d1f88f": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a154b5553414d412d414e4e4f554e43454d454e5453", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27c7140bfb738fc55d4104789cb6dd1f00d32b36853f65bf42ac0bdd182edd4601c8503e927fcbbd1f34f1f74048cee6a": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f063257696e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27c7591c39b0c5a92489bdf587bba9f6db466b09ad7c824d88e8548f5587ba158415f7514a0d0dd7c18144f6503507f47": "0x12d9c0035dd422388e6d346f61df3d9f3667f8ab761c8c57120dd61917976e10032d41", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27ce410244078329893d4dbdb2ea4a0517cecf08ce1f6f9fbe70156ec68ff04ab4ad0dffd5f39fe72c955b7f319d7740c": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216064c75636b79", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27d96139d68d6f7956c00115557f1fd35402d50604742f5071645e00cf27f318d0a0fa805bda1daeec21e11ff9387e923": "0xd453b6e497b6a89979fb34eea715720d37c2381c8c51458be04296fd059dcc3a033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27df1fb605d3871d347ec19e8fe964f32148e8ac56079d875671a8e379e8ce3726be04f32f36a3f8237c2713dd354be1b": "0x9a92ad7c6dcc51fec9f6d98f8316406ca42bd04dbb029d3ce454330a20fac0770230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e093143bfa10910f74f3252829f6e8ab4b4df0af75ca82e3289a23c6c32eea3d2ad337ce4d335029798b3735c8d6367": "0x0a439f839504ef07c5cf8daf62beb17546e808ed1026c8a683be8207245f300f0b5374616b696e672d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e0fe6cb9da98d799af4449535ba0076f87bd083c89d247ea03cac2fb12a410b3f44f87c1b523b0bd0aa3375d4dbf193": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e3adb9aa8682e24ce823aa226cb8123b47150da85f064599455634eee628e2f775d06bad83bb3631130854914e96d01": "0x5ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43035633", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e3d25abb9b49e97f19f73e27d4537613789e73dd3cb036f57dda3ed96e000aa87721b8e19205610d2625e3847f1a06b": "0x2aa53f55efa82a9820f3c2569d4e52dc467475a1a11cfc9861ce5440316edb7a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e65087dd946c27bb1e415ac33130b0fa65bbeb4425c55a611da4116e848b0cc39686a11f88dee6aacceac6bc5eca657": "0xda9f7fd3d9612a68d2ead69dde53297b172b7db514d0d261e7c5be987df7f32a0b56616c696461746f7232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e67883c4dafba8127e1226fc8e17468de4a3a5ffb49ce7652bd6a9f98cb78bc68c2360c6e55fcbd6d6d5aa6b0f2347e": "0x86b7409a11700afb027924cb40fa43889d98709ea35319d48fea85dd35004e640a4d6f6f6e7269766572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e6db057075a669d13d6945b30d080b0ca4acfb773d3f44cb7ddeef0caf203eb82d3366bef8d775a0533ef152431b633": "0x3870abfd18505f673c1808b61dd0d7067a810a9719c2ddee18f9b879752f4c500b53746173526f76657232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e8190ad4d57e14b3155b7177b481444b8774ed1e7c90fd0dbe40fe7c6a8d810484ec59624b59374a38a8bbf9d91ee1b": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033731", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e910be4fc1f76c8e2dab1e55ea0497870d7ff9f5cd0e46762d7d7d1c8dc840a4026755fe13c51237ff8601377d4fba3": "0xe8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e0c314b5620f09f8c8defb88f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27e9c08143156e82cf22a2ac64d702035d376b1daf289d513fd22426812d5a7c48a58dd121e4c043627e00fd216557873": "0xd3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a23408436861726c6965", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27eb0fb5da726390701ee9c4cf250c0f162ef7ddde3d6fa33e5b617265ea9af26a64e1248c80b7ac1cf2df7b171889b6e": "0xbe4bc35b26cdc006c69c1f827d4bfa75e4bfd4ac0094ceaeec8ac70469cac51f065374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27eb5e19af9fd94f13790c96dd5753144ca5164772b835ac12c7e86d391ec217e65f05be0f43b75a059fdb0b3e8a1c44c": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47711416c7068612043656e74617572692042", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27efd2aa9904d84c78e70a8cdd10accb1a46e73069e5a05c232b0487e1523e7a426270e43445d0dbc1744222fd4f6881c": "0x60c6e940d5c74596755e6bb1b31ec98958db10d841dfaf66954b5542c95c462b0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27f04a065bd619df1e2c308279dc9e8525b7812d3e31417cabe45153f522a4047b09e9662795cc7c7372cfb02f6dc3919": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b356804554b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27f1b8c1c56d4f27630206a19c89ac452809246069a0bc7cee32210e5e5c1a523e10db11d0d86abd29a3979e68dc01725": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5105444f444f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27f2b05bc2867bdc02f22b17c1ef504f412c0e71d4b14d52ccb248e416cad1ddfc7283a09f2625c601528d29f9a294b4f": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27f35b91401ce6524d9a9c7fb9ed03b7e9c322a9e20637c9a71e4d131e647d597b1c600dbec94bfa192465e3991a15b63": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27fa714c6ba99619fe4c576dd89b53a722c61317ffa5f84e38eaaa44e333ca7be9924b445ee9e6e275421200ecc58a9b0": "0x0ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e0c56616c696461746f722d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27fb6191430b9e8731f77bb822cbcb63631918cb9b9c9414a2cd4dd7f720cb98fe98cf852636fc4860845767989127e7d": "0xc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d609436c617573697573", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf27fb74f09333c1c1f27317b348c589ac9e66afee7026bccb1c5ccda9ff095c278ca0c40c7d44f645a9e60d2c1cf49a305": "0x0e993f475e1085cfe2d313b1089c3fbc33c78c178ed19bfc94be3d7937709371033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf280129ca7dc0d15001bcc0788918ce3522e4e174e782224c6e32c71c85d399497af3cd209216738baf31130ed860a5877": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073033f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2802d367e89bc722851768bfc9c0b56e54ab3e893de103d05f3e6e5f210faf6fb40fddb03be173eb3723cb33a074faf34": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2802d8d6177c25397d6b472b80ee0fd824680cdf69422609ddbb2cd596ee4366b84a50a3f17c0a88b9fcab7263852cf6d": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66095452454153555259", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28045e484681e088d0d62e4869fc4bc8a45276fb671d5e24c15c73f6766680b83e94bd709644fec1d5829f1126ef1fc2a": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090b33207c204b6172757261", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf280c3b7f80f0fe6e3c42e1c83a3f87ad94ec19498a19021a78fbf00ef07d366245bad3cc89f5837a7004b97a50c4a5e0c": "0x128e3b8a2d3b98071ba399c17206f84350e65653537dbbd646cb5908efff9d49095374616b652d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28103ec254905fc4b190f466efa2a392ea2fa6c11ee56da6d5e51439a0d0ee776c8b4f0f6a914cf6bd9ed8af27db80252": "0xfe6c31fcff28694469c3d4c1681270bdacf6edf7ec39bda6c68cf25738268b79033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf281126b31c52b0e9c700b2d2c99137dfdd6e2246ffbf94311de0e749da628bfe1b40ec0251caa056fc6c2050b09074a3d": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e51054a4f4a4f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28118461768bfed729087b69e9d3a933188d38e0b14f3b08bed993ea4fe1b8ab124190191340fe8de0466ea642fd56511": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2816611c9bceda771f96e2dbd296f1f5fb0bf0c9e4095ac5ab829224395315bc4e298b21b180d6e9a86e698f974d2fa25": "0x8e76c9299f5a2046beaa5266ac0ef8b7b310c929704f15d8e6657b371302202d04303332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf281665f2c6a2d1f21c042ae5f12abb684e852fc4a048379bc123ee21bdeb4c6a4d94ee131b0920ad219d6cc280b0a0965": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf281c1d78d5b5076693f2571911f26503212c0e71cee9f575993304f4b1b5dd21ab495dbad0b4613f39c8c4f49ef241406": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf281c389c2b60c4655dd7ef61ec53a85f9aef5713b3583a5730c08c16d252f9fbda97536c8a26168256b998f7e9fc1c602": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5108504f4f4c2d3133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28209abec313cd5f943ac7567422cde1613ea937fa9da7a04ab5ae026b321323ffbc3f6ffd24898500ef3eaa6b2353613": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a0a4d455a5a414e494e45", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2822c9bc287e6aebbdc3e6070407a7ba1c0f326fa9866f007e8ea4125d5364b3d7061ebbbd9a24341c40a3ad8de3d113c": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5105544f544f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28239334393b581161cec98eb71582d7ac0e9ec31daccb76e9baaa030b5780a85787b3f1e2ef54fa8f4b857c64552a4e0": "0x4ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f05f09f8ca0", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf282c93184ede0ab8f89b93d497d0e4c4c12c0e71d1e59aa52904247d6ede8d053ec5c65dfb3dc8c1e632acf34c030a255": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf282db2fcb58fad99c289f7a86656931e12eab66a1c3116f15f55dd2996db419e367106043a4c5491a5eeab1d33a17460b": "0x02bf32e061073c44300056b416cd66a4fde1e6c120dbc0089bb65134f5693a3b14636f7265626c6f636b732d6d756c7469736967", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf283189914382e0e073a81098c8a4ceb1ace4f4b5eb5e648247f1796de1f52ccb6d6e763684ab786e21239f26af6d8d252": "0x9cb0d4ddd32f9332dac7059de238b8e489afb55502d1756d7f50b78b58e20c700233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2834e3c780f4d8c7f3fd1c165f191c43040d9bfa0963116a9e97d84f9888882bdcb6faa12332997b7f5b83c7c75532216": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c49277067465636832", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2835fb70434ad8c544e7161ee304031d7026d79399d627961c528d648413b2aa54595245d97158a8b90900287dee28216": "0xa02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d550c53797374656d436861696e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2838555451ee7fa38eb18cd328263423ff67e4658ee318d7985399480025fa332958346cd623a025948cae8a7db36a81a": "0xec8c97edfab0a07c37625d53be2075b8ea64a00ca71d80cffe94edb44d215e000e6e6f6b6f676972697372762d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28388939cf4687fd61cb25dde536b3f654aaa077ac4202f4f7e1135489106099452441129dc5aad89cd5dd4335918fa3d": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf283afa21b810c73cbc3a8c068a6fefcd912c0e71c9d62c402a345adadf6d07c72b92a9df6035128105150414c0f759a23": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033731", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf283e226ba71020eb0449b4752d08be9c9ae3aba9a0f0d03d9fab3ad97a367fe66aba07ac0f7fc58d8dc18eed82f8c62f0": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f33", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf283efe88997adcc154bb4c4b7506e2b55463b64f13f694e789b1c89d219210b4aaef27fcaf8621ce8103f88e3951d054e": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033536", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2840512958b7adc1d1931d8b4abc0d5f54caba24b45e5bb6eda6ae45de9e1fd6aa64fb43bd9086694c4935d21872a5502": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28418b12c5d61f6e70ec0578815a44633a8c96b926e3a1baf17e8f1cab2e0df7229b36c661e9d29f4c005b2dfb0835218": "0x6a1e7cf7558378809fa376f7eec7b065d30759f8a4e7b721ec2ae74b313f08550232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28424750cd8689f881673991db45b14823cf08a632438014746be9061a9a74ccd8d79204032cf03d8fc605d452647c133": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef48430574697073", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2842add3765cf6536011a29b408969bec8e602e63afb364ac583747b0a8bab092d5b20ee98f0495ce7562a8c992ac9f17": "0xe4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f721070617468726f636b6e6574776f726b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2842cb762bc9e90f859325df5f7a1b7f5dcadf01d571672f755b4032af1cfa3784d389da711ea341209b86f840784937a": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf284dd8e83e4115e0710c4a6f92f8ef075f2e0c893582b2b34b415274bf95b65f52ab82079a097a9ed28349eb9a7bae745": "0x38a48b1b98077c557c474ad091c854286fdf929b0e710299b16daae9e0ae4a77064d61676963", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf284e13b8771645bb9c5f38e0d81e31dd8c0d0a4ad7841c483d4cb7813af9550c9d7c1b182613bf27a900e5211d9b64d68": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28505622504ca5ec69b4ee65beb5a1d47bcc2112d8a9de4645c4ff651aa6efa2f301c9d6a2355f1bf0e6a80826f50016e": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988833", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2855c311b5e502d7a7a2071f1b2e5875ce26714e05311dfb5e182d27b7f0e2c399c96ccdd81c25cf47e9c61315274631f": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2856044625ae62eaa06af331bef9b4bf3e848eff972706bdacaf38bc657028f303d44bacde7b359b8595fe7a4268e7418": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a0b47414c4154412043544c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28572931292aec8386fd2265b8a2ff8b68aa121a03ca81740284a3d24ea4bf49f22578caa58441527a76e8464a319a015": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2857bc767f3c97fff988fd0f41b34e326b8d56768e91cbccbdf754d7f60db1fedd96eae27b591e65d2fc8afb99b27c20b": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2863d51a50e2a040df6b12294462b8073067a2e439cc384440cf187331543175270b479ba695e2c4d6ba9528bbb6be460": "0x5a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb99340e50415241434841494e2d464545", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2864c5bec13d1ff0385cf6d3d8593552798672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b6316": "0x98672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b63160a4d4147494320544142", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf286a26c691af61a1cf897f552bd881ae68011fa4c76d86408e873beeae9385075b1f735e05b59dca7fee6147c14952770": "0xbc63ced3f8fec642128f2aa9c37e989a9313a67e9635dd85e8bd689ae8d0ce1d0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf286d609f103e7771c593f381b2d26a7fe03460b53d4200f03a8183f00d5ed6c971942ddae9065693b4702f0f782e5c553": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083134f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf286dfd59b7c01c1691d8f25c46f1e638672b86a19da9f10eab2fffdb74143afea62356c6896c265dd18207867f2575110": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf286fc3cf7a3b78ef39d1b9799193dafecf063c0ba3d0dfdd209dc5b98dee86531ad264283fce758952e49f8e6b7f85c7c": "0x54ec6a7bfcee3ac00ab63b98e084f1a1c4d0e82ff63c31387aee91c9a721a81e124e656a6c6570c5a1c3ad2073c3a17a6b61", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2876b89c310e3d0ec6ad7349ca30194ebdeaefd68c861d01a4472a1c518bdacd7f99b6c4a0b64ba32d74995a21405797a": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2879951c2d47788d64c265a580690d0e4c0c86652faff45a0e4a86f5749bf813d9d40aac848b8c672123d7ee2503a6d53": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf287a93ca2110fca6305fdd39cf046eba06c6ed8531e6c0b882af0a42f2f23ef0a102b5d49cb5f5a24ede72d53ffce8317": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf287c93e4e09c3118cc211d3fbf53f8c1a305b166542492b1615c15fb92c573ee387b90427312d08338b9c211b85a27a20": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28810385af8152cbd391955134fba2fec81a73b784a15727dfd555a15f61575f5f1b8323b8fd41416dc9eeb4df87acd23": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2881932dcd906c93391a3670833a85edae8e0a4bce889b5d71d9c9dbcd6687dfda6458cf22bca0a342f5db49d8258ca6a": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a077061796f7574", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2882e5f9d02a3ef933907e7b8449417cb12c0e71d4ebd6afa6a6462c87da8f8da65e320b207a3958a76e854432b5cdd02": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28869befdaf019f3f68978f837aa0a6b95ad7885e61fefa8373066bbb08ffe85c08ecd11bafb3a9f85af75a4eabffaeae": "0xaa7880fe9ca2bbf331fc13e40525dcb0da661f143df506fed76d8ada3db8f55104303031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288a6f5506c390ba1d001f320e2245f4328e219b7c6307a185ea3d7d203fcbf5b78176fc0601cd62b1a3ab95e81e06116": "0xbe4b9973a7f6a5586a38fa295ec8e64d4026aa878c840630a7ccfa7f3914d1620d474f424c494e53414d412d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288b83d271455307fdb42a6decf23918a920799b25e259ab600be83eedfa7807ac27a842f005dea4a2bd49799840f4b3a": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288babea6cf0a5b1540770a29aef8469f6cd55c3ecbc354fceb81b0ac3ae860ef4a3794e1aa9e31477de7c2cd36ccf11d": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288bacc16a6990c6752a600138df36bbfa620a613e0049a85c71fab0328f7449b0a9963195eab763760e1ff50a10d4404": "0xce072084c159fb3547381b718ac1660d14030e7bcbe9db68eef0f7c0e340f33b04303035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288c132aed752df1ffc83e682e8cb9c0ed228fd275f3f92e8b6ccc56a9437582dc59db70153ab33cdd77562661adda60f": "0xf4914e62f037cdb798c40ea01fd56e555b77635e0e9b7175b98bc9514021756c0f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf288dfcf7145a2d07dbc6dc199850afacee00e404cb030e7bfb50b9615ea9a2f8f75601ac9f6128d1263a7fb5d22de741b": "0xfef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db61033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2894d6ff01ce98efb73b650a4b774379fd8900a50ea497ab51afd5227503f91b03a91584b72146c2e485d149cf67f543f": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2895a7e0c21e153c5b1e9c8ab30676264196375cde4e10495687128f72d513b94bc323bbe7dc36f305133ad7cea4c6da8": "0x32068fb3b800c5df40df16619761b3418e40d9455784b6a293d2425e35ef2c270b434f4e54524f4c4c4552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf289a5c85a2b62855cb64f81d7b447d8c3449e6184747b236ba5577c3560b7739e35718c65039b8997b7e723722512b310": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf289f0c7284252c2b2bd6111539764c636ca0ed2d57f858e89592c76cad4ac00258041aaccb971171ea43b6fc39a4c4c1a": "0x9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d277551253686173746120436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28a02d541d624e3f86986ab3c97423cd412c0e71c89b2c75caab9eb9b3ee5a918dc734c5c595ee569e64ed37a306de974": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033837", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28a2068796da680669082c83b0d8ddc6aaa580379e5714c790f17e4af93773d158e30eb08f5a4d24abe4f535776b5721e": "0x4edf81ba4fbeb6ea13cd45ba93cc1d689a6e2e5c6dfc35a458a971823a3242180231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28a2569fac8ce42fae78d6bd23582abeb927f1c23cdd2161cb6bf0da7abb4dd94ce6a98ff07e9fbdedfe96acd3d7dbf5a": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28a4dff2cbc5c84c220d46b8114c4fcdba27a87e5999ee8830465b09da09f16adfaa168d3aec122953b44796a9db5157d": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28a92e7bb0410302274121a546ca7bfe212c0e71c9fdf776b26f8b4def79ecfeb98cf14bba80546f54124e4725da6036f": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033739", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28ac86cf8a962a3e880c844ddcf10c77a611f3cd11a51748d355ff0686f5c5bbc2a7b0e91b6efa0fb4f9aae77c53942c8": "0xc43aabf384c6baf54ef9712a96be7c46533b538c05d4e6c687fe09b109664b28032d4d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28af49ed4bd7a685e31f6b770f74980cc305b166a309fbb4a05d24e70b726218dbb1b5d3e8d4e1488524481032e0acb00": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28b40ffa4ca5650f8c82e80d8155f686124edcf58959173bb907319517828c0e5949a178917099537bfa4895695e5d00f": "0x98989f74514aeaf57d4f41069770242a83d619c9ae5d46cc05b85136edd537760231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28bf47da292b8ad6c3110455ee972d87afeddac420e696be2b3c613261dd7d84a25b6410eca645efd87d9f4030c7bbc9f": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28bf7bf3e9db575299831af37682643db6ec238210f082cca5552aa2ce9a0d1c4be9c7bf44c04f4524ded21f8cbcc611d": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28c09f47aed688f8039f80ce6956097da3525a2d8318f0a082d428d90eeeccba905e0001fdad3a04d6abe49dd79e15186": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28c1dfcfe0f7184d52ec4bee559507653b2f0176465f8cf99c213696538dac784ba8c59e4f577c6fa88555bb5f28ecd35": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b7570748656c69756d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28c5e4b05bb62da0cbac68ac69e5ea5acfc0b298393d72240ea0a06586ea1227e8c84f786c7fa05879e1ff28422017370": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033932", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28cad469349d96aebe667315ea8c7f907daf0804d1bf147f716661acb2ce7c796d0d655e2781c22cd138c4e6d6edb9b0c": "0x9642d0db9f3b301b44df74b63b0b930011e3f52154c5ca24b4dc67b3c7322f150573756232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28cb23603f98695797808da60a37bd11f97a78ac6bd50295c46bc350d252714c70dffccdaa6c1740dce1da940acbec1d1": "0xd2cfdfb80cb90a4a5826c98846a367489fd25d3a2561838fa372f39f3f7fb138033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28cddf503217fbb2c01228e3df0cde1322efecb509bcbfa0ebbe40f7bbc6a74d4a90cfd7e982ce06c2f11fdcc70efeb5a": "0x7c7d2fe83c4af79c49136f0f8c5f1a00cd8d0aa91c94fe74d0145cb96d688f66032332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28ce13b0ca6e2330d9c6c2ea7d714324cb4f54529b00e5295e6efaacfad2de17a22cfe1466f2ef142caf1328b5a701005": "0xaa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d0e48797065727370686572652d33", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d07f92145d67784590a148189a6ee5d9654bbc25d7891d49151110003c37da87fce6eb551768c02e47eae754b61b466": "0xc50f089e43c19f3f4ce606cd994bbecc50bf8dc53e970c0c1c592304f651966f033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d219622e65973214a92fb842af92ffd4a18d3235c574d9f25aa3371f0190be83bdc423f5b77fc310390e753b229a952": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d3a18f5fc9112db250af9b04d92a7bf402b7e0857f31fc28e9c6a0f0970cc810b66ad393edbe120b4d97f5ce99261c9": "0x88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d67a84b4069a6f636ed06dd005329f1120460743583c4ebc3076d422b73bef41b48b87e6c07aeecb07df3cf95565eec": "0x128e3b8a2d3b98071ba399c17206f84350e65653537dbbd646cb5908efff9d49095374616b652d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d7e3c6390768290af1abc5436b80b2c97d5a706146081fdd5ce77ad4ee232f351c4bbbce94596c12d300efae588ce9e": "0x142eba87db082b693b5f35e88d7a70409b0ddb61d430abf218884d4467af102404303331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28d8c1c92a879346f1453f6ee18eec0a51af4af68069a4772fc4e73cba9d1479943982c64e124ec73bb1cbc70f66bcf3f": "0x00f53cf59ee4bae1fc47b5df521d48a3cc2d02d5c15fd5d3bfa3d6a4a2e6a57611f09f8c8a4164726961746963f09f8c8a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28dbbdd354383e9438731c56ffca55a16ce10c51e89ab2907983cc8b846d9d1afa2f9700db18e176c7fcfe709d0406339": "0x86b7409a11700afb027924cb40fa43889d98709ea35319d48fea85dd35004e640a53746174656d696e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28e26c50c3f1787beebe557f64b5fa734289fad9cb619fa9f9b77fd385d003476fdacaaac6ba7191bf5486aa09e1d8329": "0x707c9246c1c227f1495885cb2f4c59297248ec5abeff2d0f68495075a16bc17a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28e94df84b52d02aa15ea48e0b82af07954ec418763624a46b49693114ba91a0137b37c1e47cc3fdcb2db75c9c4b11c79": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28ec2e6f95318a0783a464b6de2c96a7a5ac7f6af5aeb5364188840d02f0e74e813e6d9cc0398d6994b66727658a4fb30": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28ec9397fb62b151d82d56c66fb216bbcc20f540f6c1dc4dba60d21936788a5bc5628f26333e27b14cd091145d92d8f25": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28f312e4f679915416400fdf70a92471ffa98b8b13a1b03a3f86748ad19edb237b86ce74b4c4dcc08492907df447f7026": "0xfae63fdb20e3ec7589586b14ea019731b5089e2d1b22a7911e48603a5939780c0af09faab432f09faab4", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28f3a49f3d43586e2ce50911aea0140960002dd621e14bf09425ab305ae1139310c1c0f78f2d3632c7ea507feb7f82900": "0xcc9f261e20561ee1a137a7c03770706d09a6f85e36e7a313f04d92faefbd3d43036b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28f7d791d3aacd3d0caa46c42e0da75e3463e61911efe5b07ac64fbdd0b388a7b9569d067a6a34f01ce88bbfd9357f29f": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf28fb4051b925d1271466358365212b6bd564491c88a293f54f2fe2cc09b0ec63f226bc77ebf6df8f998fbc7551d0fa10a": "0x4ec0381e4427ed6567f7a5c328288ced36c33becea6ececd8145001f4230ac1b0d59542d5374616b696e672d31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29025a41e3f449cd46ef58c63f3e1b6f936ed432555d82a6fe15f2517dc871f1d02c72d8d5aa1bce703288d180ff1fdf6": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29043b6de8dafbecb9dfde02a5b7f5431b65d8d7707042e22fbf2213c687b330cafa3a792598536cb5fef7aef40cdf07c": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033933", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29065839bd178183fbfb7fd12220824f968ae914b1cddf602f7e775099eb62db646dcdabf6c32fc0bb1b951e94130503d": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331363a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2906e1529cc4bb4c08bcd87af5938145d5aa67923621f3a3395c3e2a58aeb89756e2dc11ba9ef1ac8bd4953cf2a220134": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073130f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2908b71a779b8f1d7862ce857e0e002cf2494641f85af0c7f9d2e3c942fd250dd7c2ecc7e5dcc401fb3ebca0573edc571": "0xa49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e0a4b534d2056414c3120", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2909433256e5279bada3397b9805dd81195d056d702a9431c14cc2c46634fcb656e162dca4b5a2100789373a07695f6b8": "0x6a81f13352076dce1dfe8f357fd805bbece6ec16efabad52a2c24e6824e163150fe29895455350524553534fe29895", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf290a1cf6de13c900c2fcaae9a03136c1012c0e71d5e85f0442d53fd7419af7a23a2908f88ebcced94150e396bb64ef644": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf290b3eac6dedb823eb7dbf9f5615bc0d412c0e71d2ffe345813bd81eea02b361a65b0b88ef0e5ee8a0a2268a8ad9bbe2c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033538", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf290c655b3d9ca5d7affde1fa4a89e43b13a29d1002e1c81fb779d11e082da66b45a355067ab816aa015f5d5ce3d927068": "0x9aa6373b24df370b863773f45f2bed6ebd80c886c58b4232e655a9b130b6d6150b626567696d6f74696b4c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf290cb66eb914dabd4d48b3ddf423383cd12c0e71d0f4707cb93bd1de1eeec36c3e1f995dc51eeedba0cb52287d2fd3c7d": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033439", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf290d41166ba1e5993da33382795bc0a692c1800d8039258f2722009625f77a8203729e8770d6ea72358f165350233ec25": "0x4e531ab22f712634089201978511b49aa987322314dcd8f16fa241f0055e37370c4172696e676f74792e3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2912b1a223b3e6999688bbf8a97215ab4b2dbc35ccf086294a0d24e1091d08ca3b5c2a487071c4fb54070e666cc99e02d": "0xa2da2913d7db19baf0a41dc40a73d75bc6001ce1691c3ded78e4e86387881b4c0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2913af7f52e6a8ea6b296177ebc40a7007a0d37cd4a96cb4e0445c91d19d6c84856f994d5e099e0f911b6855605833860": "0xf89b361ea400867da22fa6a069fdd840819fdc24fee6cc3763b6cf3a8a20246b0d4441524b2d4b5553414d4132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2914a0e6bd3ba3602f18f7a4d6319f53d70610bb9d4abd640e545cf56c9be0e8886b9ec274ea2e4d7facf8dbc575a9447": "0xa02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d550230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2918147e4e0e94d353be1c6c52c222f2944ed131039b1a6d98896aa12e996d928f7adb00a832fe5c11b719e7d4a4d9b0f": "0x1a903015b9ceaaf0f183eb409d3a38c4f0c9a685066ed90b32c834940c689e1c0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2925b7f992eb3af442a5645737c1b4e09216959aedf96ab893d8b8d8c66abeab8ef62940b1c6a6ab7228099d72291c72a": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf292602536a51c4465ab513af925e2592514a4ee7a1c85e78b96211b9af1d020030203a9d13c0eac03f4106dbe42d68314": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313436", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2929707b74d7370eaabcc6859872c2e319ac3a89771d2fc8c62e9d37bc6548f67306caeeb4ba49e7aef7c09b68a260665": "0xaa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d0e48797065727370686572652d35", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2929a52a46b17027d6d5846b66bf982e3d76236f0c5d432f6e6b99845a7eada1491dfa6288c36dbafe21b45a0d90488d0": "0xb45b073f1e692d18c2dcebae861b2f166a4dbfd95d9780ffef603c9e61d009350a417461726465636572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf292b9e3cc674216db6bd2b3a683ed65d66eb0bb735fa04cc282b87141ed4d60afada62fc213bda5ea0d0569c2a8c25d25": "0xcca9cb5657907dcb0bb01d335b17564e77994536edd05ddd50524a9355c2221e0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf292c8146024721c651afec91539049cff4b514120fe1efd6da4118dab0e2b1fa66ff2eeaab54af205b2ec6c506b52fb76": "0x2c08cfa5b2dbfcf6850a3b836596d82a9ed7d2d743b42aa5c69798b502b29b57033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf292f26db9e1a10596464efc932b402ef1e5c49f7bc76b9e1b91566945e2eb539d960da57ca8e9ccd0e6030e4b11b60099": "0xd3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a23404537973", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf292ffa09d38524f9c0d1aa774b67c212dcacacf100cec1782c4f9342566de5b4132a012335481dc83fb4d42bcdfcca853": "0x3a0b67c6e4b35133a18ff9c3b56d6cd28662f9e47f38afbfc508543087966870094355524154494f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29328dcfaf4b0ac7a274e9e4316053205886a977a6d8063db1b9c58daf3906841f3e2577b07cee9595c5c7e98f7b3aa66": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29363108295e372daca2b92b7cbbbebc64c9984b5187f51b9b35d16a7df5b38a2e069e568bf813532ba08068477772205": "0xfe7d71599a2b67c5085142c626641ccfc1f44919270fcac28d2ecfd41e0c7e3c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29368de12521e294d422942c4cf48ccf200c703a1cde92ffaf1f8312c1fdb3a81140f7e76789d55ae1f0683025c428649": "0xe0d744a6f291a2dc1e6d744d5ae0747e314b046739be170638ecc185ff4a9b5f1543686164f09f949750617261f09f91914b696e67", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2936f517cdc5783a821a4d40c671d88ab5c975241672d5275044da23dcd085d64949b82c83e963a2bae2230af259f527c": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf293c3d393cc9dc062cc10318cfa90edf8f2c9cf52ac4784de6db0c160481ae4ebf7ce0d7066011e36e18948172c05d059": "0xfc659bba6d3985002708101d9c2aea9155bd520c105688751281cb40e4d37163033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf293ccb275d05874df082d79db1d3bdc3076c26a1fb9acbdd56be00d4c44901856929b9d2a879caad6119ad0417e994949": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf293e0b349ed966efe9d44b24fe04ba87050bf01d23906f2dd19d8cd71dcbd3033af5fa1dd042dc4dc1f3f5f86c2e9ad5b": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033830", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29425ecf1d7477bb6ee5778054833e56cad37814b38fe39243c36ec13d832f06e178267058a03d5011f4e06ab78f67e0d": "0x56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b1150c494e4449474f20464f5552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2943fbed7900a24332c116cd5ed62ee005a718199b3c87bd8c24c35f027b2b4ba2789a85782a79cc6a924f9e4241c3005": "0x5a718199b3c87bd8c24c35f027b2b4ba2789a85782a79cc6a924f9e4241c30050b536b79736b6970706572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf294a5e7e6e250f2265bc0fa25d357064c9a992b67797a09bfa4fc79558b14bff0e2ae2b20207ceadef50ecef31d120a15": "0xb85d101c656fa86dc284f34f7583b5f178d9e9b619df6031fe2c04b4c5f07e260d414e47454c41205354415348", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf294dd2b48f94bbb72fb6066cd46e1a0f57cf5689832c7f3a596de7cf58e6d764884c33fa5bcadc7038e65e9361108b10f": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf294f1ce732f38340d83b0fffd53be934a373d025abe0b6342867c03f3772e5e3fcfa7b13d7d5451ddc934efee37894a6c": "0x7cdc1a6a5a7f23437b6528edcdf553d0685f940a4e6e85579727ef3dc574563a04563033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf294f66f6bcd95b7eec2b2de1cf9b5e39f50e1946cc920aa86edf541dcd4bc35efbf4b28671b87c68b5abfb22f655de453": "0xd23f678af47c89d76031edc91e43784bcf9991b131f957d312fced2c5187fb470c5354414b45435241465432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2951b362994cf98a76d2f525c2b9d58a8e2cbbeac13b1017c8a5a32551d77e89017551a2f9438743446de2dc2ed13ec4d": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf295460da598e0f6061cc2d1d6889c2796ba91845c6ce9f14ebbb24f008964bd395a2c1f92149810d6f6133a905706000e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29577ce8ae8e1ccdd44fdb9bb4cbeafa013dbe68838d76d77ca594e3e55c937ef7886fe2e8e46de8fe11f20cdf106b29c": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29593d3dfe56b3baf292a5b3d6e830c04607b422f959ab305856c1621be625a1776d2ffddfac9a03446da3052d7cd3a58": "0x607b422f959ab305856c1621be625a1776d2ffddfac9a03446da3052d7cd3a580c434f5645524c45545b315d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf295b01a64976c6d22df38d3ced3df87cec95dfabf99a55a128f0cc1a12a58cdf161e58872515ee35cf87510536082d53d": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083233f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf295d48737b8979b34a23569551bcfdc2a969b1c4800a2e1700fc49adc3228a1faf72543f36ef784991a2a25d74632b26f": "0x6a325e3630266fda0ef7f7725ef8199726e29d569d609f3cf068c4db7e82591a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf295e555b62758cc7ac3b0144e37591dda9454a3dfb574a6756a307688f156f4ebcfd72b63515bcdfccb50cf7f7bf92c12": "0x0ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e0768616e77656e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29638f6afd44aeba3d7752935d82d39f7f657af299a3b7d16d7c4d27876099924e5905d4d85d683988726e31b25037cb6": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29652101d72ed67522b8a8646680a61d080de9a994f4ebfe1053baf13182362e06fe78b159c319be596fbbd8d027db576": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512373a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2969cc64f0f49a2feb2096e17db454ffe16ee0e830501e14db6f33efb672620f030b65bcd30a91152c9b9abb66f4c117c": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf296bfd6a3d3b57d99a0b4224c1e28ee46a8e2730b18be41205e5d9192603da3fc19d7d4b951519509cb32458ad622ae33": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf296d6c7bceed20143a9bd871ea4607e2d6d3ffc8efc1d719ddf99d29c8a1b285ff855969c4fff0668f9985a6b41c4b499": "0x83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f5890d4772616e204d61796f726961", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf296db546d80b94d272e5849041185281b54c3bc9063fba6c75163f3e051f1387121c0120d3bfe764e68764f02ea33bb48": "0x206dd955d4ade8d59bab18cba031e664ae888491d173084bc9a0efabf0be195e0230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf296e6536073707345fa326cc3764d0545c016c699321be18f86dd04415e6f3152fe5b3bc13f4808bfb4617b9bedc2e129": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073038f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf296e6605eb771be4cef81797aa0721253269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39": "0x269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39033030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf297157ac5f270300f55c7fbc4161c36e98bbf421fcb86d5fd3e28a4762d295b722fae2260d0f3d548fe6eb8cd741c286e": "0xa06446b3474c3d9dcfb759f3df134cf4b6620b2559c4e1b99d3be4d010378f400232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29743ee8b8a0d5acb6a9232ff73ff5c26da466dea606e6a603356cbfece746254c6585b90647714222fb59e42ce45c601": "0x9e0bb283b2d2522a090d71d9c8fb484c7966d3e28b21bc513419ef7f70d6a5630f464f524b4c4553534e4154494f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2979823f538d5bd1d523893f8cdaa15b2ecda6ddb746609cf2736a0b70823b52b11b15b1bb35a4021da70126290bbdc64": "0xeaab0cb55c147ffaf184a4c00513e85f6d5bb6416994fbdd0dd168f3c59a291b0558454f4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf297d1bd2ad87be06432a6596dc8e50db988c3d536bd6f68f296a34c8c3df53f1fb5321622d5f21739b6a76670500e413c": "0x38cadf9abf7492ce1df73d8b7ee82e10c2a0571970e2aa5ded4b9a6f91a498330232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf297d7395bbd0ea44ec2a47571a9ab2859803f3ff57158c1e5483e88d4dd5d04f7f8ca3c5203c6ac29344f314099f96a31": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29815f036bb71d34b99b55524d5bc83aeb8270b6d0325eac9f3ffd34032017f7848eaa460ca9a96a90a5296e34af91f96": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf298160c29cb485d50f2de0a12d611f93f36a8ff1b35d2750c1d8482b5f8290d835f5e497bcb9ebf11928d9de622fc3053": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805407f09f98883135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2981b64b19cd5827afcd4a27d56826450fcdc5fe2f7a0789f42175567fe656b9121815763a037c761ef846f0d97420239": "0xa81e54507ca4f6fa30932b96d35e8f073556c99f4e3119e5f67989345019210904303032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2982fdfd002ceea52e57a6b775006ec4e86b81e36ea46dc1b355c79bf38968367ed63d58e7b61e9aa5c97fb6fd94dcc3a": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2983f6d2269a64d9c6bfd7ee3a26ccade600786fada3d88a3e440751d50f3e522f9b7b28dda4e0f674c9faa24360a082e": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e51064f4e452d54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf298b8e5323878044027edf2eace12a3d6b2f9413214ee983786be59b316ce9fe3848ca7cf5cb20f109b3e31d09f213274": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a0530332d43", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf298c35ff9c09ca50254e3b86d4586ce9ba248e7a6ef290c55ae9f1383eef475298bf04a1a78fc22f186cce5a797ebf508": "0x1a41e8f79310cf5b804b038d19f28b535261fc5c1c3d1dcfdc49e6bf5a946d320f7a7a4265715f5f636f6e74726f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf298d8a7a39e5d3be19e11c4fd292285504c50bd7cf1308738e5758e3f5063ffbacc50d2944f95506b8b4710d1f7a03536": "0x169b1ca15010ef10b423afee4c0fca7e42f745b39e1fe4197436ec352b7f17080c54525553545354414b4532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf299b08381cb4ebeb70490e94f7b088eb716bc1a5fbe6783b4c4fa8be371150435d5cace22115338b33a9966b4de2ef82d": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf299c3e4571dbcb08a3ba8de93413ff91512c0e71d56bc0e445558b892aea1eb53639aaf99ec6f51aba44607213c3dfe2e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf299d617edf1fb6836d3fb1d281c3082e9ccbb21d7b5bf0b08630681c37ebda5b98b5454c8916463a9c2b50262466deb76": "0x68170716ab7c6735dd0a1012045d9ea33891b5f6596cf97eb217d0962d86a51804676f76", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf299e7a835913510e319671e6e48424e90d6bacc09599d6647899ed6734cc33a655c56e6bf08d2273ba8464eb1d4a0830b": "0xeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b23477636480970726f6a65637473", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29a033bf2a2ff16545abce4209cfcdbc02a646f536fec9eeb72210c0a5ae166e0b0853846f4d052ffaf438696921bd725": "0xa8cc040d5d391967b6c50b54d81dbc18acf06fd13a704decc7df6f464679051b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29a1c41ab23706798d628389fa84e65c0661242bc6a8ea761d8668371ad17f9d036982ffbc68af2c28ebcbf2d30ad16e1": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29a5cb01d226018a91e06d985f1279f6412c0e71cf317d94584299468b9a292c7e69d3ce2ba40e4819166c78dce18e859": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29adb7651c6ddb15f52fdf2d547a6fc7dea595939a7255c7eac3f67f54c75929152fb73018a56bb468445373c17200447": "0xe49a94c01d7c0511480422e00ef7030ff64f314591b50d7057deadbd6411112e0474776f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29adfe05e86f52238646a6221a4950f03f4243300b12f9067d1fcf01c8e05f598ec2dfaa142a33398177f8b6e32ecfb2f": "0xe4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f721170617468726f636b6e6574776f726b31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29b01e8742be34ae0db08438a76542115109e87a012b2754d0b23501fe1fa775db374927f09c228f07948f81ad84bf617": "0x109e87a012b2754d0b23501fe1fa775db374927f09c228f07948f81ad84bf6170a736c75736866756e64", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29b04304c1d352f9d8819b856e042349c0c92d4e41eddd3bec4ce4caf3610213e3b3b143a6c0319766961aecc27e124ff": "0x0e038990f47761a17f45c2bb01c4c7746f4ad67c7d0c1dfbd6915372faae911f05f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29b1bd5ce8a3bab3c40e1f31c3d91ccdd70375a0d07a2172cf390b17cce40e34997aa99c1762e9fe3f96a91ed60c7354b": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f10640a425249444745485542", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29b99595fff38df3b6b595984a8507bd7deea74425ab90f984007c4324ff21437aaacd212a1a5f349d31f03f735cce907": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29b9b06a2624ffd2e996e4e2702db7ac0739b4e65cbeea7cadf808f0df0154218982008f8cb4ce04a18b89625e69ab6b1": "0xf8d542920fa20b0dd5e126de37f7c0142db98b51a6caa4968922467b42b95a7404303133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29baac3b430823cc6d06a14178999ae3c8be18f3fe77e8807a0fc3201a7689f4742a12ff44622e1dc241d1a08088ab6ec": "0x4ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29c1917ea5d48a42331709192836f4d6355a7b1fbf19d76a12b4cefc4009405905cbea3fc16452627e6a01ff866e9b6f1": "0x14ce4e09b999c54351c75b74d0bafdd17d86d98b6aab5176b9068e1be13e096f0242", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29c2bc3d8255e38d782f633ed2c3642f047b5dc76e7833045cd155547da3afa84a1fe6b9f8d8556e8c7187c3b2f50a467": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073131f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29c65c97b9960b1ab50e8d1b24af7d44d0033f9ee5f550181bf234c12c2e07ef74652d9323c13ab31ea9c2b053eac7458": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29d29c9439c87f692e75c9704c292bf0a602d88c1c8aef782a7eba2fc345663405cce57081d4a34003b895057d96d8e42": "0xf6d6531d9623034efed118d00dc62831eb6f017dcb45d66ec6af44947ef41431033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29d62ec2f1c1a1b440508c50c06d174f058ac509e6e93bcf6ac0800a070f28bd477fb9e9717ff7779d035094e361b1504": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b3568063151554944", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29d6591f67423dd3eae30b13f892a6d257c50145c707078b4d38802058b2d16fd80748729aac222af64be9e55e854da2a": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e5108504f4f4c2d3132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29d94cf5c11bd3c262179794562bc10a274e6950dc3144fc86b2f190216b04dd5f75c5ee52d7d3d0a949bb697d4843007": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29da5eaa72e0f6d6dd9732513dc7d9b7be7934d8edca47f33d004647a350aaa7ca31871f8ffe6038f187e1689cf34dcdd": "0x09ed7dc92692f6d1b8bf5e71b68f9019a16f825e4eb71bb22c5bcbb9fec300d10c30786e3030627a2d737562", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29db6e5981adfc93bab5cbedc92feb8b4cc9732afe3d57624b8bdd1afdaca3f940d0010ec54c6eeef52b15ee1da15b069": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29e2195a6551f5e80ca943326e7136a6b58a72e119fd6922255ddcb1b3f89bab2286d43b9bb3f5b3fd1d3df6a6fb72767": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29edc61902d52e6b186a7d297baed279c7a43965f93ab8e28323fe1c19ce8156b9d0a941e56661f2b172da1bf74a2de64": "0x184d701295be7bb38b2c0c58a35bf8edc592671c53d149d206e037dc7c9beb7b0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f0984a5859e139849dcc9578dfb6a99de38c0e7726f26fb4ce2b3bc8a17ded6197309efbf24d70d0425728eff597d50": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f12fc9430779ecf768f55ef08254e86d7a15c23db646cb253f769875604c28b184a2487b5dff9c282bd65087e7b4238": "0x92536c5469fd64b2adaee0a10c5936bb0d4c8e4c5e4d31185fbc0c9136e1f20504303038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f2c660e85e746236d5bb3e2a3e2ecfe99a833467b3227e480dd06ccad8eb537c399e3851d8acd1b3d1c3e711db83686": "0x6482a21b7e92055e74bc9b182ded5b0cb86e6f7706090c916f60e8235b8fe51a04303238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f32f4580e9268c1d68e167f1631232d38aa672a41872f698aa995f14f0bd9e54cfa4efd97350e742d68a0c44da377d9": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f6c8fe35aa3f4db319cfda3f707659402881d4f53d1205e5bdf3864a12c724927270a38a1139e0d6434eed97b930163": "0xd2eb07f02043788e254d9e2df57be11566d241c56302b91199b4647947af30200233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf29f8d27205097c0fc77fb50bf2bdb69b796413aaaa130817e645a00e8f380264161aa37a6ef35c2328f4c79565ae9e408": "0x82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e745035649", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a023661e103f148d838160e6ca67efd4f4ecfa7baadacf1a3aa65baba89f28312db782c43e750e677dc40fca086f7b01": "0x824651190f1d20237fea2d5953bb53ec59df25d581e54f291d6978c9a80177410231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a035199af9b75d26986371519d122b7d4e346e6bb879c076c4b6290aaeec0a06ebc5cb198245f31343ac1160e16e942b": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a09312cd7e7d60aa00c36f3dd70e9475e635bb7c13379f6b759e79aa78b8852d750afe7da16ec7f01139fef08849147b": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a0a92f1ab233e621803eb3692eba355dfa6bd8e8fcf8cd5be5d5cf808b5b5cb20aeaf43d7cf5551f1b33b0f029120016": "0xe49a94c01d7c0511480422e00ef7030ff64f314591b50d7057deadbd6411112e046f6e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a128862a321908a2676eb04870be1e83be03f2946dd310eb0212bd2c44122eb48cf77c834699f6bffa88e2697e7fe04f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033530", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a16440a443fbf60e13b7c0767af70dae9061deeb89b61291cb59efc126c4add37ce655a7954f8e2b246fdad18c07d358": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523432", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1825eaaa48ce221369a3de522058a2212c0e71c8c7444fd30b0ba7ccac70112280c31a7b57682c59443918e741b713c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033734", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1987de2aa0c33e9cb255d957a55085ccc2db6639c1895e08c384f618c9f215e32e0fd23f2ca0ff3b013d1c658287a75": "0x688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1b15a955920ab51bfdb77c757fc2a4f9a48686506ea99e3f79e0643854fd07392d8e59f7249b61557e1662de58ee059": "0xfc90e922a45ef6a5dc3c8abed38bb0aae5b9aa7efcd388fab60e329fe9c2d945094252554d4d494532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1c36adf3b3ef482c569689f17c1b29adc7a8f82a2faa5ec9326f6970edcd577f8ed603104845ad07ce5c5d8f4a49d55": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1c42ae62ff0169c3e7d42f1a4bfd73c24d573f4df9151235e457956765e6446cf33077033bbca48d8d5c6c9a1d7fd33": "0x28778f95bd35e3fec4ee72a0d252c47097380c3ffdf93a9600b364ea119c05020c524d524b204d696e746572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1c8c938e388a473d04f4274bf82f47e4416405ae9e2ded76e049abaac98028161a04e23bdd02ed40fc9e1e0826ff65e": "0xe6247d2909686256b09006b07e758ecc128364a926f1223ef04b38628a5a3a5e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a1def25ee807b27b6eb5b62a2cf92bbe668103daef522e6916064ee8e27db33ab950e2d4f065276f7c9d86efbdab3b7d": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988831", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a20ab94b438dc5cd312a7a4f775108c91883cb0c880e437370dbe0ab6747e1d6fc6decf1e0ef4f423b815f14e3ffc009": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512343a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a20d168569c6ac29c25f2be85d91be8e8ccd612df568bb9b459480879224e360d0d8c3caf9365f1fe7d54b458b010b50": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523533", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a21a585b9bb7683f0ab2d1b21ab3b528bd19630ce7a6e94431c5f771e66232e46a034f3cd18006febacf02baad831132": "0x14ce4e09b999c54351c75b74d0bafdd17d86d98b6aab5176b9068e1be13e096f0243", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a21b7ddbef861f5d3180da05262db8ba0a16d6fd4dc2954c449699e5f6e3c7d2f0dc64df5b8008135fd60eb3eac61e6f": "0x8e111a2e445cc0f64b5809496887b3130718d969db6637c0ebf1118c39b15c550a7733636f696e732f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a2e00997517152f7c5a6a1916a7f1677e040d1b984526d7e5222ffbec6cbe8bdaa73f9190a9e3d7244a54fc99cf37a65": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a2f5fbc17674a2ece961c4f66cf723b42482fd4f47789ed517ae4bf2672eba2895d1b6a85e5d963e82cc77c48e57f176": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313435", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a30511bcf2bdb11e5753ecc63e410ffce2c6bbc2bf8ac332d8f9f45013049439bd2d31008db521ffe472e8c4c4e0c348": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819114272696467654855422d4b534d2d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a345f357db50388185012839eb399bef12c0e71d2f08b6d34a5103c892d4baa26995bf4b184eb7507f9e111014e58b79": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033534", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a369a0e2a7e74a70c8e44ff8e9c77ac4003afd6023b1888ca027ee106726fced92608aa111486ac2b82717744009ea04": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a38a952f11746a2911b0532aed30d9ab4c08de8a66557f63521d871087a9290cf8032705cab1ece83bc4e5a230f13020": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a3b65d3ae78bf54868139cf1b48f13ca42d7c710711e3f6a4d282c46bdc093a1796b6878a45c805827b838756ef78e18": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b385d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a3bbb5a55aa80e890a9289301ba092ad486e705093cbe54e60dbb3e63ecf3ffbc84bbfa2a1efd0a3a9282585e2f50772": "0xbc63ced3f8fec642128f2aa9c37e989a9313a67e9635dd85e8bd689ae8d0ce1d0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a3c36c06b110b23a5f4efda988e923e486434ea1ed238bc9c3106178b9371fda26e3d4333adc04513d188844a789c844": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a3fc3d89e3a83adca320ca843b0d50f6fc46341527cd1a52b60dd5884d8ac5aa272c27cd3b3cc6750ffa51ffe6b34ab6": "0x0650a2e41ea97b60bbd3f87aa30d605562069075deaaf79559959230928a248700", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a416a53ddbb72fa299d2d271242163459862f63cee080f43d1d4de935b51b615cd7a15682e28e41f0bdf6565deaadc06": "0x2033f1e89095d22a9c51162dbcce5e28a6b12957fdcb4c3cf11ea8def5ea1e220232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a46112d3948e95f08c4e5bd2916f094fba5a53f10121888c3b765d7a0e4ad64209bb08abed45cf9b6f72eafb3af9782a": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a55918795f90eceac4c224477edaa15cd237627616a57f2897c778f501c919d17ea969251d6b46cae60ba3f01dc0c72f": "0x5842026fdfe358c9320e35012deeedc83c1e19d2b677eba10a1fad0d93c82b660a42617261636869656c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a56319aa32365b6830690093fe1ae148d38bb685e02bad927a5425d733b7f89077e5b2b6c09e8e8990c98dde3275067c": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b0648494d4241", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a57580a9416b0fbf23202acd932054ab129129bd5eb2ac144f5d28695aa11f2f14153863409d08656f7e34c2963dc112": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033838", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a587a8f0f48d85c990398429f01f6c909eed509e1b9e0f45b24942e75abb7aa6fa306d0e52c74fa8811857d54d0bd03e": "0xf287534dd5ead6c0247a1b0d3ada5588e578602c2ed64caa6f6fc2a5efee6f23033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a5fa68b8d15856164c9e0cb0185972757c24bc10ff87531a3d2780dd51b94ed0b85818f4827ddc09ab394a53884c6444": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a04563031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a6046f086be7cc791eeb3ad97f12368eacd6b218c883c8ecc7a71a6b22a74261f1c2394399818ad3f3939ef31e463e23": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033939", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a61efe1bf1487d89d2f762b254ff43ac9fb287e33d2e6433438c3584150a857912afdca0c065f86275b53fe95d3f8192": "0xa86620314a174486a9938856e3b939de3bcd73458780f542388be0cd66379e28033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a63ccf38a7ebdf295ab7eb6f05f851b8a28ef91b1509ab5a2d494b230780761fb5e5ea00e01f7ce4296907b8b97f4c1e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a659e14a22da42c9feda53098784cfe2121cb3c0a7a70ec5db8b5e2ba95aa0320ece6b999a593c146471df768adad97e": "0x482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a74512360231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a6db3a194fcd0b3fe07f2a594dab431ba00505eb2a4607f27837f57232f0c456602e39540582685b4f58cde293f1a116": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a09495354414e42554c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a6e457d13fc9b43cbb67310a31f93951007b26343e6ebaed9459ffaae9358c5b2460902c2a0d63d68a748e1d8eb15033": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31395d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a72f6673ff72d0780e6235664d747ad9502d8f8870937f44fb43dbda57dea5b07eead72982b0712bd52a5e033be3b031": "0xac1d2d82c4a69b16c3ce9eb5d0b6f34f948a34efe62488879a514bbc837e0e500232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a74699a0ff32c2ae10dffd64b855da39524c4404c14e7fbda3e893815a3eca9a05f453ff0f73212319201a2f46d5382a": "0x6ee5ad3ea0da40510f11f42c3281fd543f5a6bfad54ebef7381a7320bb509a0d033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a757e639e4b51ed97c4e339323e1500d3a365c988f1b8bf6c4574656c803938a4e0250e25837f74fa6046f0ccf225123": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7964c423dd9e3aaf5da9f04822e052f74b215d61cfbd296a81d6ead301607072d2bbf9dd308c3606eb1b795a62bcf2f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7a9263bf47daf8ed2eadbb65c3705a302c1151878ea5c35d75c7d4f879fb48ea7a4199e2d3ac9ed79d686a157384d2f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7b19e02e279c0b393f41c2279f9c727fc1855c2c5d97b41f55fd7b122cabeb3c2529f1e27dd836d131e88f5d6a66a09": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7b6572087649c1090d7aedd811559775c975226ca9eedc6f15bb8f513c0fe5a3e813c4ea2fce105febce11d5b89ff01": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7c645175479ef806888faf606eb4fbbf227ec6d922254e93c2342a87fe0840cecfa015478fc5ae7b28bb18c66c3a70d": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a7d9456f949713292865fa0e300e5a6910448cf888bdc13a933c0d1d33653f83d3b34bd775038e0f5900c5363aafee01": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a801c1088a6edb2102bdaea9a3a7f30caef53be490b506e8e00bc24809e634fef3ed2b1f8f3bc9926a39e2b40c3c70fb": "0xc66f4d91ebc7dd0065a5a2837014e5f4cef5d36d36d4ba7c915137d885dd76400a626c6f636b62757331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a81ad72ba738a6cc677caed9e0f2df5d26104ba050f385c19450c62d2adb3e9deabed8783eee0059d582ff8918c03b10": "0x26104ba050f385c19450c62d2adb3e9deabed8783eee0059d582ff8918c03b100a456c64726f6e414456", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a836828036088f3f615226f382327ffd12c0e71c73acdcfb922d6d2daaca383ec2d7a0cbcfe42ac84bb16da1c25c8c2e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a84152135635ed4add79867174ae34bfbc1e141bf6afbb7224e41e050c296f264e8c4c3cabb0d91a5594f0585be05714": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a8760e5f4b12aefc09bc776ef8d705d1d6ea41749ba9fa1ea5fb094593de0726ce6c1ae997e000b3bbd66ef09298f92d": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f36", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a8ea09bcd3fe2111d755f045fc38132964aa224ccde37501e8661ac74a75eb9c2a6793b13e40828860deae744d806346": "0xd425daddf60b2545e07c695d32d6bea2b9343f1528052b4edd1a777e93058565033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a95fc139939688200eeb51ec25bd87d012c0e71c782aad6c734c6714946bf965fe464aaaf2e15c7d43409f936540ea72": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033833", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a984484f2835a3f41e2ba4f61bb3a323a6e5748915493258986746cb3e58f9e76c69bd65bab4fc620dc649c102baf716": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2a9e475cf45beb5df0760b93b4b99e3d488d38ddf4d661801a1ab2efe073a9f35e0acd5c3c896aa28d8b5b20e2e88436e": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aa0fd96e6b35383106d6798df39b9ccfc05809bc85b574b586d8cb6cff329b5e5666a7f56963c06a4c95fcf681271e24": "0xbcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f6201244656e616c6920436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aa10384d1e60926caec3f314cecb220ff954fd2279cdc545fb8b89133ef97c121308e4ca8e26dc2f7d3c3d9b2dc52dbc": "0x6ce8f0f322c021ca4991c83240d0feb94ad1678835b51d228999252bf9223e4907506963736f75", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aa3554924e8f0605dbd0edded09a9ffe94082abb5e84b31a7cb7e0e69fd711f013ac426d62f1e157b762d284ee6efe2b": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303520f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aa50a6c101407ebd9bede53a0c4277144e6717194ee8da5cb1669a5636c8821f764ecffa0bb0e43b610b8bb1fb1f197a": "0x16f24ecfa07199b88f010d94f47864ace2c0357aa4f37898f85cb39992e2036d033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aa51254ca720f17a1f5a7027f48ba5f9c01b6763a287079871d569b4c1ef94255494347450d13fa06d2ecb298c426d3c": "0x54c473bf199d05b878ab34e9a37d17d0a8bf70498edb5c759672e984fa38b4320231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aac99d77f60d544097912c8355c33c854ee9592a2fd8d3954c85b71eb39e6eb323411ca48bfba174abbf1751d2d190ec": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aae461333986963974e8312595132a9412c0e71d5b27b11da4fee8ee2b71b1535daaccd5775846c26ba02d0821244667": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033536", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ab394ee3cf4d50586384bb27c9b041034c27cde4c0ba44b80bd040462654c90c73e26b474895a2fd746fd5febf3ecc65": "0x8429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee210d5a4b56616c696461746f7234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ab536a7613dde80e8e70d0da84e89d752ab862c753d2f6331a4403f28cdd60a942d5611882e934c079a55145f49f9659": "0x82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e74504494949", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ab8a278565c6192692b3b187d9c43f84c05795cea6af4d0bb72417772d60d0e8ca43f5790448fc92f764088b0d4f4b1a": "0x16d5b643fdfb1b22d5dfd3a50157104df0580c910d2754987afc25fe0aaf582704746f70", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2abbffc8eba374975f0e6e558b2307c9230ed0348562c1ed74187bf91ab00d4f734ce2505a6d6f5d189ca1f8dc966e665": "0x2aa53f55efa82a9820f3c2569d4e52dc467475a1a11cfc9861ce5440316edb7a05506f6f6c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2abd3d4eb29ca65a76575312e85d8f7d03650aa13fb0f5a4c3a5ae264eb820463be11b8fdbe5fd09cb34df93c19430a22": "0x66a4d150e1799ed9ffa721e7e95397c4484db801fb7f26fbc4f27e1d158ef8390232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2abde7cd2c1b8f30e8b80c6dce5c67f6ca618dac7de8bd9fe8561c672d303c542f356e8f27be541bb6e54e80141d8187e": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f08303250726f7879", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2acc6eb9833a7502d18771c4fe9ecf81850c63f86e505700906b9303be612c11427a137eee64475e048ca585562f79c50": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033831", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2acc93bace0b7ce787d1d2104372dcab3a6644cb7298d69083173522d5e51c66dc5c88bb7e4358ab6d88b216d6574b010": "0x6a325e3630266fda0ef7f7725ef8199726e29d569d609f3cf068c4db7e82591a0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aceb033b9addeb8aa7d5d99c6a8cf50414ededef8a62c8642099e5b094ef95519a5e2a1898ec9783c2bac2c71f71cd16": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad065bddba06d39b4ba56da138a2d772f69f5924c239023e8555b80a7323494f03c76357fac283664c131a90d13bf971": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b757084c69746869756d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad24a02ed1d484da31090f95d6db1491b046bbfb0ab2a461c916bd646f879787adaed72992ff0182233cc798fc9a2c31": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512313a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad261372a499359b91b3a2e016b9aa80eb6a6d492311cb809fe02a7649fe2c815ac9a824be7761d7f5b28360d06b810c": "0xa215ba2d1b408fd5350b93f2566124331dabc06e94c16d7080d3cd5771d59958063445766572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad3c87deaab49d4ef8674efce03c8935c49ea8deb91aae7843e2cdfba3a91fb9910efab535670b9da55bd5abdb7e542a": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b3568064354524c32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad540dafa3c010985e733c528734c9d2769bde86b6f4610d3b75a775d3cc411da01222b117e84073f9fb18e5a89de715": "0x4866f45ae7b07019c03464e3c8c1324e96d3f05a2c5205e889fe597b0af2a70c033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ad7db5fb78662b93f04b6acc7c18d012041eda8a25068f57f573d5b152e2c8947c7ab80dead270769184cf63c77af554": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2adcecde88c84b8143f2c31ed585d2e44e62e1df098a40f24df7e2359de24775b28736ded030da69a7ec3c809b10b6e5c": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b335d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aea9940615a604916633e29b45b404fa07598edcb29987227d3fc1d585227937f701af167165fb0a99b6a21983fdba04": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083138f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aecb57ea6827c8a04c14050c344d78266ce201e876781c6466468f641ea7defd144b054fd1966e2292bab3c550f88711": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083137f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2aef307bd73838b989f1a749238b6f04a98735853f4d1ce4c0e545e53dbbd8c65fe5f89385fecbb646a26fe00cad77959": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a651331333a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2af13827ef9659fb4dacd7cc4675e17ce2a30902e14ea5ffdb5135aed31d3940e0df7027a27d079c6a67d135981f47601": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b356804554b33", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2af37c584ede4bc96a2beec1a74fb3f10e6fe75fdd65d00f6ea16c22ba1ce89e45441b80c597eca58690664288f1ca146": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303620f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2af5798e78cf8fcbc4626ea2f1f3e4a70c5fd9b06ea650783b1d4ad13841ed6caf054ff5cbe72ec4636fce640bf1ae53b": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083232f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2af74e10d03469e3142b06730cf0bd7cbbc921beb233fc0c3ebb3f98676aad4aea89f81a08f57251e24e2c02f0dc0a901": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afa7012257eee9779458ee194e0b6a5144ab70adf9b1a6402cf14b3c61f98acf5bccabaf0030d537510166a21ee44d16": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afd1838df35537febadf5e3617420f7b8af704356b5593f79cf9861e3c26748ac8ac6a4c2920582293228f56351d2667": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083238f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afd5dbb951d5f4a9f07651fe3541d5bee2cd31d823eeedeaf516f7fdcc4c7287e3d23014e76f804b332d7b52571c2a6b": "0x625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd42417f09fa496206269742e6c792f766f74696e672d626f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afdb125b38cd6e1b71477dbb7dc67946c8ceb3b9d38e7a25f5016eba5e885ade09042c214623524d78c73f6ce9bcf95f": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b75706626f726f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afe65ec5f6703d19a70469bde3745d4fc1c0081353c756023d47df0da1d4c1b9eee95b9bb90058215e6b42ec5b00d525": "0xba98d1704adcb69b1d50aebfab39709c03713555e3d49e75690492b0a02f547c04303230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2afe974c51069584f0b67963f8f53fa99b085746d68637b4db6d45d855e9e31ac9059ffc928c3330ad1e13ac6f170ad48": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b0143ed97b93f210d26c121497e79683e8f0c9814b8cfe6b4a46e4ee7f2b9fd93aa98485c646f07e973e57293a107059": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b04ce42c85bf3a1f40e03b434f56e20740e488d3a17720b2cc51ddc6cc6c4afb23ed4fcde97698aa2cf374fa7fadb37d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033538", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b156ac766093c7ba112248de120f8777ed1d56154af1862efb63fc12298d73411b024a7b5312346ca95effe7011efec3": "0x2e6dde560aa0f00b08d0db5e3c2f199181be3ca53d2e7a0a742aa5692433060d0f405477697474657268616e646c65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b161fc09a5dd4437945738a2db74412778018b68f1983978069a54f1befb11b0702529b1cb9bb0163999d9bbeb85391f": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b1671755a267e779d29b745afa7184bdd05bd77a93988e8d68d67733df1c5c149fcaf773e6a74e70428b2aaedb018ac9": "0x56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b1150b494e4449474f2054574f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b1845a811651232c98d46a6d2db1468678054da56ab2c696de80350f00924db18c896c3b9d66c26750628082750b332c": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523630", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b1bc87a77984491d27e1f0e6ba22efc2b20ba612ec45aa1ccb1ede3e2838ed2b4f5eadad5d80a873d74ead94b9689850": "0x904168b519b2745aa1480867fbc7db364c79e03fafd6e30ccc1691e7214ef8601631efb88fe283a331efb88fe283a336efb88fe283a3", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b1cc4601528b3b27d22bffba3940a3cf60857d3958e4e8809b36403726468f6b336e952d7cdee4a16c32126719dac411": "0x868cd54faea1a0e45836635b2bf658733436ec69c5567d651be592392cbb69dc0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b1d90018e8428ca502a306eab52ec898dde48b0a82d440116e0620963bfc19d1520435a7b64c4b36e5b258be8a9974e0": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b22683884f7fb7a780be6472f2eeabfd2889d414f8bb29201637b8ae394fd131642a3eb4764a82730e494d6e60a6c4bc": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b2a6983ef59563be11c6dd410ce0053c6aa3fa5a328b8a928c0aedc22aa88d14e807d2552c31bda8b23f3ac2cf01565e": "0x423e5d0451428d77e1f81f6f20c87427e355468da3ac8eea9eee7f041871a7330231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b2c14e2914e297220ba4ac2ecf4a2dd0c009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af66": "0xc009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af660e434841494e2053455256494345", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b2d425c1822c8e8f9d00c0f561b3d58a06ffadfd1ff3fb474bcca0ee75b100d244da043ce2e0725e40b1e8c7d6f0251a": "0x0ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e0c56616c696461746f722d30", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b2f4429c50834c52a099157f11c40a473a6a0745688c52b4709f65fa2e4508dfa0940ccc0d282cd16be9bc043b2f4a04": "0x00f53cf59ee4bae1fc47b5df521d48a3cc2d02d5c15fd5d3bfa3d6a4a2e6a57611f09fa5aa53616e6477696368f09fa5aa", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b335bd1aec2af648ea2cb3450de1bf5a759dc44004f91bfe44588e84d9c60517627929b322b7d00b8979035c3fc0be87": "0x8e28e91f200ae0e50fec4354a429a7e4e00f684f594a33437dff6e8c4ed180530230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b34954837d8d6e4690d665d2e8f6698746591c7794e2cb60b8a342f82bf14b2cfea945671453f92e330917366ed5f946": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600c534158454d424552472036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b3a55f3b29992f1e339da4168c1a78c8007cf8c189e43ad7cc1eaabd0aeb82ae7d62e5ca915f6bb87c4a0d85bb8c3772": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033533", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b3be96d7b60e74bf343f4dd04e31babe081c3d2269ab0253aa2d2c40fd37ab6e7304b0daf0bd6068d0d689fb51f1c40f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b3d6cf295dc61108cd8672c531252b07644f5b938a2bca8d0b0d5b0f08bfa3faa67acf54f9d45449777022fc23cdbc0f": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b44e7e0fad1601773b34fc84fbfffbd11ccd666d5c96fc362fd7fb1633ff09d05b3394ad29e7574e4231f5ab2e0f276c": "0x828618dad92559461b479508086bc781d88434e5372229cf66ffc887672e9b3404463143", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b4738370a4177572a0e9eb1ba3a720d8a61a8e0ccd37645a2dd65916d9bcf3b77ecdf395ecc3beef72f3ad5565bb3353": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600c534158454d424552472034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b487bb41f8f8bcf50bd84ad49b25667b662d04da99fa11b0ddd8bdfec9bbc2574ac71565e9346c8e13857934c18b3646": "0x2cba024614ea8ccd1ebf7a634f30b38d65c082be6aaa92551b9c3b4d1f15ae6e09486162616e65726f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b48c0b478f2d6dc553626f8464e3bec9936c411f5a41fcab2c26fd03ea779dfce7ce65c93203c5538051e77258315834": "0xfe88f2849c8b51127fefbb618de330c811b4092da0b9272edf2b8b7fddc05c1f032331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b49ee3607cefdaa13f3616289ca079f136dafe22546294dab15b18d1f15fed8856e6ace31582b0dca7f8d450cd963368": "0xabb9286b2b288f2af6eb392d95b12a64768174de723047b9ae0f86283dd5e34c06506f6f6c73", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b4b7eb72a33fd8a878404ccb4c18d3b01239360b36af37935b370032d2306b6c99c2e06b0312c2de4ad61c263b82886c": "0x5a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb99340650524f5859", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b4bb8572019f90dd482da55248e0f1b21ed7e0b663455310e4a8d084ce985ea6dde9cbd788f01cbc27f9a85264e97515": "0xd030ca0b2a60a30e7d1a0fec231f6f36c3b608036d25ff6b2b9ab9576d59c2520d5354414b452d515545454e32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b4efc7c6912288cdba7f101a722de6d9d8a8b294275746ad87f5fe0d3f5eb3fb81905036522357b616096f3e84bfced6": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d0a4156454e5441444f52", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b4fe5af086dc362ec68a3fd6623154e7027b1e50e1acb6c1ff8777599be3350bbbd0236fd3866c367f420393d3adee41": "0x7ca460cc927a04fbc91f4ddda54149556d1a85196bc753d054aca1fb7621e3490474776f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5129a9ad311055df8bc46e48cbcd31b4462badaa1c9c6bf3e368c5de7a206c0e8c1ec70ff0c8c5d2a51545e0514ae30": "0xd6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c250643544c3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5202c8793cc26142c2ed9c2300e87072ed9d00721b2fe294f0f2af432a1a2d98a45cf3d6db2939ae20f5bf25625ecf8": "0x1a8ab26aba64d6176b6aa462a2a7ef6252ca1063cf978dcb6f6c64fec81e7861074534592d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b56ad69ff410d39715cea2897e28035c4248d8caebe59dd27fb0606a3640daab22456c80bf8449bc0f9ca721ad2e2074": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313030", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b58bca7f1d5002592c9d5f4314d6155dc44a96f5d752d040b443a98592bb0d42719b2cf3ebe538fc10f76637bc054e7a": "0xd6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c25033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b59699f193b136dca7642aeab5b7e63f1240c5bddabe0326741d3653bff06d6fcac311846cede93f8aa44a86a971924f": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b375d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5b91b98aa6173a5eb85270b4ee572efc80e5adbafea30ecb72dec246ad8b5647f95092b535a702b4347d2ec210c6972": "0x321ec507203650141d2ec630b967b76ec45dd53d852b9cb25f220dd3a3fa2e51094e4f564f53494232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5bbe7f3e23bed01c8dd47249447aa6c953288a0e80d88a64db2db07ca48da06678f683fb99301500223d663dca35b7a": "0x582e9acd4386d60a8d3de206a575ab9ab0c383f3b4ee88d2a2ed144afd3565040872657365727665", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5bef284b5039ba4a4ba3ba8eb004ed490e389b9296c049a2cf0cc3255f3d58346b0eb6e6b0826aeaf81aae144d5306c": "0xea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b0239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b5cf72ccc7c79555b6fa9d50f10f9754c2b0f22e091372190ee2f4f79357f9084e1a9d3bc9af30e41db16a3fb31fd3d1": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f0832436865657365", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b600787f7fa0dcf6bcd77df14eeca35a12c0e71d25be2e5d1c5893ed30710dc6c645e8f26b3e1c3ca43800fb99fcfa4a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b6dfaac45c58ac397aa14e90efb01d6976b2a1db526de647dd7aeeebd328bc037be6795e79e7235a23f74198387be12a": "0x7825b33ec8baf2d437c19856a6ce74f09bbf49c284602a18ecc0683874dd596e16736e66206b736d20e29e8b2076616c696461746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b738857ffdcbfc2a18c7c4e9a3bed4ef12c0e71cb2e754bb49f1758439d6729debf9a30cf5b9a797ec564f00592a2f5f": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b75da1999ab35263ba79c536fd478fd338f0ee79e61dd2bd100c13719c468038ec4d722104b0a95fc38af7057c28fa50": "0x82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e745034949", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b77d8d27f7500c1c4a94f6d63eb20ab612c0e71c512bfec8bb542308c909c7b50f401219848e9cd7ee84c2bf25196449": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033431", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b77f5b4c626027fc176dcd30aa8167a9e68e209129894d176228151c41e67d96f9d8ed4da38338fab5c964f2cd2c6156": "0x4211b834beac4f35ff92e0dcbb0167f6ae7a0c43b186727d581d3f69f10fea3407484652203031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b786bbaf5f0f4985d65e2c96b517b5f42cb40effcc1bd1e91c49205a599b87e3a49dfae2ce9644f3a431e974c721c54f": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b79f96e3e2aca9cd3df81bb6611dbd0d62307128d13196dc291ac51e68173c5801fe6bace303a222d2659255d9debf27": "0x8429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee210d5a4b56616c696461746f7231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b7b365c76d69bce8a04dfa122cb30ee3e62bfe4941f647a18c74850008608346ad2c9623378dc3b8856f4d9a17ccb176": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b7b7a632d73902d03c337522ac4f6b102c13d8c2c4b4445943ffce2d55a39cd4c982e5bd4181d30f712ccfd8347ca45d": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b7e3a8de83f5d9c72a220db7d533ecad8e2ca3235e29d530a16e44fdc3a6ce04c42aaff4ed9b7c275bb9ced877bde979": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b7ebe3f39428014d2cd531f2df6e16c48a989898ac32a8333eea5bebe65671f63fbae7c43756c21f8507be73a53941d1": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f35", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b7f510898ca9dc0d3cde9929856ade57ce0b753196d88630621ff926331ce4780474fdf5b100fbcf96dfd4e984d1c669": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073036f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b8077874958094585a4ed28a6037b037ac0c25ae153af1c54bd0eb9c02dbd01e3b462be18089e560a9cd19890dceac6e": "0xb0ef511fbed15d88d75933d12bb50b56d1bbed109380b2fe0c7ec72d441191520231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b8d9e0ce3698ce76df431f5bb8cbfd883c6d21b257bbfa6eaef65227c3ca8f934d4df946f53f65aee505dfa6b741c852": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b8f66ddba1b6cd906785cd2ab3f5d1995eb5606f625995f4a16ab77fab23443b28b5ae51964638b6c6d1020f5cdf5d04": "0xc2a82d0740d343bbcf853665019f2afe81ddeb884f76dbb5c74533610f72a73217747769747465722e636f6d2f706f6c6b616c75636b79", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b914add7bf4db96d40bc2192c35c31e246378406055f64e506440a1b008f875abbbc8d3fd7c05f785a723fe1b5739fee": "0xc852bd64d95e1c2fc164ba7ee6c2cce6e87ff8cef81c60940d46f710ed712b7a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b99149ca92c21e9733fc719abb9e96bf9e7fb05bdd2dc88013e77f26a37dc19e1c1717fde8a27bfd1f2fa8231ddf8538": "0x3e89cc7fecc4ad46cd7ba606522a8d1679863da498718cf9acdafbde8cfe4b7804303039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2b9bba004e878e6b65f88fb505f441de8b82ba825d0fa34373ebb741509f70042068219d805f221b75330b4513f62e674": "0xf0fd6298e6d06eefc52fb2f12dc1a6ff9e8958ac2a3efebc7f5673dc33808170033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ba8007316dfb0887dfa7438eebe1aa06dea318de2228da64b91c671dd7f325df63959f9c51c86a36f28ec94126f32070": "0xf01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e0423600b476f7665726e616e6365", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ba8e2b3d2b14691b6e8f2b344633e311f6f9a8d8e0eb8f9113107b5f2bc4c3bf64a31c6ce51913433873e4357bd35524": "0x1c82102e4554587f23cbd4bfdb0f43c9d2879d18feb6102bbed977930f695f220231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ba98f853e954fceb922f0ff042f441575ff5a4655138350a17e2dbb4ed130642abbe12b52ed03867883f0af9a1ef0cc8": "0xbc955504a40c50ded178a8082516a78a68f503348c16b106fb2a1aa2c594743e065374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bad206323c089bccba048f80edd29a1248b36ca55541b8f8c030a3a844a247a85e731764d015bdede53205fb5b355a25": "0x7eb07fd02281d018a4c45bab914fc6e2a0f81620663b53ab62432ae62a07194d0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bafa48c72defb21f2abfda59e80ad84d9181d99f43daa05e74f15ff308adb8a4ef121fe4976904813de2e16ac447c3ee": "0x625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd4241e5b325d206269742e6c792f6265636f6d652d612d76616c696461746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bb0e7e0784f6df9f4d3896533f0ff3e380b036ace5df3680d4f61cccc6cef4d37bc396e6a6e63fdecf505ecbfe41149b": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bb44505de60060b7443bc2710270975712c0e71d06dd205beae5054c937e4170b53866e429f4be7a98318c261b3a0b2d": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033438", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bb928d4de94710209fa18382a0eaa1a602f777f4b3001d83e7a2441ab8456d2db9ad30b77e5d3f2fa0c4150b769e9a39": "0x0cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bc06dd4cdc189d8a0eef9f070ce3c65b5f58951d682a66090492f70ce968af8b8d39a6308aebb3cabeafd44bb0213d91": "0xfaeffbbb88ab949b51abcacd45d7f9addf608a6e6ddc3d4b39147454e1a23a161356414c494441544f5252554e4e455250524f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bc1cc9ffed2bab794b7c8387367708533245a2e5ac185dedd4f63f9899990dc2d467a359dd573a7adf0817e06948451d": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763134", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bc29a465fa8d8290db0e093571568a99160e772b488c83753ee69cadc56cdfe71937dec6a69b4bee87e4cfeb4bf8d475": "0x2458c79f1b8d080257ba31830f364170c90b6b173be1832ebace48595d193b2b033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bc4c1ee10a12aee9866c188315d2c8d1caa6c46edcc1d2a38bbfc4e200c3851762178268d7a3e565ab99728c18ae0376": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bc80891a015d9446458f46a10ae007da7eb15d7fc95b03fce6ab8cbc54c38ac898932407a3e9bd86d8c03bbfb5b8112a": "0x6041e8f550869197a24ed9e968eae648692cde7bbc04077114639c249cc0a0430474776f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bccad62ada0ce1d94de52aca44af59005247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61": "0x5247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61094e5244204c616273", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bcdb959b5ddbd2d2d60f5ea4cc127e5464c23bf3c5f9b5c2b83e9bf6722b1a6c15671dd610c63009b0f67d4daa521b4d": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b32305d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bd24d016e6e576c1e340b9aea878a99d9d2acafdebef59f646598614d1e0f1ea7ebacf643f0ba096abd078d9a2e4ae96": "0x400a075c48b7985fad91dda0b168b2185958c9fee280f145d2dfe24958a12737033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bd46d31c6545637d7db64114b9c8bbc0ea6f0d87d39b6b348f609c20246f065864972f409b809e94636fad2e6e779059": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bd5adc4b7050e1990be742027d6b835ddc64ebe91ae1dd904651525eb5fd91eb0abf458cb0f5986158803e0075604153": "0xca437639da37528d8edc0bb6b31966fdc0263218f4bd60c6f2cc37e963090371066d61727332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2be0a46a1f347a4442d32a7ad6c50a341f0825186ee2e14875b4da41144acdac7d5aeeda144951b84cb93c5b62388dd57": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2be2eb08addf037c74fe47d69298bafee7cc30da54f59bf041de60af0a1eeaea965edff0ba95e43be290b08ff15f91716": "0xbebf5aa73bf19935376f19460dacf00bf0dcd021ca37d6a2284cc6347dfbb13b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2be4581484e33efc5a4f22c2fb7ea7935d3fb95a477ea8deb243947948b28d08677f5fbc3515d9365668056b12f028ce6": "0x400a075c48b7985fad91dda0b168b2185958c9fee280f145d2dfe24958a12737033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2be638c7d07ef5629ed517c7de9ac8e5d88d38df37c92f9cee029f6290428a9848f70dd8f10d519a6c8a861101863cd40": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2be7ffaf77a9ed2625b0a2444d7405c4a5624e7bedddddd49110e4c76ecfc6d2406dc3bbde447a71ef0e511560f588f63": "0xb2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a04563034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bf222eadfe6e79e6b98def037e616931eabaedff8f91f5afd170b1c8252522e76584565bda69f49ca2e223fdec4b5529": "0x7825b33ec8baf2d437c19856a6ce74f09bbf49c284602a18ecc0683874dd596e16736e66206b736d20e29e8c2076616c696461746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bf2ef73a6f67c9959ea062054f42e7d14beb8e393d37e827b64939797512b2988db9ea41f5b4d2f06a4f8c8fb955d89e": "0x5cadb1617794ea8d20a5b0bf1e3275a815229a34c834c9eb6383602ad47ecc550231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bf553593611c66c71467dc868745cd4fcca9c8d2749a01cf11872c61580b40f227d566afedd3b40cd29849276414c350": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bf662d325aa8286f5766ccfbc05655e76920834078df5f13662750273260531e585b9e802eb1dea6a98e7fe2f7555570": "0x68f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb9607033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bf7716964fc735731e1526ba1768d4ec3012b3f9f22dfe0f9f29a97eb2fbcd227e5bd4f9c27df3a24816f9fd3a4b1713": "0x4e3711ff0fdcfc953c9ff93355ed42146e442c256b6010ddd5b5fe0ee8b8ac1c065374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2bfb6aae7f8cb718d69cb0f57c5895a988805b2b3d962de88736fcbcccefb08f9915ad1ddab9d1e31782954ef1ea3e622": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0732c17118f0d7b682c4eef1536a9e29083308a14f56003ddeeadcf3e12c5f3685f05393380a47adc6be23c88d8b40a": "0x244a202cd6b29e2026b65a07c3fb32422138a122e581a627e35791da331bc9050a566172656a6b612032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c095df4ecf754f5d54cc181242ef3a6a68c1fc61924efb992b4e4c2c7a21d528dca21d3073fd304f536fd99a5cf1794a": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0972e8de0c13e5b5abf5e9475c633d76d6f646c70792f6e6f706c730063000000000000000000000000000000000000": "0xd6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d05f09f909c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c09f36644024793eef9e286856d2db4f8e74741b4eab0c60f4b1621f8d244da79dc84785622e52ac8e4e5d3da9f9e512": "0xee16a0a68c6bb00ee88ee56a12ad67e778bbee540f868ead35fb6851fc522c0e033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0ad33ef6d83ca521b3310eb6dde9706c419b5e959b021c52f9afc64d96ab1130da2a03f08f820789a20faa24a206163": "0x844152eccf08725bea8ce898d6fc5362ff2d0bc9dfc21ed15fd138438d1606220942657a65726b6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0bfa6e33b308d851c2483e1c82b32f44e3d6c92a32e9ec43fd78e7d7b967fa28ed347d96028d73f37113300cfa565e5": "0x34a3f0845fecdf74f7aeb569953da8cf8f8217a9a167a4e7d6b3438d8bb6d82817414e554249204449474954414c205354415348202332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0c182d03f1e9ffa82b584e07c5c05fb12c0e71c9c7a0df0270f56ecec10f80525ff477398256a84db44f8362cc9cb7a": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033830", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c0e1ad46d17fc0f4b698a7287ef8fe3efca784faea5287b50efffea3b8ec2995d80648fcf5292f38deeb5bcec2d15e2b": "0xd86dba437fa4388bc312e57328e808cb1d37cd49143b90c338714703867edd7a16f09f8d8041524953544f5048414e455332f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c10ad8e048145565807efaf7c8b46d8d0fca29bfa87fda85b6d07265341c56bc44fe830e4bc1d7b8cd31f54cac6a32d6": "0xa6c197a5b757309578dfde7a02e19aa9922b8f81a60e81bb0c6b7295090b3456033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c13831eb5df91c871b9b1c11fe81eed6bcf0343edbf88dbd0b2d302af4a027cf7a1b45be2fbed9e9b11b6bb6bcc426b6": "0x608aa0febae80d8c228709183cf997bc87b0aa219cda0928408df22ac7ffef3904303330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c1824b6d21a6d089a61ac4a92a8da63458599575b1d7994d5f588624fa628018dc6357f6a90f488a2d880525e582a914": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c1d348ce50c513331c744df4c80887f61233533732bfa8bcf7a95e0dfca71309e49a1fdd70d43fd5c405505a6826ef72": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033633", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c1e5370219ef8bf404a05386035753985c9752253a165c2eccaa4dd8644eb754e3c760f586e935efbdd7c3b629cc0642": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c2c0df7bcb2ddc198b401ed3b93b3d6e766ebc87370f898dd73004e524f0019b36a511b071efcc5f685cd935cd6ac57a": "0xca42f0b5c7957571706f29d2828291b148b4b162100ddcac72c507fd8ab69b2e073032f09f90a6", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c2cac9c49da2b4ffcb8edcbc915771ae12c0e71ca560b3ce013e7ea6f20692d95ceba300e0b354cafdb4095a94a27e68": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c2d19768bb70536f5095fd03d90932a3a8ad44d6bd00b9ebeda2a48ccdad36d0ca29bd930ca2856cc8ce1c109f938625": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c2d4765322365cb80a91583d75048ec0d693e6d764ce80662d891b0e1496fc7afdfd3470eeb4d703ce721460bb459d6b": "0xc63b6d81d7d307b9f4464304330a840f5159c78a804dd344c5fcbfb3da9aad11064b52594e4e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c2d88f1fd0fa5c57e30db65a2d54c3d8e573ce3c1ed2c09f46eef869e472f6fc1e1345949d22b585d2dab0198ed34727": "0xd3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a234054563686f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c34421b30f87d463f8dae047c202eda6b43e9512a0b56f6e9080b36543163cd843c3816854a331c48cb107c63ee42f21": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523530", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c368e1042e4bd743cf6dd650094c8968ac66f315467fc0b8d0d5d5d8906dae845567f911e24012ab0ebc185ed2dc6a66": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073037f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c36b2c037f282fb5ba74450b56b8cdc60e2515bd2e4ff6a32fed6306b3fc37095cf875c65f987c19c2b2691d8545fe51": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033535", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c36cb8b90eea3eee5d839a707af372125c97524a02c01e505359a29988f9098c6b1034dcb3ed8af5873fac659a10763c": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c372ecf6bda917e8c3993d822e9d2938cafd506351cbb8a3af1f69479dc08628bcdc05de50e86e2f94aaa21306727b2c": "0xbc0525c374a8198f3288a0733918321dfc26532e253d94da3a6a27a4c3e317600548415553", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c39dc7c0b3db9a41dc9d0cb970ab04784445d3cb2872e596cdcab7e8ac9815a369a6d4277f831287523ad9da7e60a53e": "0x128b1857f835ab1569c06a71e4de49df3154a9d5a5fabfa2a4f1ab1c458bc1400ff09f8d9d20434152424f4e415241", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c3f748efc07f699c0be80180e548a68c18b8c0db8e0d79d681abc2cde9bcdf73e8b84b9e893952d5528d849a465f9a25": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31355d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c4282e7215ba56f6fbedbad9256127c9d3247cacd091a8f95e795c76e84bc34db75ba76e13a79c1c4671f12f433ee83d": "0xd3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a23406427261766f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c433a21d7d9dd5728f4fc2b5002cbe7012c0e71c85b306f02dce509fbd905815ba90fd450199f70a6e00a56341340360": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033736", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c43d84a1afca11e60189cdbe2d58a9702add23627ef63d51a47ec9d5f0fa0d06fc3dbfb0e84183b90a13f072cf735300": "0x4866f45ae7b07019c03464e3c8c1324e96d3f05a2c5205e889fe597b0af2a70c033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c44d77cf66ec684924776cfa5a523fba5c975240a88ac1dc2d87fb2de37a5d8759307dd7cc9281114515ca26876f530b": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c47a4b177cb9cb76f304a12fb2e5dbaa326e27145577ff5e9bcd3f75bba30fca9622705f65a07ecf04a5d692b284ce72": "0x9085297d964ea873a23b63151b4c82189c1314c31fda6f2d71f83133d0877c5c054b534d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c48fac29dc8b043a08ca8a6866a3172d405637fb518f654b40c86cf257796c857ac3c28e5ce0ed978dcc4d69a5d67442": "0x628f36dddf8cdb0242104a2531e7d3efd4860a9a4633be69aaf30f63ccb25a5e08322d4461766f73", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c4a73ca17582841b17aef5d92af7ad84764e2315d026e1e02073b27ae98b6866388a0208294c4ca8e4d70e25f4ddbf18": "0xe2fec50feac8a6c83a3e9f869ce04ab800420b2c80c4310f2de2e9f0adfa301d0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c4b11bc3246014d0ba9828c2f1e5006eeee6c7b76518ff52ab727047c1214470a0fb4fce60ed6ae06185a1501e9a4ce6": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083039f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c4cbbc94ab26be6a5bdb9daee5cd70725ecc1d4e60a92262c1bec62d034c979f42cbd3fb1c28570d5baed6e5ed20d533": "0x5ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43035631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c511c6d5a2c38335a61c6672dc3acd6602a6ed2142a394d0f42a51281478530276f88d15657aa277b62c54bd1576f322": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c516cdf13321f494db81413474fc683812c0e71c49ca78c235b4cc7c02b0dd42d2ba68cae14091330453206d11f34a56": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c52166ebfd1d6b8020d3943d7cedec91941acddb878c9380546d8e08a2c94431dd6943d8c238428364d4eaf95218075e": "0x983c5a0d1f1e697c1a0f9798bc25543603751b41102d41c3b0e23cbc6e3fdc0b11566978656c6c6f5f4374726c725f4949", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c57d41ec62587c3fb8186cb0e3dfd8644396d758a45239e3ad43d8ffa0d171a6785aec18c571107c6675d53d082f09c7": "0x92e02ce87428939cfbb7fbeeb1ee758b749a5854a1bd3ae9ce36b3bcb753010c04303337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c5e7f71fd200b6fe4eb9835f4d1b25ff6cf4b9ce8d60ca73a35f036cd58afbc52ecea4d691484586967ae1ed45a1c423": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c655baa60c6a1fbebb249e33cb0b9add2bfbb8610a814c9052c287849831e4e28789a020afae5a23c9a19d3f37864a49": "0x0a71c6a0fbf9b63ac089c5395bdea4917a84aabb3475d4454147c4d24ce1013a033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c663bef8269796b13f10c0461aac5d7a460fbb15abc6a11bacac5accdd7a64ac63bf649e22c4efb879ff0cb0446b7e8f": "0xac2709eb9569c861e63940eefaec1f51ccb76eaa84544e56331adfcdec85991104303033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c69574091b5b55b20ca1398ba24ed8127e91f2c936482460b397eea5923867efeb2635679ca776cdfdc62bcea000250d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c6a263da35f84d08100669e601eece0f7c731b26739bf75d9607468391f9d743d3ee7f65f8e668d770174f74dcab7f43": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c6c3052eab8465f19e95119c634901719e7b589d0d5c36284021ae227a2e2be43e1dd1b67c0df432648e5026dfac6f43": "0xc46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e51054d4f4d4f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c6d5d6ccd4c98d250adb9db370fbd83c240246fc1579b9f65b2c83cfa020ea61e54330741399b8acbc8b7215b8dbcf42": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523338", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c6f5823bae5e0af2ed8e01c4052ef851473d3b1ef58c6170dd0d8e4f61cdd1d594cd17280988b52a7333b3a98fed4269": "0xdcb38c186bf97625f108b4832981d966ebed50d939349d4437a6f538d40d56760c56616c696461746f722031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c78f02cbe754419892002443c7030fb284e7a9749fd2b23ce7f7b775dd0f3808d6cdab42ba064fb242afdf0283e60a20": "0xe04ca25cf1cbc516ed1c138492a7f2e606f60c5a9ac96cb405eaa3914fd129730231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c7e0feeab14ba681f29b85c5ad4274fe9dfee84695666c414061c119c231b91511e18267044792868388c73f59306474": "0x08745476e8a2fb16504c77a75b2dd20b6f56cfb71c87125f1707a702753af24e0d4272656164204c6564676572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c7e4e58a6554f3b70576f68ad2adec1112c0e71c471767a1c8d1f0fbdc97763c8730745526c890b3d603d90337caca44": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033735", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c7e7b67dbfb457a80e1167ce2823f278867c63888fb81ef44bb0d5b761d8b536abaaaf5dae3b5d23891554e924049a4a": "0x54fda5a0e241e5497283afebd81b53f6a0235abf62a9bd39594be3f42d291e7f0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c80d069f113fdb657473619a7965822308c74cb0df1d73c69a078a6dd56d80ea94e08a2f72cba07ce6c5b471fcca8976": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033639", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c862a10b89cbe9a3dfa65a39f18b3993ee75ab2836d2ddd324049b86b224542d6cf8a12b601045ec14c454fea4e9cd47": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033534", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c87238565a7c87c42dc1d0af6e850914bec1f258092973881a9591a5f751a5ca2b305c6bac9f4500c0e56ba02dd8581d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033930", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c87c742f32bd7ed02b901c06bc6d6b877fc552b8c6596a09ef8008c83d1dc8ee77dc175036bbd2ca89a55b855a0f01cb": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c88ef78987683612d50c0be34436b628b64bfb076e6685695cbb09316f448529f41964fbbc9520059a0aeed64d63761b": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988835", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8b8e9bfd20adf75bb72e680248543b6241816355a91d53c772aebd5c1ff1114bb35fd22995e8b0d84fe770304b80352": "0xa0ad3e520332a754892d7a16de9de871b9f20e982d62a498b5d9c7e5f93d433e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8bad951e3d5c6352288db6618ba66b03b839ff2a9cba91f5d0a511651c76f3ae7e0eb8bc76d7862338f987e506ba6de": "0x58bb56063a47ee6e4a4d0bfe444682394a1e4657fa39f4622f2a0285689c1b3c04303037", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8c2ebe9ba5122aa7c5b611104f6d2133c667aac50304fdae4ba9932ebe5628ff1e133986bb2e1ce686f28c6a5d4ac27": "0x0a409ce1eed912358015a8139383b02292284b392bf23ef9eb89c7f31ed7e10b0c47414c4158594e4f444532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8ef88b4ff9043b10d3482e3d690190188d38deed3dd10c90cab2c1a5b59040baa3c1742b2439d6c4ac83df7da5d894e": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8f27ce4c04af2dbee5b29cf6738cc4e64dd9ec1480c8ae7a38a6566f4634c7f1b5253a0fcd426b3c712d8e2779ff71c": "0xf429460ae52548e754c712a7cfc75f1bf7c9295da165293ca52ccc686db5c02d033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8f65b71c2d877b722553f31af6ccfa9c61e997a53022149bda8907ce19e1780b9ae75e23fdd6b44fd5a6adb4ff91801": "0x14cd612ff7f390b9e90584767a00a4e9b740b61c0f2134698bbac79c6649764d067374617368", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c8fe8b016f9239cbd637951585c50f2512c0e71c4dd67a196937bcfc45ed0384d81a3b7e8a5b9746ac82081c4bf30964": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033634", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c9112bddeb1c092662778b846189608264563004d7fde7f69c99e461d43e799f2b8bc69c9c6941a265f5fe1e7e50c464": "0xbc486ed2f394da6e6b58b130687b48d3d19f756ba6d0655d37bf58ff0f59f974104520504c55524942555320554e554d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c92041aceb812cdc1cfef27b6e230ef0eea34392724db7a397808df783a7fe52ae6436bd9c2d86af32abe8dd81f43c33": "0x80dea82a6a4704d208bd43d1ea1d5a0bd97a9d20c5237beb348be8c82f37d93c0644656e6e61", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c9237312715124e8572d812441a946b9980e50eb048a8102b537fad10ac389068a37e29e93ed6cdb700ee571eb988116": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c93e26ac998c0f325e7513c26a2d488436ea3b4376625f8f5ac0cf7b48b7a186f96bc215f34976f9eb692eadb46ce29a": "0xac59122f8bc8c527a8efde87156403558ea66ca0ef049cf3fa4f671f98517d6104303131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c975a2d94f7f370b9deebb70fcb33468888593ed4e02aa8a39aed15ec8aa2f0ba2eae732b9e2bf7f6d72b6d012fd925e": "0xb8897a746ceaa53376946a3da353c1c987df8c0caa4395ac0eaf0e6c748740540656414c2031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c97ab4211b2be80337ce8db6424a4b82d2d790f992e31eec84ed33b3ddf3e92ecaeaed911f0026c2ca09087f3eb1d3eb": "0x00f52ade889dac25285059b639359071c2aad88e3f1f60593f86cc460ce2021304303236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c99c694356696e0d88c2b9f0978eaa40d6574db78e7c0315546032b1775930c40d4cca7562e9210cbde93344aad7aa54": "0xe04ca25cf1cbc516ed1c138492a7f2e606f60c5a9ac96cb405eaa3914fd129730232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c9a3fca2fd6455d970ee5a18021cc07f12c0e71cdddce276170fdafc609d13aa23bc51e46a52772dcf1e378130b6b014": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c9de13c0f1f94250695cf5357c033fed5767532cfd7c17f35bb22551c3364d9737749661b25f431f04df8364c9db3954": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2c9fe0fb7c71abc4543f69c72b7a12f10f29100ef06c7724dc32404caf185c03adcfe64e92a3a4885e08cdafab2594d2d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033431", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca0a74073e20c91c21ead30bd7c080ac7bdfd0ce52699e0b3f913ebc544b48b0cb02fcb8cb394625f88945200318f592": "0x0093c7603ddb81760e5c90ba6c0fde51812e18e6cc14121c081f5a573a86814204303237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca264436f692517aac39a0019195e8e55a3116fd94d5f079378c4b1f2066ff567078ae68d97100fa408185a98ee92fb2": "0x9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d2775508576869746e6579", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca4a896e116624b2861f94798a238d6a29cba2b60e937fa112f8e61fdde36e4043d0c40b1eb73f12b5534b52d01b5e16": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca60b7ae0e6a88784f6dbde953128897deb536d9d2138242abbfb7d0f1b7b2905d8316566edd28c2d029996a89e51e09": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a0e4d455a5a414e494e452043544c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca68f8e1e13fc625a7186db589a2d5efeaec5e47daff641a4a15c87ad7e12649e07f6ebbb54630b984952184c657e441": "0x88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ca791bd928f52765c183f6f1589e1951c2b69f99b0ddfb88c8fa9df62c4865ca4e69515a21c16bde93c726b1e678a156": "0x8c2f8f1570391214b89f82df1e2e0c12f9e2e814cc8e38b3d8baf3692724a311032f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cac3a1bd3e914af301f241775717b98284993faa382230fb6bae24747cb90b01087b26817950513c4b313168b517950a": "0x4e516d9d6527c3bdcc45105195b8e23480bc0f257308b1f4fef03e06efbb1c5b00", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb02f7923bef31f1ce1312dc332cf80f603d8b10a42a8be5f7e755820b0c4241732614384e039536c8e43d3b41443056": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb0b84d68fc7b2a7866ad3cb80b672c24c6a12b41192cb3355642a4de4fa55ae61387c23673f0e8c8637dd864eb0c443": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033736", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb15507f9629d869c55b268697b25ac0d6d65677fb307c3ac6c6c0405a1ecd9a47d0ade13ebd9fd340038fc78d9d8836": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313039", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb2339fa49f11b9c1fd38f5f968d07102c01bce1cfd949c169cf6d216d5c446a8c947147b5b7f128b6a46dfe92f90f00": "0xeaacc14e67deba7935dc28c86bb8b6bdb64239065b718fed6b8691ce141633500953494c49434f4e53", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb40f49264114da393e7182b3be70e075e25f73392aeea8ecd64fd33e2dd4728e355e314d8fca42e2a382f95a941d6ca": "0x5ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43035634", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb5a9851dff4fdf52cfdb2a41da2aac53ac5201c3a4b0b032e701e34988ca6a06831b69aadaf9a388dbd33d85ac85f6d": "0x14ce4e09b999c54351c75b74d0bafdd17d86d98b6aab5176b9068e1be13e096f0244", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb65691609bf934f487f8039e13f8182305b1689cfee594c19a642a2fcd554074c93d62181c0d4117ebe196bd7c62b79": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb689f2fd08e34f3e90238d841086e91d8151ecb8e8d11e6c6bd81ae49216b9ef92d2b83b3ae39702a397922f1477768": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a064672617a7a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cb7fec13b4b0d346f813adbf6e0f4714d2de3abc2fce0e6fb421d7a29d736a9ddcfdf51244022ffc483a291c4e4da958": "0x5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47054b413034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cbc95794f214bac79234d84db933b4666a1241c7ef9541ddaad26287d92df0abacf7ac4a7fc4df046e4b866c05db4aab": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cbd2e8e70dc5faf3239fa2b71325c085426c1e2855920b16c78a37f7b6f480163f2a876a889f78b1ef2d11ebc9fd1459": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc0032b7847c0117ed1762e6f5618b9ce25940a2f472c60c242463e18c20ab6555074a0644ac2b9583140abc15e27124": "0xabb9286b2b288f2af6eb392d95b12a64768174de723047b9ae0f86283dd5e34c055368657a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc32df75fbbde634234f8396ad7d4c25280daf6efb2a16974f928da1abda06f2997f18a8db3cc73dab3cdc97d13fa520": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303420f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc5cd9eb850ca3895f1947c8669274c754572de1db5ea15bc7731401c4fb92ba2ab3f7c387acdbbc2590a673bef4e248": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc60d0fcf17e5894976fdecfb422e9975e5085f483896c9bfc341a80912faf167a1ef9229fe8b2989de7b6bad03c63cb": "0xf04c95a6ac10a0db5af28ac44776f95949dd543f494f8b8787925c41fccf7e0f033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc69ce5a07e89174505f3dc6f32b0130c6125fdd59c2b545e1032e0223a7ae0e3aa3c4ebbafe72576dec399441068e3c": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083237f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cc7658cd138d09c0993a1fbfc7d4dee1540a38c94322e193c52afe4d438b6d6b1c50a9cafa87e47f1fc41221594d5f39": "0x7c88cb63517049b0569ba773b2cd7be3dea4c7c88340ba5f31c7bfa2e847f65f04574d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ccaf6e6baf961c91815720cb19b07a1dee67b25f8646b574d06dda6da0b74ececa842c48cdc5bd8fabb48276f28a6043": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818076c6b736d3033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ccf2a14c5e31903431298a626cb6338886505f7c520a5d79d531e99903d5a18615f4510652500f511c8052d8e6a42721": "0x0a71c6a0fbf9b63ac089c5395bdea4917a84aabb3475d4454147c4d24ce1013a033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ccf79fc0aca9b50e29400ea26e3766a3f40945c32b5bb894f311b2a680d927a1d26080b3b4b1c8b5bcabb196918d0e2d": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303720f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cd4c0c53d5dad472fcf92c48f39dd8b04e9a1114da2f930a02193c823ab3393fd2f4867b0ba68ab5ec267e50ecd35420": "0x5271937d9336b12c2801a62938d27878729a7987c705770d5f19c0e42ffcc64c0c455645525354414b452032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cd5844c23cffe5eeab0272580b3c099e5c97523e781c4c65e7df12bcab25d2f3ad96a2e73c9252da3b889bcf77aecc5a": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cd76e777b154c1f906b39ca7917edeac0cb5554f54c346c7996d2f6ad6c5bedcdc094b6ce0bb9a4afc7db6ae865cd378": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cda725c218beb9ad3ed6c3f612069deb9257672efbce6327e97783808a8feb2ef8dfa71bdff401f06700337dae17a253": "0x84bda1949a2b78bfc3b12dcc8f2c8e8822912efe0c693a23effaf7f3b54e9a5c0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cdae06255e18caf09f75addd45e7945c60bcf3dbbcdcb2254472d74e7522e08b6e35bfab991d39e17c8e35ab634e3c28": "0x34f589d251903b0ac5a22b1d13d54696fba34b77f5d21f5244de9071711447630232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ce65ba8dc6d139df7b9d100a5355959d9c9d52f08adf4aa10b316922daa16d396cfb66bf6d3b87454d7a468e19060f68": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ce7325022b2841cbd87e51dc0fe475e72f9daa984f4b569c43ddfa8b12c3f75e2e02f8c0ce9980e00daec2cb391c74a4": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083235f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ce84651c82027649daa82f74929a1a68ac5912fc44a3f886271bf2e8f0dd2d5f102f7bc313f1009b771526114fdc2d70": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31385d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ce8550d1d22ea15df455e6d9bafe27d0befe117ae4a987baebd13ac5c3b611ded994a75dc9ef2dfcab5071688ec9e2fb": "0x702a6dc9592ec94ce9e1f07e2a0559d7f43f932101bace2400d0e92419218732033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cebc66c2defb142ef92b6aaf4fd35cd226090dc5275e53b65763f135108a9111289aa1ca6331a8ddb3440059cd33d75f": "0x26090dc5275e53b65763f135108a9111289aa1ca6331a8ddb3440059cd33d75f076b7573616d61", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf19e88c68ecd0fe6ff5531f8a20c3d056a88434d91c219575e30f91afe0ef870901772375a33f006fa82b7c743b4917": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033936", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf2a472468ebd4c5207391a823f9eaf954cbb80bdac7fd85808d631bc4007c2b928e88ef08e8773d7b26e0acce33dd39": "0x7ec07e354ed4f92abdd5a1570470994410ad04181deb63229bd98ff39b73170a0f4b454241422d5354414b494e4732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf3df5e48db7f78958ad9e0c84b7a87d787f2dc3f07598f255932ee1fd3cdfea934389c61a31473a87d270655f70811d": "0x287e6f010e50f642775dab59f39ee4de313fe6325181ca603824399cf4d42c080232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf54cae9e2c000cc351b755c233471197618f7a742a744daaea9f6761f81fc54933a584cc5b4870a47e9525f42cb1760": "0x82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e7450256", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf59286ba700190de3e238a509f05654e2dfbb25f8e8e6047e14474e054090c283b6c8d34fbcc7370fff8292592f934e": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303120f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf5a7a71268d5aef05bb902061376d137294d22dea735215a7ac4a2aee260eb25d1beaad4b02bd8dacf87bd611a96c3f": "0x7294d22dea735215a7ac4a2aee260eb25d1beaad4b02bd8dacf87bd611a96c3f0e416c656e61204c656f6e6f7661", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cf84a8a77725503ae8de745901e90a5c0aed675c9de132c2b598f6fe8d256c8057b2d2cd28b2ae3fe6fad5475b407324": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cfc822ea97fc4ccab14633d946df8d1370a8fd1a49157402789a0c495dc9c9d12e87a64805374661b32f1d715ca22f5a": "0xd896f718b4ad053ba53468ba0347060b4a80f03fa72e9c14da5e2e7ea80e3f2c046f6e65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cfe0705b1ec0b13dcfca8982fe2be0685e0a33a0fede6d4995303cad923ea9cb39de708069630184e76f3c276b76c772": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523339", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2cfe616516a4c40b9240377a15fdd83ec3f9bd8000dedbde0a47dbd7bf089dee1fa558ac28796942a5883af07ea59fce1": "0xcca2a0719fad006090aad6536ca8b7d8c527589be01b0012564dbdd36d9a492305f09f8c9d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d027c850edbdd122c1ca049f4f84bcbe6cdfaeaa8c9eba3e4d30f66d1b53a97f830612cdcdb1ee1d203a797ef4973125": "0x4e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006054b563032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d05351a690517c7ff30db70d638702339a7f00455c8ddda3532450ad2eae9a5405522b11b320e52851ac6fd870b12d12": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee070f5265776172647320436f6e666967", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d0c0098f070694c79f4ac845ed9ddfa312c0e71d489fee1707d4857f5f4cca6e9ccc10a81fb25b9cdf5c2d872d0f3a5c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d0e999d1814db997088ab8eb16c8e4ce2c61f078a240b295eb8d19db50e5b27b39225ede1cf718c0872c441cb7ac8d54": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d1225dcab17d4833c75587142b80cdc916cec430366d2ba6b46f6b084f62ec4f76967ec6fc65101e6de60c92d2751977": "0x664b2886e95f12e168b420f06b90c11d8cdfa7ee747bc12e235a6d5efbae6e12033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d14e8491c6088ebd501c2798aa90a7983e8086aa5e41114ace08f4330aa4d5adca61f5dab191bba7ab6b2596f1c40c18": "0x844f55022b2b8667129c167068a9c2a6bc292f2d312336bd98339d686b575a1b0e414c4c34484f444c45522d5631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d194b05dbfa05a400c9c5eedbd8b124c3a43a4e20e15a0c9e0009fa11135246e1de9cf4507c1945bc86cb0a088c1c465": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d19b2b7f6f4027c79a0abc64de1ed2c7a570c6ce21a0b2f432dfd11756cca948259a8b281196ccec975c681372a06280": "0x3a731ac0ae7375a2cce5b504484d91f1c49923b3425072e36e12b0afd5f2a8570530303031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d1b6d842ffc033eb576b4e2268de1a3f6cfe88656d6a99bbf56d216614a02ef9f0182f63dfc21d7dfedacb4ff517f135": "0xf40cd7a2181289e32776625b9f3a193f749e33ce1bdeb76cfaabece606c7324c1968656c697873747265657420666f756e646174696f6e2f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d1d8e0232be19b72146d75ffbef993757282bd520ed3b58e948d1e3ec6d993c607c87f153a9b90954fa973cdf3adfc54": "0xa845ea35913a0fbdec49687ebc5b1579bb632c080ce61b02919ba40bcf8892760234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d1f92b7f176d02ad63f25f36c9c66c1912cc166f2df9f0fe89f79e2b568a6e92d61ca5f5f53050ef8744edf74aced0fb": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d26582886f6371b327d9d490054d68b8681559f05e3544030950899e305d923d8e11e244943c1520c35e801253d28008": "0x8e32641448f9a5ec78ad04a33b7874a2942ca7ad4c7e8ee2e45409cee1883e060231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d26ccbf305e9a72d94dce38f185b6f613a4d56fc0f3aed44e21a24d0a3c17a4d6c1360123ce0a4d9a22aaac577031c2e": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d272d57e3f1f50afcf83e2781a1a3bffa6f39c26ca691bd958706b03619b5579a313404e93089bafe5760b2a9db4b551": "0x6c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc12857789867608e29aa1efb88f34", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d29b1f2499b255d6726de0fd9a8f33d4b842b822ff26324247b6ac5a4f3eaa2bb97ab63a9ca95c2ff07775a1858f0173": "0x78283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f525033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d2eeee9a44ebb023b302f71ce92956c9807a095defd81e409429e0f0036df659f3472f90e3b9376e669b71adb898702c": "0x184d701295be7bb38b2c0c58a35bf8edc592671c53d149d206e037dc7c9beb7b0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d332c90c9ea90c0bc0897fbf38b83925589d797b259ba12d5f74d118a2f63fdd5b519b69003821b9da81614225776a2a": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31325d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d339f0d287fd7b01b925311f978fa71fbc154c7a8b77c508d364f2ad31111f48c1eebcd3367da39f5fd907b510e5e170": "0x68f8bfef657c69a5c34721cbaa618ae9eb2108566f9a2606cf5055578e0c251100", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d3804a2d371ac6b1b45ff1c4db978cefa61366bf4c8e9f8fa63bdf70263753a1d34a66a616dca43b48c9f99d2c641c7e": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523331", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d39abee85bb62414141a5baf3a7022bc2dc4deb5830a5e765042800fdbf03927e72ad3d40644360b07cf9ac241638701": "0xb45b073f1e692d18c2dcebae861b2f166a4dbfd95d9780ffef603c9e61d0093509416d616e65636572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d3f2c11ab0f9dcc8fdcbe4b7d2419a2ea6cf293e01355a99ab2429bc7d9f56bd24beb526079ac3eb0a00c3c70e4f6465": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303820f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d3f889daf4e1933ed169fde2153f634448ff655461db0e896365cea6351beafb80b40f19a3c453fc27e6609f872e4238": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033637", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d3fbbbc50dd153421623bd762a2151e4c6150d4b20644caff90e355c0740cf211f04ec624a65acac57608e7390488f0a": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d3fc34f7bfb87eb2c0895361a192e82a94ee7175041f3293479d3abab6dd9fd5e5d463f539bf6eb18a2bfc85e6c5bc54": "0x16eaf9666bd95a04bc6ed619c30a4809a43fd7265e414284c11b27b8c666fd23084b686173746f72", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d41bc04620b2161b34eb34e6a47af25a3a337becdfacffca71fe67fec208733754f035958d349d36b30225fd47798f6a": "0xf857311106c8d7b0daf6e096db9a0d759b52403e439ab23fd6559780a8b1c803066269736f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d435c2aa12bf8a0adfbadf18fac462d02602783d96c4e25d8f6894e457ceb968bf1c9694295aee52514d4919056cdb12": "0x26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d4a320b2374d4601da0b577a391500a08a51fcf7cd53d24e15d85b8180f31d5f9b295af7841f9448f80b7264f3818752": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512383a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d4c814a5e0c2b6022849e302087912d44f00d8607ea768fa23a0befe7cead74f5f99102a70f53aae2cf68922f526523e": "0x046ff960b0d51db710b8ca414171afd47c9612311b69fa9416622dfb42a33124033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d51de4a39ebe413b925af948980a9318ce00415c4b594b4c5085fc803c7eb7872847b7b50fbb0ad93cf0fb95c7a0bf68": "0x7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd7681903434c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d52334bf3f7bd78a7fece8f120b980605f5013d41624228728182b71bbe799dce7dc5df6963fc02730c6b4b3e84273e1": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073132f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d53c55f298492f938e93d235aa93defd6c98dfc795cd34290966dfa3a4f690a2c703dfaa31792854885295a61cfdd670": "0x8a320af9e031a3396f15acdcc65c43008124068226505ee7e12bbb0a12012e600c546563686e6963616c2032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d561cdf3d173b0e7dfe0ebd50b63f0a9260707c021782450fc2707ad65e0ffebf1f9e4025b69b8e192378e4835b05f74": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5741a0a36a4d5ff8186e070a2e5f417d4cc99150b203e2ded46d1bdfa43c2f64f89cb4a9102e8e6d5b37784ab97b117": "0x9642d0db9f3b301b44df74b63b0b930011e3f52154c5ca24b4dc67b3c7322f150573756231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d57f307487465f7a00d54cad65ec792a34a2536cdfc1e92e55a4f4c1310aa2cb76257a87b0e66cea1f2d392c7080be22": "0xc8566f6d3669729e877cd5e453d59f6be01ae6f31b7a9c9925160e70072f7242094d555348494b4132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5912e8857d3fd846b9b7afb3d401568d091cf86d04141b1c17c70826c08d074cae1b00d6f82de1b8a5406ea10ce723b": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c095452454153555259", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5a47d7294408d90d3f758a183db159d49820d872869c2370f72f871556e9584aeefb7b7de62e6559c69f1503cbdb545": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5a98fa4765f4842f41161a64bdef2980cfd5ba5a03ebfcf979f3bb7d68fd694bfc64d37bf04ca7b2e87d4e38827f94c": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523531", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5b7042dc452982b56910a0b527fe10c9cbecddcf7044de2e7f8aff6dddd8660e28ef5214c59623dd37a62d950da795f": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763332", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d5fa0362c54826076a67ea94dbd89fc41884855fe5ccb84c814252cb959d599ee9f90de9d3b7c65058b75c39f21b2802": "0x225f2459239641fc50300041f8980fa044cb07705db61fefb340804172b1c25d033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d6422f105e1d8cb4f11ba2d711d212f922dd0bd944bf21712d577daa894b5d2def3b907ed1ce8cb334dff3c8216e1a59": "0x50df6ec6f3dbb1134df6fd1d572d4dfdbe1058fca0e7197ef8d0f3d05a720f5e0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d644185f1c9275c27934b091f00ce5aca56bd842d168e9b1eae2ef3d1f6d323b9bd4b8db997ffd2ff52369e5c0ba5512": "0x9c2b14c09923911fe0ff6918b7c7702a91762aede2c2cdd0f1f0bdcf7b9f2a5a04303235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d647c6fd4fc90d8ae0a3118849fd10e144a8bb3fcbbd5b54617b782667c7f8c5a89ca53c1f878cdc9dc1766f447ea30f": "0x269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d6551bb9732ee95a0588e7c3edff87bcef8d3f3e96613631bf0c63444db7abcc063f40cfcd2f4b477615443fb8e84d5f": "0x4ef63a0f97791221290fd19207cbb23ec5783221b5016afa55161b01dbb0125d04303139", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d6916cf16eb26f9d1c7af3577f43b00c367c5a125977696926fd9820f8282c73f7a2cc8fa0dff0f0153cd7519d6ff316": "0x20112dff656489548b0a7815a06d3a59f93880ea46ee2662a6439bb431bab04607736972697573", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d6a9f2d02150c4f45638b84b15be87b812c0e71c4aba6d53775e0a27ff00a6090b2d9bb4171096109a5aa2a59328df61": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033633", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d7c3b31efac1b9eedcf9c85fe247c820dc89c6865c029c1088fb27b41c1a715b0bb611b94e1d625fa0bb8a1294187454": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033335", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d7c748420ef9a4ddbad4b898d4a03a5df86ca83eaea9aace8ba08ee406a2ca470fb8d274a9fb496cac6e8797721c5977": "0x3ef88f51188ea054ff03b902d8706c6d9b1ea56c119b34e0b88e915b5d02da5d035f31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d7d29505a6326c67cf801741f043061f4cee1a8fd3bca977c086368843e54330002df861543497ac55e3818e4111cc26": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47712416c7068612043656e7461757269204362", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d7eae4b41a09c76f6187adc728d7c74b3ab6cfff71e91eea05d195a10fc0a03a78667a6ee5a915fcfbb25e90bc258f08": "0x2c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d41033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d8058cd6e8e400b8b686a6dded37ac508c65e884140b3bfc129cf21cb7423ea9f6a72246c273c3ca4c77a00910f58136": "0x5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47054b413035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d83f38b37d340f3c33fabe76bdeeac52b0eb1b93d4fb82e4fe4e55b4dd8375b8a09c97596db6bc7e080401f2b88a07e9": "0x88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d930cac322a8e3609661590a21692ba3ae47a2ee72d479b5ae8c2237b156a6c584d82884c37be50958ea32c1aaef7832": "0x7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a0530312d43", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d9393dc793396a1735689e9acf9fb238fc53b8a54a21149380351cadce380bcd0028cec8145c34fbb67db6176dbcd31c": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d81804763035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d9dd9d53e72d0e4a66b17379e58131ce6c736a063c16e476c5d534aedf7e9c95a40f13c95aceb085ef74155d4b37800b": "0x2e62b548856a9ff975d160a0df8219bd36a7807620ac1ae2eeeb34498ba3e4701264656967656e76656b746f722e696f2f32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2d9f6e3572a83d81ad6cadaa3c87a2d5272f67d9caa91e4c5777b9edbb0f7297d7f294627685c9af7eab3563ef66ffc20": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2da14c430f61b548473feed1d3e41218222caae65e7ded01a955d36299f613aa1636767c9944621bf5eb149290339b97b": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512393a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2da71dd7ef8ca0345c33322399ee10dc612c0e71d2a6032287a5bdb910afd1522f52f26c1d619395f3c8d1d18ed23c12b": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2daca255e05a7d5ca9895f01d07cc29fa7fd69aae09c52bef16685e25b29e22f3d1b43f6469f035a9081033b9a7025c94": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b04423132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db06bc4c90988ca9c276efca888bef2f720436c87f73ebfaadd5ff7748bac986ab74277d57e5b946066d922884a5d80d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db0bacaee235efe7f0fe598298761c3912c0e71cb40d9d91814a130bf4ee7008a6e83563520ad677eb2034209fa20e55": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db2588a557075ca073621e5d0b07a30d2c21eb7992f79d2d844f3006382236000c2b1eeb4c8985c6ed6db26734ec2e70": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed80540c6b6172757261706f6f6c30", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db6986be783dc3e2bb83f85d79155aedbb4e1d9efbe50d88f02dc608509ba4ef589646abb8dde69c9398738becc8cd48": "0x008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a074d454c4f4459", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db6d64cfec14a985d9c3e13fd71cf74f29c22701c5675f9a1d0c99c86c5bd43a5c781b5029d080077926cd3d3d17a81f": "0x8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa0234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2db8cc90b6fcf6061805fc0b2f6d2e0b68a650412c92229bf1a2eb1c0cab9c133d54c5b82cc723b202ee634e925effa6a": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dbcd9f73ac37913ba3bcf7ff82f93706882b91920f9e4483d2910d72403ecc9522283079ff6770b58be852648e008d44": "0xb4410d33f13c053dca87be657a0ae3cc87655baf43f7efdd454ff74e3a9d8a2f15f09f90b15374616b65204b697474656ef09f90b1", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dbf093212b4012e7da96293ddc06a4a09b1e47be56602b6fd57d873573f8e1cf67e97ee448fabff165be2cd9b7b6a777": "0xd2cfdfb80cb90a4a5826c98846a367489fd25d3a2561838fa372f39f3f7fb138033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dbf5ab9f73be1b226d58325b74e902f22e91e1aef05cb877f9c862b416d157a840115d43c307290dfba6ac4c4db5dad7": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc04960fa04dbf91bd6f0f6026404e62faca0437ebd16050e22dffe85c091c5a8e24feb20d488444e9b9e7e7cbc78013": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc27428bd38cd5acd3165a17711fa3ba1a765697eb319802107fc3eb312b686bc335cf4456be1c46d6482bba3e1eb038": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc2a961efcab146f4743645e32a5c866d06a4dfc33d452ca4fbf37fd660a153b0d87011761701591ed79e5bb87596044": "0xcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec47712416c7068612043656e7461757269204263", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc4913f0c56caae531361483b1d0c8ff8c21fb36ae0d9d838e3e635f7d867a4eb44fcedbfc8f3d03f22f342f2a64b38a": "0xa6659e4c3f22c2aa97d54a36e31ab57a617af62bd43ec62ed57077149206927000", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc5dfdba2a0510c456ef89f489bbc1a9b04789c005102f21fd271c09568a78047f581710323b5f91b7c2d5743011e128": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc60939087599aebe53acd8e5d4079d33e94cee09a8718b5957b697f388b7300815ae76c15d0ca5c0b0cefc84d5a7d4b": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dc91ac82f44cabc9de8a2c79d28d6f435e11390e1f7b87f6e2a59603d7979e4e26259c41f011eba0e6f3ed6996e7151d": "0x7a8b217ad8d80016336be124846210559ebf720aecd25ea0d0d11c10f1839e7105f09f9299", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dcb3dc43edbfd078f6047d712dfef49614b04bcc309f1abd5fae50084923f7d14fc5b9eaf257c0e2c5dafcd83e3cb363": "0x94339db8b404ea216d60433f00ed67b0cdcd9e29d21355615d967161db0cb04c033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dcbb8a73f2966312f90b7a816f27dbddda5484b32d12a09f6c28114f2d9ef1a6cb2088cdd2c5d9be152737bbd165733f": "0x1e6ea78e3190ac2cfde9c0041ea7a0e1f7b89d52f4a58f01f69258150b782466033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dccf206125ed7e98f38e60fa95831a952860f5267cc37b8ac5cce7fc5e1e00aeff5c951ca71a7075e75e5be1136e8e3c": "0x4211b834beac4f35ff92e0dcbb0167f6ae7a0c43b186727d581d3f69f10fea3407484652203032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dcfd76fc380cb9ef8907144f5c27f7f5acabeb358e532ad64c9e4e9f5b3a2bef0358e8535cb4e1b8a7727cc24b7be643": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073034f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dcff612df642a86df4851fe810a4e808594e4ff12db88b9c74fecc23b4a9bb35e999a5c9a6424ec47f3e0f5529fb655e": "0x1c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea2593856090239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd00eb692e2e60a5edb02bda27491782c573b977a12a27f38f686571c67e01b848e24b49fb2ce07b8b0f12caf651b6ee": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212073031f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd3906cb7799120e9220dca4276cc62a6268664daaa26e11b1691bbada389dcefe14898f05214f50027c797d8004f777": "0xbc486ed2f394da6e6b58b130687b48d3d19f756ba6d0655d37bf58ff0f59f97411474f5645524e414e43452050524f5859", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd3b705c6ff3a2e644c15c6158e2a27500e31d15b9166c5238cbdfbcab39ccc2fe0173c9419b060f28fbf3f0ea0cf25b": "0x1097c82198eca584e8d9bedca6a5ffc1f1eac3c1fb91d0ef4ef313b842b04c3f0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd41ba720188814261874148a590262616a025114b9898b0e78a9472f31364689261cfcb35daf692c62f36012706db19": "0x1eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843117374616b652d636f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd66630c8a9f37422bf4f2e1de7853f55627b276d86cb8de65eb9b261907a0134f1eeca33e423eb357ed4cc339e68d1d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd7049f241e097e2e14377b9f0d1471fec46a834c9d9bad9de24c9d4c6c85d4f942e2c52134f408e7fef2381bcdf2dc2": "0x983c5a0d1f1e697c1a0f9798bc25543603751b41102d41c3b0e23cbc6e3fdc0b0f566978656c6c6f5f4b534d5f4949", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd7649b3c6fd3940e5c3f07a003847b220d879dee526c91e9a590785b4982690fc4a04d41fb7e49c83389e6848132b0d": "0x6883b9f834076b9c1368e7692ec0a01ae97a52c5cdca957b5d31103423cfbe45044b5631", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dd8a2891c55851c6d5b09185a589a015c40595c253aabacb254a3a476c0ed1b1fdc9368157d2e6d85dc38f5eddddf13f": "0x945e90a1afc83f0c74a3ffe96b40c4ebb5397af04126bc2db23036c043be4a630232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dda664af553b017672bf40043090e510bcf4933936ffd18b5b65409bdc003b5f5ad8f9b8e36ae97b1f7b5f0af2803bd8": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2de19609c2b633823780967a99f09eece10a89404fc6e546945ce58e433c4e88a17167caf4e763793cd3b048e4b0b5940": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07105041594f555420424f5420f09fa496", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2de251e40f881f9217c2e38706e3af7ac12c0e71cae4be30aa91dc1e77bf2bde98af86c4d385e9c0868d8af4a50258803": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033939", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2de981500a43f4da9e8719948e3d7565e5092144ba4cf9a4997c6dcae1ec2f9b8cd1065ff5d1f97812c5700132036a504": "0x6849627c337067117e864eff154c6125539fa6e4eaa980712e7594cf78447874033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ded01e74365e3760e06036ae1c43d2317c7c8105064a32c52de4d09d9b9dc358756f37ccae41c1ae71178ce302ff5374": "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b75709487964726f67656e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ded4e227d37f3edb020a97a214ae2e0a46105c0b02b08c1a4e094e2bbc42fab06c13cdd155bff92dd844d3bd727f2612": "0xa61514d5cabf81b3f62650806870ad83b2e5059538b846b6dd9963e010566a170c7765623334657665722d32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2df4f39598dce850aaaf9166114fb0bfaa6359df267482f0eb4004f12f3189cc44d1e70441ecfcbc1a2d5c6c32066003b": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2df546ef0648729181d0afdc326b51a3c1e25c43583448b07d9e3ff3a2c67c1674ebc968258e42ac4ac000204f6298774": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2dfec92e6b1ceb2162f6b90e6c1e58c1d6c4d3e81cd1909e980648a1d2b7820cc93eafdf0151002f481c0b874502db473": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e00c261c706fa106c6b2fe14b24e0f857e581640cd7c61c76dc4b85b771ce496d10e52429113f8e7629425ad9787c81c": "0xe659339aaaf44f9871d9a42595bece9cc446cc4dc321dcb30c798332a57808460554555a32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e08e603289d76e449e3961b2c9ab6ba4b2fde580d330e81fd2b163a77bf1797f3fd19e98099fec1bbe33217c7f18b77d": "0x366c1d734b33c714b0e0e9f164426e66e3bfa97b917b23e5d3674f4a2074f86f0220", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0b3f181c5a9a05fa98a63930a7207a1009ea4dab5c62d5da4b72e17b5ee5932a3098fa728b996bc7ed07f112702d32f": "0x5a7aaed28c23b0b10d2fc6a0a914c93ce965749d67d7f657facb010255e4852e0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0dc322e86d29e3b50cfb38e35ea5a7f90549dacdddd5bba278515f623f95197c97a6a7793e1e350c7492a9436e4a90d": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033737", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0e6ac01103ed2c064932499ba7b8198623ad4601b91806226421ebcc2af8a4e60b4292b52e9fa8bc1c57131da504800": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0e84d0ccf8d91b0701dc235514ccf4f40ffc76cc196faba27d81c0c8925911628bea264b949bff7a26edc041bfce66a": "0xfef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db61033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0ed24a7b6ecc44c7eb0d7c0d32ecde38cc54beb3db37569467a12154f037da2f6d859d11b72db7cc8f615c7456bc923": "0xbee287e579da5137412f2c3bd4d5ae4c6a11c4c420e04261157e04842a2ea641085a676162696361", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e0f6b4abe0f57172867aaec554a3a4177a1b5cf762b0c34865a94bbfb0382ecf0cb030a97e582c4f219c51441ec0b805": "0x6e8a3622a7355ab70892bc48236c461076d5163f55309b7e5d0a459d17c6272a0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e155932771905a9da18ab702614d5a4a46911250513cf4880a89dd8ee3e32cd8363d0f3a064767a4fd19635f2605475e": "0x74c76b2bb6e2e4b16fec1849aefadeae913aed26e72e2101a4dc34abb3e40776036b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e164b11dafd4eb203991a45bdece3cc26cd8d0f1e2161523b73cdde28b857e8d4c281ee0825d88c3658675561a2bda1d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e1cbf7f00da6e53c3249ca49ea77889d62832dca982c4883b26bc9eb5f5af530535e7d216400578738ef04ef0871de73": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313530", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e279f183c3fa7038c796be0ca5053141c0c6960f5ed4ae55f47327fec246d858b57f0d4baafbb54920e0bd47e1dd721e": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e2e0559b320cef9a9e04c60fd88d7ba088bc16ce9ffb289186e900a2c7bafd486c3ac4c2c612497a5bf14f8aa2dcdb09": "0xa0d32bc7ae5d421990bdb847fc38cade9b388ce8138ab4e4ae957fc7ca59bd2c05e29e9556", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e2ea2c505786b366b22eda70f336ba33ce52792eba24d1a81f5979865ac647e16fa810d48fa38b2840de291115171e06": "0x76f45a1045fe47a639befe802be7eeea599080222e2f45fba46492039609cc0706426c61636b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e2eebedecb077f136805ee88eeef2b7eccba4ab664396955d9309b5ddad39f02b7cbbf76743a9e8969949c3e8a2f5ea4": "0xc85cebb3f21b5e97737a7bbc14d8376a79dbba9c2849a28edae77c776d1e4a080232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e3340acd351f61644d02973d5b0808a7c234c72214c38e8cb025a2b0995370d26b4113bec935efcedeca89dd30d21275": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31365d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e35c3408f4c500c4263624ed16c2c6f5545513938fda2f111c89660c78998fe45547148b9c2c0891f28ccadc27313a45": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033531", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e36f6a57fe303b9ac571b4f4e279cdb5600456bf4a3edc3d8ce8fc483ea6b102c620264661f24c3f33b4b41ca8e54450": "0x8e06bfc989509d6d625c085209adb405867bdbe4f167ded7e61ec126c683165d10416c7a796d6f6c6f676973742d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e38aa8146872f9e132f103cbded76a490ed01c71965026d33ac38506cc0590b2ceceaf2a3cd648e16e0a1d4c10542671": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313437", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e3f641554b5597f917be4084dae6e274d44824ac8d1edecca67639ca74d208bd2044a10e67c9677e288080191e3fec13": "0x68170716ab7c6735dd0a1012045d9ea33891b5f6596cf97eb217d0962d86a51809706f6c6b61646f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e456d7ddc7cc8e5a24e70581b204c85b2ad8cd53e45f24d5e7c2cacb60dfc3a4dc6260682150104828e62d3a0142c008": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763234", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e4941e79c2fc14646d53947055a43a6a5ef2424315d83ff1d4199b1151f91ad9c0e89306512b02f846f7acf17f00da67": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e4a9e83f16a2f3f9536fa0267e9daf3212c0e71d210ce61c449fc8f5f3f521209d2906e445239a938303741301d0ef7c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e4ba00cd633b8e3fa3f5623f69e02de848636a9fc435413c12d7c7524f6c12110ff15938dff2da4dd92cbc87696c721a": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033337", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e4e966dbda21853ec16ee4d348d8d3fa62be3477b75e8497245a053f1f51f752421fb039f6bfe04a397e85be7e193440": "0xface99d3401cb9b45ee1bc0ec52f4cb35914dc5ad27806230534230eedb8413d0546756e31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e4eb707c294c16066f750a1ba2d16fb34a1123e20cbc903262ef39136378a2528eb7382d3b598cd240af1a965f402662": "0x8a65f2773ad69cccedc0a58ef7ebd2d446b882231b4b97044105b2035a8d95460232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e50d77c8ee8e0ca85e7832a42a57c8cb989aa1bd13df5939cb65518a399c66800e3b23e792592f94ba7af30597d7fd71": "0xe4269547e0e9a8c162de9215bd45921be44dfb58ec95d2f627990d51890014400231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e51ce0489d80aacb5ac38f204dead12c740cfb483a7e7c4d04abc9fc3651beeaea5633eed75f65c0380d424312412357": "0xd8783497b4c06f05dfa6ca91a0502e77ea7ffbc5c33c7142a5d9d1f0322d783b0853504152544132", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e53ec219e68dec0b35fe17cf965f90a7a6148a5ba31e548196ff678386e2c8792fb3bea265b6c2475e62eab64254946e": "0x18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc00190238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e54e0729b8b63fc4fa13f0e6fc628f08808652b2296e43e858df65b69d5a3942ba76744dd8d0cf390ecdefc89b3a553b": "0xe4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f721170617468726f636b6e6574776f726b32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e5a91996fdb6ad1366a1d9c10f5cbe533cdf73c789cb02811fadd2fc2fad69647e6a22e18ff3b20c03cb9ed07ca0e69e": "0x2c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d4104303163", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e5af5fbc22b8e32f770ff1429ca33d395e26900b9067da461527acdd9856b0934eef5f0c099a2acdce01b51f02be2351": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e5b3c8937ab058e906ccfc60b0908667dc226375dedb131cbc73b5c90ea8d374d5d4b5e75dae7eb6a9a4c215d8e9b0ad": "0x98edcae85e6eef98ba192a51fa0efd89aac0541fa264d46adc9d8f29d3e2104704303138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e5b64404ab43ee7cbcbe85ff6f5d5b65ec496735eca64ceabe80e911ddbad8c072ac5b69d3d88ed8dada02a9cf5c66c8": "0x4c042cc1451781f79ff3bc34cacd5329b21591b2b2d82ad57426a5079ad1c45508f09f8eafefb88f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e5e92887f1972bd9979c363bd2d8653ad21bad21a85a2c91d823216610c964d9fef7dddff9f1864b2a7b4a8e667c1f53": "0x3284bc8ce3083b62e671d1c5bd61db5b3fea95a77967341ca8834a69cffcfd5f0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e623a56518f78c9028775cc55f65c190ec194255613dc072122c8330dc7c18e15b12e5eb3093a442224e91e50cba7d3d": "0xc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed805406f09f988839", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e63b7a685f63670a81a262fcfbd9fbd2eaa00abd5e6449dd46d8882c6024f26cb5247d26becbfbb4f57314d342b96a65": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033734", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e658ef02e990b8c30f8da6914cbd955f0119766bce9e7ccb7adf4b74870a29b352995478848ad500f46166c797f1c326": "0x083f39607241c8ebb62919ab2ed816cb6b20c7d0abad78a92570030d2f96c63c033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e65b73e2c0faf462b8528f4a507cc9f8148abf367d1fcc88ac026490727eccbeb507e35714b327c4a3dbe404622184b2": "0x1a8ab26aba64d6176b6aa462a2a7ef6252ca1063cf978dcb6f6c64fec81e7861074534592d3032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e65b7dbc9946c336efe1a3714adc5c139068a88ce95e5c34122578c16d46855386229be241a7e0656ef469a03db4ee19": "0x12d49078cd721faa2f041d0cf96e0d8194561fdcb4ced457270e52f209e76c0f0b37363666373436353732", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e6641af3b6641795527ce31eeed557dd12c0e71d46088235059834f57282e18f93197b164a04be4082b6dfd88d86f531": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e748d98bf8b780c7f223b13fb6222c5612c0e71cbe21aa863d666ff694ca4aa3a1f0e89a9e75ffcdb6c629fa1d006460": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033937", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e7555fb4759ac62feda8f76622333aa7922988e0c062661a2af3df12782ee38f6df030390d1874d113bb8a53c165f147": "0x269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e7589bc127b541c9356d09774bf0653a2c34b3c3d2a9e4c126b3e6152b8ceeeb75c43d7530aa56ca6f41de5a5e76a270": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523438", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e76b9a352f58af1eff362b8764392433187f07072543de8fe520037e115acbdb9b9ab6a321be237e39e67ca4ee979749": "0x12bf9efdc9e4e25b4dd72c560029152b6546ba2fb62eca400d7edee7e5f36b5a0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e78077f817c4c582219bdfe28f1e7d7e2e8036bee650826ea445368d4643b0ad2341924bb357c8ee1596fd1235ecf326": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e789267e130c5ec1992e7b2300146bdbccc10f47daf388814d58209cad72e4c07dd9131ffb7b2b909d39746577a97178": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e79245080d82d693b3d098f207b3efafd5febe9f9f424e1a509cadb2ccd2f502fa1e9b577c03bfcdf74f7e6abe6f692c": "0x02b47d21483aa953be67636583cb184f55d575e0f71ec75f45383a786324a64b055a524831", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e794c096ddccbd0c284049c16597e94a88c83f9b6b21778914870c7fd18ce9b3b44831ca8706611d6b2fec736a5ecc4e": "0x5cce1eed57740222d643b9c92a594bec58f9b9968bfd4d63d495a7fe5237ab1e094849524953482032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e83fd59e7b41f06d890f542016d8d5f75ad5faadcc4848cc8acadadf39c4a9893e13e8993e270364eba8ce53b8374c6f": "0xd4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b46011f09f8d80204b534d20303920f09f8d80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e84ddd98e3af983e752fcd3aee367351fe3aa3a8b8e0e17a72626db79dd999dd5e9cecb8e0f265391e5daae3ec229d3c": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d154156454e5441444f5220434f4e54524f4c4c4552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e855f21c0bc68c9fd5e477dadbd5b2eab22f3abb5bafd42556aaae871a79acac48e9b874703cedb7f8f5ce219860ae08": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e8745646068bdb0edac7096adc4803d597a214d9d7e4d9756f50d6b43a18a8ee671cb1512b46f2c2c8c1309694dc75bf": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b06415341524f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e8ac56067099b665e2ce074b028d38a586d6e47051058a73623a0abe221e2cdf86a362a3da910618be17cbe3629eaf31": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216064561736f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e8f202e282deaeb09e361328a01c8e1cbd65fafff9dc200e3945e786ca92ba36a9aa333b09bb500b632e8827f8f7ab38": "0xa49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e094b534d2056414c32", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e8f875b461cf418f5973a82da0aac2212f9c09c8a70b63d73be60dfe13947a17839970667250b900c8560ed4d042841d": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e958ff3b911d721acbddcf612e892996b89b1a8c5532845c171dcfc78c4bd5c42c634e7d6548d6646c83fdc25bd4737b": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523538", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e96d7ea11d81f95d0428a125ac69d5d6225ad9907fd7a3f7f3633f2251c3b390b338385358f1753ce35bd27328c7fdd1": "0x68f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb9607033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e96ecd9a7d9777c34414149982f444e3801df817f435be03321e6a77b0fab3183b9716117accc0f3db95c9f6f9434954": "0x9a2cb674ea2f4866664769a1663fd6aa321d9cfb89b67c402c881891700c0f57104d757272617920526f746862617264", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e9b53625b2ec22da0d66ee96aed6c8a9fc036538dd0a7335685f0b7f62f6745658ff16bc2d61a8830e70dad3e1749355": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033837", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e9c29fa4d8f011d919e8b0aa24ca376f687a846146ca3cae0d51993c0e186d6026b2134ca05e213562c0141a85b4ef5c": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033430", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e9dba064d1e0741d4b5e37a05f52e1c046a4204de252ad6bb8587604684eb6b0d8d7c5f9f8e7ca0132bcdc6d53131e47": "0x04c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b3568064354524c31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2e9f3f3edd998aec1842b1673a32cb65d16c4a4dfdd6c04572aa9c3fbbce888451c65cb1a1c96f611aa638e609cb6f609": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033532", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ea29bc2f13063ab1c9c07534875dbc8d40619a9305b0571ee5a5666073612190b2035be70b6846a2f16c94e29908d389": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083230f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ea3cedd2f091ff1f1d5ddefad7fe2d8fac11ec66576b8d0a1c924596e74f3b45c61c7408e1680e16b4e365ddb4b93f56": "0x729f8acbb64cb60b5edb62beadc9ac05430ede0086e29800ee32d106befc78250231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eaa90e48b9a7dd48967a015150804612d85561d4ee89c473f4220a4a5ca0c8eaeb01fe8d0740aed291ad796d4b2da175": "0xb08b555a5a3b2725e01ba15eb40aa32dc5b781532854b797808ed45e752b047c0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eaab2b4e0025425dd7049c8429770856c63d0c9d2b2f1b51dee3c65bb2714871c2913cf646efe3c775d5cfefd4e1bd89": "0x16eaf9666bd95a04bc6ed619c30a4809a43fd7265e414284c11b27b8c666fd23034b33", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eab688ffc102f64125630a3c861323e9048bc4da5e4289eeb52244056c70c535f165d37ad921c08b9d00466a1fbfe442": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31315d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eacc1ece31019fbf6408ccea0dfa084d12c0e71d25d4ac0ea242b6e44fc9625e1a4dcfe17e6cf9dfdc0bb233ec589556": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eaf55c9b1b5c07116f73c13edcaa29869eb6835f83b4313045b2a156d5af104e172dc687b2bd07554ff3699748c41050": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eafc1348fe1623ea22d24055452df792d2c2f040d9b3546eee26f30efecb97e72fdaddea5d4999845b37742841e95f57": "0x240cc50e90684f175ebef583b904fbc0b9aef4b38aaafd53e6436ad3e70ba3660b496e2074686520736b79", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eb3072732122ad64b038c799d470f71c4409776e3d248cea53e8d6fce41bc1795b83793fe794119a63b82a7e837e9f59": "0xe683743954d0cb555a54ab21cfb8161f74e689a051d1ac1dbbb94df70be3d81e04474f56", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eb5b956e59f0279c2a89a00f1a78eea9bad66ea053eac162ae6fa88c672a16dc18d932399e7159d0e2ef25c62189e637": "0x3d6d2d20735ec00c7753d3e6071ad1e2280288a98d7d89c2a2b7fe08bf6d05bd0641726a616e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ec26a61f6e5d8383858d0a1eafaf930a9e745f85a1a8ed92e237063f3ba463c198d7744b7698e0e0a9a12c5966d798c8": "0x88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ec4fe475d73cbb6bd5e7e5afecb01039c0266f91841edb77e30346c6da3975b5c3ffce4a2b1ddeb696527bcc0279f3ce": "0xcca2a0719fad006090aad6536ca8b7d8c527589be01b0012564dbdd36d9a492305f09f8c9a", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eca8cbe6e1a53559e1f36828c7644781f87441058c9c1d89f27cd68a74ced729f5393936f7c041de6732df7217d17cfc": "0x548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b074e504f4f4c53", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eca8e087b9c31caf6b65683abd4243337cca5de8c58ec8fd1a269c3e51acf6ad45a8b9b32e4a65a4d4c481c5c449d826": "0x2a807fc9b3748a0d6b964bff11360e00040fb5fc569a9595532f935286a45f47037632", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ecb59c824a063fa221530b13ea4793e99a9868ff02ab61c9603e98eaf9560a864870596f58a7144203636bef6d04e269": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ed7626002652026efc7173f5149ce3a5aec16460ec51be05e01406f39af4e8adc9d400e511cac7aebc10c31d42540f46": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db196270238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ed845b33e774e62f877fb9bec62ac9085b485a5d58748bfe83392a1ade902a02c95084c00df2070dc8f32f13ad499e1f": "0x0c841e6aea307d8704d5b7b7b71afad58548ce47dce090e25d01b84925e5c48d0f43686f636f6c6174652043616b65", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2edbd4867a11999b712c3889ac4cf711276ad7b338e915c739fa6055381d937bd4541d12ca755533161da8611aceca14f": "0xd8876695e0680719107b9ccb595ad5d8bfdc4ccc8e8e4656091fcfe652c0f1550a564c4144494d495232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2edfa6613fca1f3a39cb95daf9098547038cd946bf9de9d576d29db5fc442e5078a03f73b67ba76d8717634b7be4c5a23": "0x8c33b686a457b74f9b1a61b4446404e522d122064d6713ffacee88bfa9a158610f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ee06f0566e3a2fcac576e9bf84a239110a750504f5da1835d98bf849ebc018742d544c86edbcab2525a8acc2178fed59": "0x4e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006054b563031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ee1bd3f0eb1dc3033e9f4c7f4c9b3e29cadcba686c8bd7b8579cacb9e1233fee5eba81db5e7c25328b724198bc499b2b": "0x0277ce02b2ac78ceeb9ae4fa0a595005489bf3f5f77898415e32a3e9504a53141e546578617320426c6f636b636861696e20436f6e74726f6c6c65722032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ee51c0467906f0399b711fe5128cb7ee12c0e71ccf0639294d8ecb643d6dad93d9660836463f91d1b66292fd9b1ab05f": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033836", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ee5aa3cff49e0a798d42c3a4edc2b45bf826721deb8c5d5f99d57fab56da2e28286fb7ad92f148b05d1aa353fea2b26a": "0x86b7409a11700afb027924cb40fa43889d98709ea35319d48fea85dd35004e6405f09f94a5", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eecadf8dfe8dba8d2e7c5557ebdeea0b96043b3a00f3e936328165ca3f780b594dc2ff0d9e72659a9e13ad74c3bdad4b": "0x4ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ef2e11f785c26f6ded26c3139eac5be7506014a02fa72b89b1b4ce899d40e369b2ab4d06fc1ead4663c856bae3d9db60": "0x56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b1150b494e4449474f204f4e45", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ef60985c2bf366da5782cb9287150873964d882bb6127e75f8c02efdefbf052be0c010256c41d832e8c81fae632dec75": "0x76e282d7a7eef593fe7a9a8c5d08a21f134e8858e1b1753bf347057c4db9b23404303336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ef72750a5dbb1f175ecf94f7254cf8da53b9577bbf862a61bfd4c7302c3a43bd26a9b50370e3cb6586c8e267c1b87180": "0x58f26dd10efac24a7fd1813d6aa72a8e60bee976f7da28e492ad033fc18223150230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2eff63fd37d1b282f7824ce8d27c457b5ea4565b84bbc645ba42d3ce16887c42062314fe6aca7ab36a1fd942d7f31c76d": "0xc088a8a35f9a31008c7ac0d4103078bb14b3d50213e4b92bf03ea98c081f173c04303036", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f008e8cb26020bde50d4f0b553b1a67093bd14a518853f72f3deb5357ee12fdd6e77151580b082bd468bca1358250d2e": "0x96f7daa1a00790f8b168d3db7f0175e5f8dfd3430dc7edb4c5b807bce2b9d93a076b75732d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f0094ef8d1df177a8d33417bd36a38e93e4f57a212fd4403b083d956909c66b8e492e24c48095c3681a5a28208803744": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c0bf09f908b205748414c45", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f02caa348f4c67075fec728c3413c5677afc36665eb89509814350a32bc136f095dc1c9224dac890c0112b5f4b53ac6c": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f0550d244d630c7356199c24d2f56fe812c0e71d10a91f1a202191134bc06e790e98829eb7d76881e3c8b42dbe8a6d41": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f09d6c2a2016877c4728ec370a211b47feb86644e89b8c9daf871b44f7111264cc15bfd8efa38a255124412b9bcc5869": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f0bf2c785c3e07b3e53a9fce2530b727deb6ff39e56549c7a265ac798934d66b541c41c2e2212c34bd76b29635b4cd23": "0xfef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db610554697073", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f10c646f0d99a97e06f60f9e098d413d831b9437615fae78c29e32df5b9ca228b4e9b4b31eccc8c090834cf6a85c8e29": "0x32068fb3b800c5df40df16619761b3418e40d9455784b6a293d2425e35ef2c27065354415348", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f11a108af7a78573dd904944eb3de78c3e586d68dad3baa2426853204a502f7476c280a7cc3bcc4f25bc4bfa3e121601": "0xa43b2797bd4dd454d7fb0870a2a4edd62b39eea0801f6baaf09b05c8634b5a250233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f13d95baae246a1e8d55a2507dfe207e88624098732487bb9f92045e3d405bd1b7f9432dbd705c3ba58c5e86d1353c69": "0x8c20d46f86242eea89c400d5c478207e05c76bbab29a748af8aac90d627e1a010243", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f1c9ce061a86af07f6a818c8734f14fed8c68f5ee90ef5d4f3a2b0d3e827b6b52d6d42c66f0789546e7672128891df61": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f1fb7eb39a9d8c38c4afdc44ae906bb73481012d5c43235dd891fea6f46c4745b4c6f9ae37e756f7da67f6af35831a23": "0x3ecdb909643a31da23e3dec041ef8920632ec16fc5157297084eda7515badf68033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f237d4da327376ccc05b307e2369972b26053f965308328e14c097fbfc2b09b6b97256bd6a14ca1459ff9c1e8dec3556": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f23ced154c515cc7381ba21c5a71a2ff54416d87ef2183c6d1c383b29dd10f002272468fc70cdbddd42b5093425e5422": "0xc0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b033230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f23f3b7febcdb548f3145cde9c1a0e9112c0e71d364ec914b6b740ad7c055dbd9a15aa2cdf4f6b3349970e15b6b73e01": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033137", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f292f07891bc9729fb879d675866f7f98e4ac154f73a0576603db7786e98d6a1db1e72e3a2b32d2540828395dbd3f7d7": "0x2ca8e96b721f074e95a3f7d994c370dab688fc85134de7e2e7d4589d0a306c51033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f29930ae86e28dadad8b3f03c93d00962d14410d4bb33f09014a028cdbb9d2c2f00e7d5021748ac859c5dc11cc277a6f": "0x02b47d21483aa953be67636583cb184f55d575e0f71ec75f45383a786324a64b0548454c31", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f2b50261383f32267afd11d1441702149a3bd9c292ba18b98cdfeddc8e45fc0a4eb962baa86c5d839ff3e433de19944a": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f2cc70fbe35d96dcb882f5452b71816412c0e71c712fc750ea7987ebc3adbf181c53f54133d3378fa5d7268bace38a05": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033336", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f2ccf65413283ccc5fe7be230377dff776497a6036a1ef7d02ede96d44f39094a5fd50e69d524990946cf5e6e6f1da2c": "0x22a58635dd1a211d33750333282985df00d84e87b160293d6b39e89ea4bc7d670b414e4f5645524e4f4445", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f2cfff95d1e91cb6647ce16c34f693f8e4f351785e2ba01d8ae8c408b0112af93577eaf7487d1ad4cfb54285c88dbf1b": "0x9642d0db9f3b301b44df74b63b0b930011e3f52154c5ca24b4dc67b3c7322f150573756233", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f39cf3feea5583006ba1636f26099b471adfba8c2b21414451ce19bd06d2e9ab7541214eb3285ae73da678a755432237": "0xdcf2917d37c64e3d60416e47b5185b4d6c3965ca531ecbe29e1d2cf759f5f871033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3c2ea1f45b4f32b0ef74fc35e1e741a847074f1fb351eaa06337823c68f2a9fb28c98db976bc5cc16867e4b84bc1060": "0x9e826b5434525d00c118f3f6b0a29b7f432be7bbd18659d472c5f07298e769490a7068696c6f74696d6f", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3c8018203bea6b4195eddc135d90047164f70bb86b671d46c1748f38329f50db8fc5461a4ba4dbbfaca7a47bd063962": "0xfe6c31fcff28694469c3d4c1681270bdacf6edf7ec39bda6c68cf25738268b79033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3db22b473c2869c1572520aa5e1e3f4dab0125fdf270b1af39164693d9bb3251d63b78742a99693632359e0dc6c4882": "0x36b5dcb29928d8a462f493e0250e895158fc4fc54eb5d00a2a6701fe36a4283d0d5069636f6e62656c6c6f2032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3e73875249d17f518bc605addbf0c8212c0e71cd7c05aaf2bd4ceaaeddad56e206f8b7be033b915ca7e8391aaa56a0e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033330", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3ef16462d5d6cf08146deeaad6c6a1558b16e3eabd2cb50029bde70c7a7ec0123d1e710bbf45322f50be3f21ebf8747": "0xe295650fdd71d7046633b1fafd0881a3207719c573f17725fccddf854a8b562805776f726b", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f3f6ab2f877ec353024b0d4a581ec9b69e66677d3f5f4ac376d14bf73bc819845156f1f25ce9e6930fd096741276ed67": "0x1a95c3968b83520b8e43f82edb0f050b1ce7281873a93bf9c0798efd50f5c41a0654616e6973", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f45a148fa03b9a5ce97e26b45105f0e79801bdf93fc1d4b0186e1295d517b03a5749b90c94a5468d74331a6ff529a953": "0xd60cf655685824e9966b0a10c01dc8b17b37e24944fdd760e4dd73ff1dd4ac1404626973", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f471887a1bcebb9ed9456d6694672c5412c0e71c92f12577507a7ceef4da940099fd984e976858d6d4c6826ff76e2544": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f4b2b50539776257271de63e3d55aeeee8b27a414bbf2ca10db6202c922e1d33359b65c8d4967fc76f926d93f54dd916": "0x5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b0237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f4d460a7cf7347eecf1ea2331620d3561024e48276b150fbff7c44baddfce92ba5d90057d518d3b29bcfaa421c13ab7b": "0xe4e00e63c3647fc8c0a3d1b163ac988b6f0a7c3d05a01e209d4adef8e285037b0942696b6572346231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f50b6a6dd76109679dbe380f073a1fba09f7f25aee06632399bd9de5e4a311cfbd1846ecc34f8abc3bb8118a45c98a2e": "0x0a439f839504ef07c5cf8daf62beb17546e808ed1026c8a683be8207245f300f0b5374616b696e672d3031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f50cca20f59770811debd1119a649b719ca08cd9b7fdd71d23d3a07906fac5a51b77c703f290adb2b5099b4334407913": "0x4a003aeae28534daddcc861d7d3e91b576683544217044cefcf4803ced1fbc690232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f54df87c5f1f17edf050018f5d0f6e3d72ae12a9ae7729206f6988826c71f0f3076971462d1ac94efff198392464a657": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f563f9de25dcf55912a6f06a528d5fa774fb773cd20d9adffcfc49a58d0ed20bf5baf645cd37aaaf65408f56ffe22116": "0x4eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d164d55524349454c41474f20434f4e54524f4c4c4552", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f58d058c15c34128c960f33402556779649bd677aa43958fdeedca2f9159ce5de8d5a278c08e73c4ab9a713a24d0d47f": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e15205b365d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f5d4af8d3aac1dc12cb3b4e57ea6d654280774e8e4e6118ffded6250a1b6b1a50285b5a61cf184e19a2bc8e8de880858": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313138", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f5ee7dd57b2155ec96f49d1c5d1dde5842091485cb911996df13bf18b2ced631569a74c5e43790f285fa4ec64142d503": "0x08a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f0531426f74", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f61a062242c9ec1639214545821d86e18c6d54d22c18c9072a83594d805c1a6c4a06940528eac4c3cd44359dcf9aee4a": "0xd82318297ca7af51ac2546ea6bd24acca272e1627db952e2ca35df527a3cf2570232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f69833f1ae9dbbb00dae666f139773905009e192ec169788c9c1f0202fe7c2bc79405ff8b6e1d1ac78fd6152006e606d": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c08e29b93434f5245", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f69e7ce6dbcee801e749a85956c602a240e877da5560adb4bb476e067659f4446675875a5e49cac2d3a4ad207adf450a": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae480230", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f6dec04f83b8e2ffe18956dcfe64f2db1a232a8dc0c50a8faa639ed22d11410c00f5b812bd14ffa6f3f554d8edad4172": "0x7c7d2fe83c4af79c49136f0f8c5f1a00cd8d0aa91c94fe74d0145cb96d688f66032334", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f6f510eadad5c8c77ed6d38c1698e558568538b172c522826347235dd841d08c6512bbddf1fcf91a10c9bb9542b75ca3": "0xc2a82d0740d343bbcf853665019f2afe81ddeb884f76dbb5c74533610f72a7321b32202d20747769747465722e636f6d2f706f6c6b616c75636b79", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f70d1ff9a047126addaba5bc180f653e0cb8ca7ceac36a246a8295a56068d2b532fa2c61affbb34bc5a80777d91f1805": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033635", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f72913cfcdc0d34c9abb281c5ac246c3ea08268d10b6dd05b9db75c7b7abc2b95e9b24d47f7b2a6147a56dcc745a0b4f": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033034", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7802b4b06fccbf0ccd56f8111fff98a24177bf6f8ef353988a83494a9fd6a8ed1f89ce97daba4d8448c48035b646960": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f789f222c0c713b56e093e473a22562d12c0e71d466c86c2834663f4edc4bf268a2746f02da7a7334344582db793062b": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7a6e9656603ab873c94abe3d3da7ffc68851551f073cdbb09116a1e5b1500042b1376b440f967b0ff961df638fae867": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033236", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7ce288025bd4a563fa7c6828507dff3d8ccc709448e61b19bc01bbe3be7d7e74c2303883ac6d06c19393f9c1140840f": "0x78baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee0705504f4f4c", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7cf5ede6a33615ed553efc37660a1969e98a7c353052e4ff27d50ee1dea0f7379ccdbdaad823c457b755413243e967f": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680d424c41434b4d4952524f5239", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7d6185d74423b52fb1014da109a710f93ec952a9328c2f39b697aa00f57f01c289423ac2068f506ce2165be10f1ec45": "0xec7afe6fbfc9947fd177ed118016e403dbc14803a0432bfaf0337e3bbc3c820b04303031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f7e69d9b9b0db08ad3941a583e280b29b00533dede137ae3424e18ed36871d41e440bdf62952275f43c899e1837e3161": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313434", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f881b72e5735e0005018dd4da333c3d8eef86cb3454d5d2d17aceed4598209af5d3ec6a09cacc00bc88d86bba7f34645": "0x243612f0fc6c935d9ee0cbe21c453a83f58a9427054ccdc74966890ca57ca7190232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f8eacb151d14f713c6edc17cd546d26a12c0e71c648c0ea092b2481ad9657956548a531fa3a89a140d3d8f9359fce54b": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033936", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f92cf23fd7dffa81b32c1b18edcb1307de89b93418a2be5e997eebd4b815754518fc3b7db32b2c31bf97c8297f8ff752": "0xf6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a04763038", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f9361e34a3820d9663762bf72d872f77c0ffc934cf4bfe0fd0cbb0153cc1f8c1f784ae59bc53da0e1833056c63b157a2": "0x4284fa7c290fb6052b9437610cfb2e19b3b37081fc72140e444d5b57ca01924d033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f963679a580318063a9fcdd9ffcfeb131cc49a4b3adb82193695b2dc7507d28e72567060373e1e82206a0430005b694a": "0x56d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e16205b31305d20542e4d452f4b5553414d415f424f54", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f97972cd70c90172b59ac8f8bcc1956f12c0e71c6c063c135438f8997461cbe25e61d7569fe4c3f9f07db032f75a581c": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033434", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2f9895a23189b4bd5c7dc15f4354c2cb55c7c97a0165263b9287982692ec2845cdf8ea293108d3cf51f598b6e98da1f7d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523535", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fa174cfa8ec743e7fa1821b8f1c83320837cd9bff26ac28b84a814643ab00556d90e873a921633bab990cc75b5a06dea": "0xf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212083135f09f9a8020", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fa18806f4b64c61f196b040fb75212ad2ec6d11607a14dd26f32576e47831719d548c856ce4c188091790cd93ba82606": "0xdc86d7e1dba377a90f087a942c0c2777851b447a16af68cfac09c2e58ecf7e1d0242", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fa43c77ec1513d34e343507763368d2c5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00": "0x5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fb5e4582a7d7f848ef547ef35b4002c612c0e71cc202669b8b8f008fd88fc91048ddec2434e536b37adc066ae2d1653e": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033238", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fb6259e402d8e96835c54de5060ee57a6e5bea81107431deda89d3b05e7e1656354c48d0a5cb767851726ed359371f7d": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523131", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fb80f286c0d81ae630a5066a97174c07cd5f012106aaea7652374847b9658c8c300f0f0b26e484e99f7c1e3d32d83a10": "0x3a731ac0ae7375a2cce5b504484d91f1c49923b3425072e36e12b0afd5f2a8570530303130", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fb840883000e9e9bb33e817326b3704af4642a032339376577e3ff7f6d55a53fb6519c5a20633e30bea2bd4d2eac3a05": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033434", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fb8fda93c177343af72612720c0a4d885a3b1634ed187e0ff740fa52e33f2748d0e88a19cec4e5c185cb00408a89b605": "0xce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d680e424c41434b4d4952524f523539", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fbb99ba0c4a86dc67ca38c3071429e8406beb838b0ba3114b2d1342cf7011c397879da3fb4b4ffd4df534e6948d4913e": "0xac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f10640554525359", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fbe3ec6b6f209986f7c790b6f07f5b847493915ecb44badd479418bd0ef0f753952690f6ceeb421a0fe567edf2fdb228": "0xe26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04094175677362757267", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fbef333f49a8a69f97789d70bafe9bc34c69cc407f4deaec89a4090075f36639e151c616b8ed573e7e384ef7672d100b": "0xfc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216073131f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fc1b05f18f15932e1feafb89e827fe010879c078b9026ffc8f5b7ca4f1af1ff0f51c592958f24b43ea5433a34f0cac02": "0x4e4ac8070fea95496b63cdcb6987de88f63dc75a295eace6ce5079149169300c033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fc365be94c882e564b1276951858b44ebee52eddafc82ea6226864dcf0583e034f6510d2b390ed60129b6855fc020c06": "0x8c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c4927704313133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fc3963aac45292fd533f75fd86b2776712c0e71c6d383ed080fca5ac67242f4365fce824e3b989af1388d5a94f38b934": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033237", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fc7ba4593d07409b3f412f1bd282cdfc15ece2a3d6a57419d76a4a66bfb72185e128e3abdd1e13345052f43f21548a9c": "0x8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa0235", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fc85519bd52e95bf35dca96c087df9833159dccdbf4c37ba277b4becdae7ef002bd7ab17d62fc7419dd68967e41a358b": "0x6610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38033033", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd040f54cbd52461abd73a171fea85debd05066b950d256e451a29012b1fdd38e661516eeeb487d816bb2a65975baf01": "0x68f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb96070530312043", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd2d5105a0e18eace0917beab6a3c06106b430745802c7c8d5cb3537dde6dda1c74dd2251837c781be4e0aebfde8d673": "0xe8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e0c506f6f6c203220f09f9a80", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd53da24044e2cbb272f820421dcce934e6776c8d171ebb2e352ecd10eb75ae1403f00a4d76089ef92d9d598264ac841": "0xc8c0c1fb9bb3902b9e4790461bec2c33afa31c9a3b72a4e4ab6c050b4a284507033032", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd6768c7769684ca925e95e347e739f6f2382813004a234ea40eacc434ee04b04e52977a2907023a2d2cc44d46412057": "0xe6247d2909686256b09006b07e758ecc128364a926f1223ef04b38628a5a3a5e0231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd7743d42f937d08697eed3dc9a08054de670277a4ec31a0664f1d47eb01a7fc351952d63980ac1246ae1e6751f61504": "0xc229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a6512333a206e6f64616d61746963732e636f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fd8cbf55b87480eb57c660a1ee51397d742e6def792a15d4b2518cd2a957f9bb7f75525308355f9217a2df17a701128a": "0x4c4769cc1bf4774f19c7433e31a5b8cb686944cdd758e193d264410d4918b1200231", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fdf2c89d5d9107f1c6f7abf3c00afad2c2b18a21865fc3da2283153ebd44a5da61f33753f6f20eee1d8e41fcbaa0dc67": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033133", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fe336c580c0aac48f9675f6119359f3c74378a77c102cab0cc86d7fa5bd19668bd88c48b2abecf283d81eaf19b4ef464": "0x0a54e1448806b2c0cbdfd5da73198f12554bc972045fc9dd3f2e22b6c5a97c1d0f466f726b6c6573734e6174696f6e", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fe53b5e22298bed52eb973676ce36961a872a2b4f736ef9a7242e0a0d8e64d616ed4c2da9a103707e9ac7807a764292f": "0x8adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48033136", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fe781d2115a0c6d6e092f21df11130e6041edab68d8fa56e9c4845bb931beb45b2e457162753e65c440d11f83cc82871": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3333", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fe7e3f3f42b17a585445b3960246fa578a1e84fa7220a6f820ca42a6dbe689b545ba1def88a7f1bd98d7aa46a9ab742e": "0x48ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54033135", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fe8e5e0ff57af24f2fe84e128c33379f329a36786940b598924622428c95d5c41812d55b9ea2f091ad99b2fbc944331d": "0xaed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b430653462d3035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fef4b17e8881773f3a7026ed8252925b4e8b6fcf0dee98dcb0d710fab325fdc6b158964c7011e9a43be877bae760717f": "0x52e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818076c6b736d3035", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2fef90f8cfd2ad5246969d5211208d9bae6ba74e93df6c3e3cd1615c99708e867e1f3160e324fdcce53be8e3b733e663a": "0xd6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c25033031", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ff1bac2f77ddd9afa2671c7f8997439f983a3e49a6aef7637adde845d561274ddf1d66ce267c81b3b0bac979ff79106f": "0x9c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627033833", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ff8ef22db0199c20624fd641ce685a3d988740c0cb624d6228e22704f9dddd8a526775c81506cb9eab96d3be870d4a04": "0xdab8ba7a028d62fe9a5088e46acdbd2039f01abd8baa7c695d9377661c3d406d0232", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ff935b8d9b8b9bae1cec0a900aa2d3c812c0e71c83c45d50d2f831c6574ab25eabed7842fc69f51bba122c617531d725": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033435", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ffe13fd1e48e4594d33864de440f71acbe6ac75cc8c52d2d3b88dd29c0352b579f4891c52f76508269f2328fece4d07d": "0xa49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e0e4b534d2056414c312043544c52", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ffe84d61bd1090467d85b0393f73254340d1c7929a103e88681731f954862765bb66d96c36e22f82a35fe75cf7a72c20": "0x9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d2775513576869746e657920436f6e74726f6c6c6572", + "0x2aeddc77fe58c98d50bd37f1b90840f943a953ac082e08b6527ce262dbd4abf2ffe9d9c0d6db5ab5e0051a7533be77e012c0e71c65c6d73c4787dc93561ade71071ffc5d78756ba4f606fe91a6e34521": "0x12c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310033433", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e00216b615048534c12bf9efdc9e4e25b4dd72c560029152b6546ba2fb62eca400d7edee7e5f36b5a": "0x0000000000000000000000000000000004187f07072543de8fe520037e115acbdb9b9ab6a321be237e39e67ca4ee979749", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e00ba2794d92fc826e4269547e0e9a8c162de9215bd45921be44dfb58ec95d2f627990d5189001440": "0x0000000000000000000000000000000004989aa1bd13df5939cb65518a399c66800e3b23e792592f94ba7af30597d7fd71", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e01dba54cb1c92c2856aa4370ee3d21b98ec19f0cbf2106a036215937a15bbe517b24ae5fef4d3870": "0x00000000000000000000000000000000040a88006a747b712bbac65dc015105c9cb6d29ba60dde6762a881975c6b1b1a02", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0214f0b5b1672e56729f8acbb64cb60b5edb62beadc9ac05430ede0086e29800ee32d106befc7825": "0x0000000000000000000000000000000004ac11ec66576b8d0a1c924596e74f3b45c61c7408e1680e16b4e365ddb4b93f56", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0223d09f1c0c1ef00ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e": "0x000000000000000000000000000000001006ffadfd1ff3fb474bcca0ee75b100d244da043ce2e0725e40b1e8c7d6f0251a2c61317ffa5f84e38eaaa44e333ca7be9924b445ee9e6e275421200ecc58a9b09454a3dfb574a6756a307688f156f4ebcfd72b63515bcdfccb50cf7f7bf92c12b6a0389596b472840969a9088eb5852fa03a5b5dd7a3c2fc7275d7c05563a900", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0318c1db47739db4d030ca0b2a60a30e7d1a0fec231f6f36c3b608036d25ff6b2b9ab9576d59c252": "0x00000000000000000000000000000000041ed7e0b663455310e4a8d084ce985ea6dde9cbd788f01cbc27f9a85264e97515", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e037dbcdc8f46729a2cba024614ea8ccd1ebf7a634f30b38d65c082be6aaa92551b9c3b4d1f15ae6e": "0x000000000000000000000000000000000c98cafd75bd233ed0674c7493c67d589c4d7e78b69cdb409ca66c0f3a7391ec06662d04da99fa11b0ddd8bdfec9bbc2574ac71565e9346c8e13857934c18b3646223b081a343ef66eeb872caa2ceac54d75566c279627592362d2cd162bd21831", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e03bfd6fd4ef57fa5a0ad3e520332a754892d7a16de9de871b9f20e982d62a498b5d9c7e5f93d433e": "0x0000000000000000000000000000000004241816355a91d53c772aebd5c1ff1114bb35fd22995e8b0d84fe770304b80352", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e03e65d4ca28086078c2625b0e10c7bf65f283c576878cf00f67478d3dbb6bf39ee62b3ca19ce893d": "0x000000000000000000000000000000000448edca59aaf9ec40d9967f298ab5a5a2bb7265eef18569d5c065f318da512358", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e03fc9979d20d8f4376e282d7a7eef593fe7a9a8c5d08a21f134e8858e1b1753bf347057c4db9b234": "0x0000000000000000000000000000000004964d882bb6127e75f8c02efdefbf052be0c010256c41d832e8c81fae632dec75", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e046409e5f145bc2af4f95e82d3eeecfde0058a399005262a9709101ddf3f2a564ab34040678ece15": "0x0000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0556a86b11fa77913c7f40746d04d77628d886dfd469c9bf606232dedaa248f5c219d32da93f4054": "0x0000000000000000000000000000000004f2ee0d3d7e3d57e18249e42d570e163d7f34ac68e81c973b41bfa521f2e99e0e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e055ca836acf0447774422321a842adfae9419ecd3983c4fa2da6e879ccc1db031e54c742bbb9bc03": "0x0000000000000000000000000000000008f67795750255b9f9c19a23a72960b240276a404d3c5fcb4fde2cf5759e88f7045ff23e481785ec5fddb6178f6860b44bdaa0150ef473a91de3f1ff794b2b6fcb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e05d31d1ec885004a5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00": "0x000000000000000000000000000000000c1415a9d9719c249bdeecbb9b746639f743e2f238ef5a2b227ce206eb93724a6f6a4aa384952d2245b6c439c833edb350c0ba7e31ca423f081ee6a0d79596c6585a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e05e3f970c23ff63cb85d101c656fa86dc284f34f7583b5f178d9e9b619df6031fe2c04b4c5f07e26": "0x00000000000000000000000000000000049a992b67797a09bfa4fc79558b14bff0e2ae2b20207ceadef50ecef31d120a15", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e06464a684f7b7a0d1c6681030fd4860fcfc1dfad9ae55fc0181229b007b6365dc4c8f5fbe162554c": "0x000000000000000000000000000000000cffd31bf694e0d28434da06abd3fe4febe23b25054b5de48ed94246339c51b2e6eaf1654d9143d99dc782d03b496b3801e06a4c6405ae954f40b7e7475f9ddcb466a4ddefa00f74de69a30bb8f6f87c50cbd2804768c367f3fbad5663a98fe48b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0655181280220c8b6280b912d54001e1ac0bbc1023ba9a16974a6c23d22e817e97d418ea94d29642": "0x000000000000000000000000000000000414a0db74267a9c3994944cb470c48a9f4c8a01df05766b96eb29789e9f049748", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0823dc59ec2f7a204eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d": "0x0000000000000000000000000000000018b4f8dd9a19e72f2ae65f989872a96ee2e239a9e135a868bddcb4dd278ef0f97a8d9511843f9df390385c97ef304025decc2d42cd7082db58f5b5e0523c58183e7a3a98a1dcff1349491c4de950bac2427069580f45cabcf5b57e645d0df2882b74fb773cd20d9adffcfc49a58d0ed20bf5baf645cd37aaaf65408f56ffe22116d8a8b294275746ad87f5fe0d3f5eb3fb81905036522357b616096f3e84bfced6fe3aa3a8b8e0e17a72626db79dd999dd5e9cecb8e0f265391e5daae3ec229d3c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0832e37ad433bf330093c7603ddb81760e5c90ba6c0fde51812e18e6cc14121c081f5a573a868142": "0x00000000000000000000000000000000047bdfd0ce52699e0b3f913ebc544b48b0cb02fcb8cb394625f88945200318f592", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0867cd2096d96b96ea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b": "0x00000000000000000000000000000000200cad33c225bbc550c7e1b89ff2feb2dcc8993f2e3a8dea40898fa8f54f754b002ecadcb36865c859f998d5538bc2629b4f4aea6e03dc4cc110bcf0eea4e063307ebadb760b7f8ca8280f493f1604fa76e90df43f3ce4b084ea6383315b94653f8aa121a03ca81740284a3d24ea4bf49f22578caa58441527a76e8464a319a015a27a87e5999ee8830465b09da09f16adfaa168d3aec122953b44796a9db5157dc6df02cd907ad64313666799a84023c8e8025e7f9f5483a05823a732de3dbd3e90e389b9296c049a2cf0cc3255f3d58346b0eb6e6b0826aeaf81aae144d5306ca8e2730b18be41205e5d9192603da3fc19d7d4b951519509cb32458ad622ae33", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e08cc79e8d56c8beb7c88cb63517049b0569ba773b2cd7be3dea4c7c88340ba5f31c7bfa2e847f65f": "0x0000000000000000000000000000000004540a38c94322e193c52afe4d438b6d6b1c50a9cafa87e47f1fc41221594d5f39", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e093c88d361b492968e76c9299f5a2046beaa5266ac0ef8b7b310c929704f15d8e6657b371302202d": "0x0000000000000000000000000000000004b0bf0c9e4095ac5ab829224395315bc4e298b21b180d6e9a86e698f974d2fa25", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e096c13bcbcb0791226104ba050f385c19450c62d2adb3e9deabed8783eee0059d582ff8918c03b10": "0x000000000000000000000000000000000426104ba050f385c19450c62d2adb3e9deabed8783eee0059d582ff8918c03b10", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e09c71da7f0f4f7aa98edcae85e6eef98ba192a51fa0efd89aac0541fa264d46adc9d8f29d3e21047": "0x0000000000000000000000000000000004dc226375dedb131cbc73b5c90ea8d374d5d4b5e75dae7eb6a9a4c215d8e9b0ad", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e09d05f5fb1d062ad503551a752e49ebef1b6988ee561cbbfe0f442a56fe624a58ae80ff3b3b9cd7d": "0x00000000000000000000000000000000085034b9af07130a1799cbdbfc0c2ff2fbafaf47fc4cf70d82dadd9e606f23085f5034c3e43599377576fb1fb81c8410fca61070ddcff4484cae5e57de2d084f6f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0a7a36431e6bf788600e047c97181ac8d0b9d5a6372f6018f556d68b2b4cdb529d87da365f718d40": "0x0000000000000000000000000000000008ad17c83beb46308e21cb6fb45b9587a826addb8c001e01bc2280847982af1b77769e87de4b843adb49b3de1ff29ce837047c48023aaaf9c6d3abc6e66b4ec34a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0c100cc5eae89342e659339aaaf44f9871d9a42595bece9cc446cc4dc321dcb30c798332a5780846": "0x00000000000000000000000000000000047e581640cd7c61c76dc4b85b771ce496d10e52429113f8e7629425ad9787c81c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0cff0134bde4ac18abb9286b2b288f2af6eb392d95b12a64768174de723047b9ae0f86283dd5e34c": "0x0000000000000000000000000000000008e25940a2f472c60c242463e18c20ab6555074a0644ac2b9583140abc15e2712436dafe22546294dab15b18d1f15fed8856e6ace31582b0dca7f8d450cd963368", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0d39c09be41728d25271937d9336b12c2801a62938d27878729a7987c705770d5f19c0e42ffcc64c": "0x00000000000000000000000000000000044e9a1114da2f930a02193c823ab3393fd2f4867b0ba68ab5ec267e50ecd35420", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0d533a9fec9db13002b47d21483aa953be67636583cb184f55d575e0f71ec75f45383a786324a64b": "0x0000000000000000000000000000000008d5febe9f9f424e1a509cadb2ccd2f502fa1e9b577c03bfcdf74f7e6abe6f692c2d14410d4bb33f09014a028cdbb9d2c2f00e7d5021748ac859c5dc11cc277a6f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0e77a555b20dfd069642d0db9f3b301b44df74b63b0b930011e3f52154c5ca24b4dc67b3c7322f15": "0x000000000000000000000000000000000cd4cc99150b203e2ded46d1bdfa43c2f64f89cb4a9102e8e6d5b37784ab97b117daf0804d1bf147f716661acb2ce7c796d0d655e2781c22cd138c4e6d6edb9b0ce4f351785e2ba01d8ae8c408b0112af93577eaf7487d1ad4cfb54285c88dbf1b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0f177f5acba9e6e070661c356f24a2cddc859fbae974cdff149661f165f5e622df3060bcb8e7b373": "0x00000000000000000000000000000000047ab0ef4391500cf4634c08dcc0bafc65b9c787a651ca8679b8ef33a6b557fe5e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0f7722ef9e3f0c3bb0d8ce5256f0b5a51a38ccaadc6d21fe930d8ff3da1dca198ebe1807802da753": "0x00000000000000000000000000000000042fa216946d71756ea4bc43259d6866958233f796bbdcbca326d684a840ef72f0", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e0f7f00ad7cb619c008769738ff8d53c17d6e0f0344e52c50a5ef6b61a33389f4dc4adbb7aa2f384d": "0x00000000000000000000000000000000048a0e42d190d3ecaebf11d3834f4b992e0fab469e6bf17056d402cb172b827a22", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e103e847acd44a834c8c0c1fb9bb3902b9e4790461bec2c33afa31c9a3b72a4e4ab6c050b4a284507": "0x00000000000000000000000000000000044e6776c8d171ebb2e352ecd10eb75ae1403f00a4d76089ef92d9d598264ac841", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e10af15fa81ea76ada81e54507ca4f6fa30932b96d35e8f073556c99f4e3119e5f679893450192109": "0x0000000000000000000000000000000004fcdc5fe2f7a0789f42175567fe656b9121815763a037c761ef846f0d97420239", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e11e755e0b2a267d8a8a2e5461f346cf0c23d1ca613437432a160525b6487dbb718afa51439d48d04": "0x00000000000000000000000000000000088a74d6464340d1e60feb30c35ef63b8e48737f225e6343b1875e352756d0160f3515e1b78389f5ef86a9b5e739a0912d6cc4e9f4775698ac23458e8fe8764f89", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e11edb4162e9b96b85ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43": "0x00000000000000000000000000000000145ecc1d4e60a92262c1bec62d034c979f42cbd3fb1c28570d5baed6e5ed20d533c83b0bba37f25f365e26efbe6c9ecfa7905dbdc0b0e3ae60b29980b42c509c6fb47150da85f064599455634eee628e2f775d06bad83bb3631130854914e96d015e25f73392aeea8ecd64fd33e2dd4728e355e314d8fca42e2a382f95a941d6caa471c7aa909cc665212bb36003c52c5d3eeec39f96556a8242e861c5dd7dde41", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e11fbcd54abb1de419ce84f6cd845ac3fb2a009aae8e99b1a2fb64aa3e7ce1c7867f3ab2db0c9bc00": "0x000000000000000000000000000000000432ef9a68234eec37684bf683d6e07e2deaf52a336ad7dd7e124041baeee37368", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e136bb08c596dddb97ce2421f6b3c80a00c8fa9476eddad55f7bb9cc2f54ad916b4969c103b5fd438": "0x0000000000000000000000000000000004aacf425049b018fb55d17640939a6f651697b153bbc59a060a7f2ce4b4c5610e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1404625c59d62180187c76f60b8e91032091aacb1ec79764af51e796a0c962bd2f2e766e9e5ade45": "0x0000000000000000000000000000000004e212871311a823c9537b3f70adf0a9697c7286c84fdefe5603bb2fc49b0a7b67", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e149ddb66d3286a35ec7afe6fbfc9947fd177ed118016e403dbc14803a0432bfaf0337e3bbc3c820b": "0x000000000000000000000000000000000493ec952a9328c2f39b697aa00f57f01c289423ac2068f506ce2165be10f1ec45", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e14f43fb7c9ca8d300cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66": "0x0000000000000000000000000000000018b085746d68637b4db6d45d855e9e31ac9059ffc928c3330ad1e13ac6f170ad48bc1e141bf6afbb7224e41e050c296f264e8c4c3cabb0d91a5594f0585be0571402f777f4b3001d83e7a2441ab8456d2db9ad30b77e5d3f2fa0c4150b769e9a394680cdf69422609ddbb2cd596ee4366b84a50a3f17c0a88b9fcab7263852cf6d982b1616f2b4b963fe2a8aaec915c4d3f90aada694bba3fa5924127e67a2456ce2af982fd853bcdb276d9be46e6bad4cc8e1af153d82638d2bc829e6ec3e2a6c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e152f5e61256c5cb31a95c3968b83520b8e43f82edb0f050b1ce7281873a93bf9c0798efd50f5c41a": "0x00000000000000000000000000000000049e66677d3f5f4ac376d14bf73bc819845156f1f25ce9e6930fd096741276ed67", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e15cb248f0f9af445fe56be5933800b45a21ee8e9817eae9f49099fdf4a20076718497092ed43c62b": "0x0000000000000000000000000000000004a8070648f6e43b7d8a8f10418b696130d2046c10645f10085de80e6098b85f09", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e15dcd927177e5b7aaee65bf22cdf1f98c91b6c176854d8072f1328e027d2e84d23607b517b1b9429": "0x0000000000000000000000000000000004aee65bf22cdf1f98c91b6c176854d8072f1328e027d2e84d23607b517b1b9429", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e16530c8e1e5dda93b43ec7322956d133d41e28758fc64d2da34d2888d93af64eb41f7afa26967961": "0x0000000000000000000000000000000004b43ec7322956d133d41e28758fc64d2da34d2888d93af64eb41f7afa26967961", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e171ca88a3597ca4a1097c82198eca584e8d9bedca6a5ffc1f1eac3c1fb91d0ef4ef313b842b04c3f": "0x000000000000000000000000000000000400e31d15b9166c5238cbdfbcab39ccc2fe0173c9419b060f28fbf3f0ea0cf25b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e172f5474abcf5643a8b5707defe6889dc178861ea7b68861fd0ab5427b54119950e6788afe1cad2f": "0x00000000000000000000000000000000041ca9c1ffaaa251b220fbca62f28d6936272e11d052c4e995ace722bb6c2e8d26", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e173c712e406fc7a20a54e1448806b2c0cbdfd5da73198f12554bc972045fc9dd3f2e22b6c5a97c1d": "0x000000000000000000000000000000000474378a77c102cab0cc86d7fa5bd19668bd88c48b2abecf283d81eaf19b4ef464", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e177d87d70120c0c15a9e357de87525b67cf9ed1d0f06a15a6363665ca1c9f43ff527c87c0945597c": "0x000000000000000000000000000000000c5da7c5df13916304befdcf8c879f5a35c7d65539711eb5cac00a9d5176b36b580ee022b7052ed281ad71f8cf98ddc2efd5b5fa45d741e4861c225a2bcf22731bd5f8960e7af211c990e0d092ba6038772482a74e9dc91e5696c84fd079992ffe", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e18871df8131a10a56041e8f550869197a24ed9e968eae648692cde7bbc04077114639c249cc0a043": "0x00000000000000000000000000000000047eb15d7fc95b03fce6ab8cbc54c38ac898932407a3e9bd86d8c03bbfb5b8112a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e18b47e3024d66dfe628f36dddf8cdb0242104a2531e7d3efd4860a9a4633be69aaf30f63ccb25a5e": "0x0000000000000000000000000000000004405637fb518f654b40c86cf257796c857ac3c28e5ce0ed978dcc4d69a5d67442", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e199f24e2487e567b321ec507203650141d2ec630b967b76ec45dd53d852b9cb25f220dd3a3fa2e51": "0x0000000000000000000000000000000004c80e5adbafea30ecb72dec246ad8b5647f95092b535a702b4347d2ec210c6972", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e19caab1fd4cdabfaf287534dd5ead6c0247a1b0d3ada5588e578602c2ed64caa6f6fc2a5efee6f23": "0x00000000000000000000000000000000049eed509e1b9e0f45b24942e75abb7aa6fa306d0e52c74fa8811857d54d0bd03e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1b2d52234edc009738f45bd8f6341dac4486eedaf00f2357cd19b8d4b8f0271c7340d56fe02bca72": "0x00000000000000000000000000000000045cb36ec4414da2e8f8e6be74901ceaeb189e4bae84245b00640f96ea36814501", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1bcae011029977921b0fa0b1a8e6d3ca06224ada945bd41785e55822a36102e48d584ddbb03e9573": "0x000000000000000000000000000000000438bd292140ddbadfe9cfdceda3090c9818d53ae79a862d77e782bf9c9e94fa40", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1bd7316875d7fcf8a0340d617b2e5fecf5813d12bf441eb025f610edf738af8f79a98a9e168f690d": "0x00000000000000000000000000000000041020aecf6332d324cc8681199d469780ab81d8e87dc408aa96ca573c590ce344", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1be2a3fab16ae5e58429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee21": "0x000000000000000000000000000000001462307128d13196dc291ac51e68173c5801fe6bace303a222d2659255d9debf273c0bb72774583cae164f6f184ea05f95f90c8fa34203b9b2c5a2c1b6beb90a5f389af7a171ff4ef270fc5c602f1570ae7b818fbcd797ae42b5ac9f14454c5b4e4c27cde4c0ba44b80bd040462654c90c73e26b474895a2fd746fd5febf3ecc654c70ba4d71065dc3bd0d11c1fff6bfca26d89b5c3f406eef2e5de8ac7334866c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1d7259e4eafa026b88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b": "0x0000000000000000000000000000000014c0d792a19684453c51324b0f2a420544d8c3378c515c85c6aad72b7059ed4cd19e745f85a1a8ed92e237063f3ba463c198d7744b7698e0e0a9a12c5966d798c8402b7e0857f31fc28e9c6a0f0970cc810b66ad393edbe120b4d97f5ce99261c9b0eb1b93d4fb82e4fe4e55b4dd8375b8a09c97596db6bc7e080401f2b88a07e9eaec5e47daff641a4a15c87ad7e12649e07f6ebbb54630b984952184c657e441", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1d77b5b5e1a11bfd62a79f3b924342c4f634d8ebdf77f50ac051d41387a72d22f2f38155762c125f": "0x0000000000000000000000000000000004304e4137516cc6a906f03158933c2430744e602d6549dfcbf5a0d767358ae419", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1e495b9d3175bbcf109e87a012b2754d0b23501fe1fa775db374927f09c228f07948f81ad84bf617": "0x0000000000000000000000000000000004109e87a012b2754d0b23501fe1fa775db374927f09c228f07948f81ad84bf617", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e1f4321336da7ceadf4d95d4c5c0131969148d3a16b3d95ab3d051771d971a1955d7e745b0a3a4f16": "0x0000000000000000000000000000000004ccc49a4cbcaec6b03737d84c907628a2cc104cc75ad817ad38292e5bb76c527e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e208d340a192a7ce08433eae795936e63871cbcf0410517d1dad4755f2da4a6d88c1cc1c589b8e86f": "0x00000000000000000000000000000000042a4f829cfd9c12a01da70549643e5bade2829684c101fe7c1362176c884a3719", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2137b4e662fa80a05a37c441df3f0fed7ddef5581ff70437b00fb071e0b09537caca8adc4354913e": "0x00000000000000000000000000000000045a37c441df3f0fed7ddef5581ff70437b00fb071e0b09537caca8adc4354913e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e214a284ee9e9b01cd61813f456c8f11087d572921c67afff25605aa712899d6a6b04cc42c3d2d417": "0x00000000000000000000000000000000089bee35b6118399b673cf802455159ae282fa4a1e68368fb67cf85b00e47461194f83a66e4c8f4afa5949586c22ba0e7d73e7e4dbd6c1efeb9ccd689080834600", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e21667555f2586f1cc852bd64d95e1c2fc164ba7ee6c2cce6e87ff8cef81c60940d46f710ed712b7a": "0x000000000000000000000000000000000446378406055f64e506440a1b008f875abbbc8d3fd7c05f785a723fe1b5739fee", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e21aad0a24a729734c0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b": "0x000000000000000000000000000000008080b036ace5df3680d4f61cccc6cef4d37bc396e6a6e63fdecf505ecbfe41149b2e91e1aef05cb877f9c862b416d157a840115d43c307290dfba6ac4c4db5dad74ee9592a2fd8d3954c85b71eb39e6eb323411ca48bfba174abbf1751d2d190ec4e3bd152d910b6c892f23f85469cd64bef5d7561d69475207c60f4542cc1257f29cba2b60e937fa112f8e61fdde36e4043d0c40b1eb73f12b5534b52d01b5e16cc6bce54889ca98332b8d289e4ab347234a96a1d5389bd183d7f991791a79f0ab8dd36cb05189e12ff133ef1c0f3ddf97d1319dc737e4acbd882d17e143bb083a8bc182820c46f4dd6bd98b76dbff06f8565f0004eb1a9840ee3f3bcae1442d575c4d8aeb08fb3e8276a09141d8139b74d6a76af72acf6955617309dea176a7a7f90cbd721e0f6df172266f725ed45095c9ac42202cbd84abae8b5494119a938a9c13c25dc960c282ae2a76f4e315ed20c60cbdd08750fd45cf5b2790f7ef045bcf4933936ffd18b5b65409bdc003b5f5ad8f9b8e36ae97b1f7b5f0af2803bd8ba823c07ebdc12f850eb5dcc7e39971b34d5fd6643064e0394cc77cc0fea6718fe96b7fa8b193f73106d03bd579b5cc090cb75640ec8090d19d96a3c3d5d8c7d3a43a4e20e15a0c9e0009fa11135246e1de9cf4507c1945bc86cb0a088c1c465feddac420e696be2b3c613261dd7d84a25b6410eca645efd87d9f4030c7bbc9fcd1a5def7ac55b1ccf202ae5de75a02a224d939e1b8d84f54e5d03a714d4989649f2baaa065d3e927f265702cfa8d8eb83cbea8c64bb01d19c5c184b8e2f5d107fc552b8c6596a09ef8008c83d1dc8ee77dc175036bbd2ca89a55b855a0f01cb9c322a9e20637c9a71e4d131e647d597b1c600dbec94bfa192465e3991a15b6381a73b784a15727dfd555a15f61575f5f1b8323b8fd41416dc9eeb4df87acd23f2453d14482695f0ec5b7ec434dcddaaf83e09e570e22c293906edad0ef967c7216959aedf96ab893d8b8d8c66abeab8ef62940b1c6a6ab7228099d72291c72a5db58282171c8d2c73678f13f3c61579902ea4572ae9e9158046e8e820bf4d82bc56d28e12b54fcca3e2c3e90cd0d8a991718bd2fcf9a65dcdcd1bdd04be44591ff9f838183843605f88f6b88971f887fd069e00f4a2894ce4249a8a70199a057fd69aae09c52bef16685e25b29e22f3d1b43f6469f035a9081033b9a7025c943a4d56fc0f3aed44e21a24d0a3c17a4d6c1360123ce0a4d9a22aaac577031c2ead3ef6399e4bf49bf0ed9ade88ec40ef21be714cf9efc112306cc85c194f758a6cdac27581d1f3929bf543452b7da444e03457ea6424f84ef9a372ecfda077ecf87bd083c89d247ea03cac2fb12a410b3f44f87c1b523b0bd0aa3375d4dbf19354416d87ef2183c6d1c383b29dd10f002272468fc70cdbddd42b5093425e5422", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2200b6e2483bae501aaf37daa4afffeb0d84c47f52330d8293ea648e1bba5fe0e35355057e63c167": "0x000000000000000000000000000000000c522159de5d549c217b26deed24558c4ea6e33ab8daf73f5410665acc1d5f845cbc79ba52668a29f5a5c62044bf72f6c666f2ea1347cd1d23c3e54d7a5dd0614eeabbb97403ae010a1fcbbc9cf50529f27e0eda03efec95e29b6ed44dcb075648", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e22501e6d8f21e9dd5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47": "0x0000000000000000000000000000000010f40703cb81f0aeb2691f6069bbb67a5a84b30d392b6c5906100b5a6cc57a781c5c8bb12c78741c7b0ff4659360c78bf5da3af34e842a60f58e53045ccb070302d2de3abc2fce0e6fb421d7a29d736a9ddcfdf51244022ffc483a291c4e4da9588c65e884140b3bfc129cf21cb7423ea9f6a72246c273c3ca4c77a00910f58136", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e229ce4e5e00a4f0b1e6ea78e3190ac2cfde9c0041ea7a0e1f7b89d52f4a58f01f69258150b782466": "0x0000000000000000000000000000000004da5484b32d12a09f6c28114f2d9ef1a6cb2088cdd2c5d9be152737bbd165733f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e22d261d77c92c974201f968f24fc0df93fe98dab905ff103d00a9a232329bfe78c22663dbe60a12d": "0x000000000000000000000000000000000407e8861ce764f34220c198710b60b72f8c59c617fef101bdba96bf6f598016d3", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e22dc4c22ba0bc0065c05d5f192c927b30b33c85470b53474f2a736a01c3c5da905384329a430f22e": "0x00000000000000000000000000000000045c05d5f192c927b30b33c85470b53474f2a736a01c3c5da905384329a430f22e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e23439dff64c47d6062f21f6587843801d599ed5855ae0ebdd2a84c822919e80cd6f12899e5088772": "0x00000000000000000000000000000000044b639041c549fb527faf54fd7e915d481955ae0bfb42842cfc3d63b5b98a0f31", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e25235c4616852bcaa6c197a5b757309578dfde7a02e19aa9922b8f81a60e81bb0c6b7295090b3456": "0x00000000000000000000000000000000040fca29bfa87fda85b6d07265341c56bc44fe830e4bc1d7b8cd31f54cac6a32d6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e25c679865a91ba59c66f4d91ebc7dd0065a5a2837014e5f4cef5d36d36d4ba7c915137d885dd7640": "0x0000000000000000000000000000000004aef53be490b506e8e00bc24809e634fef3ed2b1f8f3bc9926a39e2b40c3c70fb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2643c0564bb7e30e26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148": "0x0000000000000000000000000000000010f2b13a9cb72a219a88fbb88f7c5306fcccbaa21a22484a24bbb84b8acee8b50b2602783d96c4e25d8f6894e457ceb968bf1c9694295aee52514d4919056cdb1226842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148ee69e45394d3fea77645868ce1992caf33fb25200b4ae2b41d1306a46dd5f720", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e26a2abbc21cd770cd88a4b558274e57737ffd3fc9741848596199a29d77fe511804d20810cb76050": "0x0000000000000000000000000000000004023fe56458783b5ac1d399ab49e8ecfe911d282cf645ecc8b4d9803a130f685f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e26e9d47393173c428a65f2773ad69cccedc0a58ef7ebd2d446b882231b4b97044105b2035a8d9546": "0x00000000000000000000000000000000044a1123e20cbc903262ef39136378a2528eb7382d3b598cd240af1a965f402662", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2777a559c125897fb8897a746ceaa53376946a3da353c1c987df8c0caa4395ac0eaf0e6c74874054": "0x0000000000000000000000000000000004888593ed4e02aa8a39aed15ec8aa2f0ba2eae732b9e2bf7f6d72b6d012fd925e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e27dc7bc51117cc44d46e6f10cd59b0f6d7082dffb33d27c9f29801233f8e28fe3f5edf2d51762c6a": "0x00000000000000000000000000000000041d6cb02740c7ed074385a93d27f0f9fe5efc113a8e5961d964c54b0afc6bfa12", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e28cb5aade7584f6236d7b7a05501f3e93e7eec83c53739147dd9824554e4907136371ca062820e3d": "0x0000000000000000000000000000000004904f9054a49d973dc073e09bdb9c9e49213558cf7b5a29d6f2671d8f6999656a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e28db6c1e91cbc43002385caf9a08b92ca458a0b817a8cc303cefd5a0c6e108cb939e04242b9e007d": "0x00000000000000000000000000000000042cce76137e2e2d9bb63e081d4074cfa4688d7d9781d2888f36634f646da62561", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e290aec17ae7c197466fae573cabe4172bdfc60dfd00dff703a4323854715c151f868293db828190c": "0x0000000000000000000000000000000004f7034438a748412760539f824f38f3f9ecbf77ced8716de97c5ade5d2444c8c3", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2960a5a23c329652582e9acd4386d60a8d3de206a575ab9ab0c383f3b4ee88d2a2ed144afd356504": "0x0000000000000000000000000000000004953288a0e80d88a64db2db07ca48da06678f683fb99301500223d663dca35b7a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e29b138c94f24ba807c4e144380357ad3e690e74f5b7bbbe4b7d6ab1579d4c6d7c844ef003cad9a24": "0x000000000000000000000000000000000472a136cbd146b0596b9cbf73f4f2e402dda2683568e33d1a3db791ddfaac6a4d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e29c4999a48e5667768f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb9607": "0x0000000000000000000000000000000010225ad9907fd7a3f7f3633f2251c3b390b338385358f1753ce35bd27328c7fdd1bd05066b950d256e451a29012b1fdd38e661516eeeb487d816bb2a65975baf016920834078df5f13662750273260531e585b9e802eb1dea6a98e7fe2f7555570ebb515975618eb35e252200dee0fc30b3db265686c72ca22708ad304084b975a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2a9b352e5eaaff5751f78769768fc88c83546881a768523b3c70c2500159047a970ac4ef16768af6": "0x0000000000000000000000000000000004905f923a67cec79db9e1415567822f2c440e794c4a38b43144bfb1a044b2a2f2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2ad59b47893766e9a215ba2d1b408fd5350b93f2566124331dabc06e94c16d7080d3cd5771d59958": "0x0000000000000000000000000000000008eb6a6d492311cb809fe02a7649fe2c815ac9a824be7761d7f5b28360d06b810c1f8ef3aac7ddc528f500ac380bfec2dbe0c58caba4540adc427fd3e3186bfeea", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2b031c075ea343ce443c76dcde19df9387486ded7845c6d85ec2a4c17f38f8b1e7a0a14de7968d7d": "0x0000000000000000000000000000000004727dba627f34c210eba395fc7f60d28b3a58c5dbd6b63fb4f9788ee764b2702a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2bab42363fea46ad00f52ade889dac25285059b639359071c2aad88e3f1f60593f86cc460ce20213": "0x0000000000000000000000000000000004d2d790f992e31eec84ed33b3ddf3e92ecaeaed911f0026c2ca09087f3eb1d3eb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2bc21eb1a6e88498ea524b9e0dd9bd336d31e71bc1a172388b10d4b6571ace5e7e6e836483110216": "0x00000000000000000000000000000000049e23e3588757c7744916bc6b65d9562fd12f807da8bfa23ca354ad5b40bece4f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2c09493faa9e924efc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216": "0x0000000000000000000000000000000030a24f97e96ae4e213d8eae1f35213c986e0ec03126812b24cc1bdc9948443044086d6e47051058a73623a0abe221e2cdf86a362a3da910618be17cbe3629eaf317cecf08ce1f6f9fbe70156ec68ff04ab4ad0dffd5f39fe72c955b7f319d7740c2e4e174e782224c6e32c71c85d399497af3cd209216738baf31130ed860a5877acabeb358e532ad64c9e4e9f5b3a2bef0358e8535cb4e1b8a7727cc24b7be643d0ccf4cb7501417f0d7bdb6d577e026612d02579686f0ff1137a10c843f5c963ce0b753196d88630621ff926331ce4780474fdf5b100fbcf96dfd4e984d1c669ac66f315467fc0b8d0d5d5d8906dae845567f911e24012ab0ebc185ed2dc6a66c016c699321be18f86dd04415e6f3152fe5b3bc13f4808bfb4617b9bedc2e1291076ce5a68ccc3f21da73f2b8747c87a71aec14a792bd55050a44cbe58c7196f5aa67923621f3a3395c3e2a58aeb89756e2dc11ba9ef1ac8bd4953cf2a2201344c69cc407f4deaec89a4090075f36639e151c616b8ed573e7e384ef7672d100b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2c3ee724586db259eaab0cb55c147ffaf184a4c00513e85f6d5bb6416994fbdd0dd168f3c59a291b": "0x0000000000000000000000000000000004ecda6ddb746609cf2736a0b70823b52b11b15b1bb35a4021da70126290bbdc64", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2cd98d2b43b99a0b6a325e3630266fda0ef7f7725ef8199726e29d569d609f3cf068c4db7e82591a": "0x000000000000000000000000000000000c62a791daef6863829ce7969886db050a38050dd52ed6c1a685cf7897e67f165e969b1c4800a2e1700fc49adc3228a1faf72543f36ef784991a2a25d74632b26fa6644cb7298d69083173522d5e51c66dc5c88bb7e4358ab6d88b216d6574b010", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2d287fe916fe23dc925000bd5b83d502f56c49f2a91e3532af9f919d6eb52d750b72539c6b62d45b": "0x0000000000000000000000000000000004541145a8a9d8b066ecd0c7dff89c9d397a18e2e0e9d65a36cb2c1295c768e376", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2d859f3bd54b349892e02ce87428939cfbb7fbeeb1ee758b749a5854a1bd3ae9ce36b3bcb753010c": "0x00000000000000000000000000000000044396d758a45239e3ad43d8ffa0d171a6785aec18c571107c6675d53d082f09c7", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2df274fea56f1419fc659bba6d3985002708101d9c2aea9155bd520c105688751281cb40e4d37163": "0x0000000000000000000000000000000008e0fe63b7c5032e2437b3f8327e95b07eae600a8ad4f31e17db0f80a3208c4728f2c9cf52ac4784de6db0c160481ae4ebf7ce0d7066011e36e18948172c05d059", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2e61081843efc3b7105c06afbe01ff98801bf3e46b96d61d0d7aeadf7af7d6c39a20dbf946b0fe41": "0x0000000000000000000000000000000004f295175d63624a3f6e510b8c189db808a049704c4b99f49c2638e9d963d1a3ca", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2e7e56460089fc7a54c473bf199d05b878ab34e9a37d17d0a8bf70498edb5c759672e984fa38b432": "0x0000000000000000000000000000000004c01b6763a287079871d569b4c1ef94255494347450d13fa06d2ecb298c426d3c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2ef7dd71f889f0050c841e6aea307d8704d5b7b7b71afad58548ce47dce090e25d01b84925e5c48d": "0x00000000000000000000000000000000081bded8b683a29a0938bbef126bd9510acfc57f2332a8009a305e94190da895695b485a5d58748bfe83392a1ade902a02c95084c00df2070dc8f32f13ad499e1f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2f20db1fb9bc54324c042cc1451781f79ff3bc34cacd5329b21591b2b2d82ad57426a5079ad1c455": "0x0000000000000000000000000000000004ec496735eca64ceabe80e911ddbad8c072ac5b69d3d88ed8dada02a9cf5c66c8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2f2145cd985eff31bcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f620": "0x0000000000000000000000000000000010c82d85d99021f559a9a4f5387fca2bee170d488b97e00766b5ad19617c52c17e0efe4d35b7d336d66f5ae2cf6969014428415b9d32d8eb2c17b58829d505466715647f856e3beac82df2fd67403a0fbd18fa79f584646112d15d61a064a681c5c05809bc85b574b586d8cb6cff329b5e5666a7f56963c06a4c95fcf681271e24", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2f8f1ddeb924bbdf5cadb1617794ea8d20a5b0bf1e3275a815229a34c834c9eb6383602ad47ecc55": "0x00000000000000000000000000000000044beb8e393d37e827b64939797512b2988db9ea41f5b4d2f06a4f8c8fb955d89e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e2fe1803695779c79b2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a": "0x000000000000000000000000000000001c7c24bc10ff87531a3d2780dd51b94ed0b85818f4827ddc09ab394a53884c64441a746810bc697bd6b464f5115aef1127130712a70960abe590c8a6491f432232e69aa84285f761bb1942735db2c3d443e29dd3f3da5aa7a00038bafdf93abc5703a56ca86460efa365897ff7affd5f6d280ab3a0d857b37709ce67f551d1f88f5624e7bedddddd49110e4c76ecfc6d2406dc3bbde447a71ef0e511560f588f63ea00a7167ab2ecc7f024e26e62a15b24c02f0b30e967cb91621169e3c780ae4e1cbe59b1e375a52b9131fdb7a85c0992b8c5cdc3f4b4d90e19185972cef58b2a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3161b54cf940118e9aa6373b24df370b863773f45f2bed6ebd80c886c58b4232e655a9b130b6d615": "0x00000000000000000000000000000000043a29d1002e1c81fb779d11e082da66b45a355067ab816aa015f5d5ce3d927068", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e323ac9ca334c2bce400a075c48b7985fad91dda0b168b2185958c9fee280f145d2dfe24958a12737": "0x0000000000000000000000000000000008d3fb95a477ea8deb243947948b28d08677f5fbc3515d9365668056b12f028ce69d2acafdebef59f646598614d1e0f1ea7ebacf643f0ba096abd078d9a2e4ae96", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e32ed1c932b701c300e993f475e1085cfe2d313b1089c3fbc33c78c178ed19bfc94be3d7937709371": "0x0000000000000000000000000000000004e66afee7026bccb1c5ccda9ff095c278ca0c40c7d44f645a9e60d2c1cf49a305", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e32fa3d1c089ff9ebfe88f2849c8b51127fefbb618de330c811b4092da0b9272edf2b8b7fddc05c1f": "0x0000000000000000000000000000000004936c411f5a41fcab2c26fd03ea779dfce7ce65c93203c5538051e77258315834", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3308804a76f50044ce6e3dc917919ccb44e66c8a5d4c693b96265d5e7072433971fb38d083d0587e": "0x0000000000000000000000000000000004c0d4fa6e65eb6e8de70d275bd49773f00fa1c385a21608fe2f94a13036ce8661", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e333c08553d75ed2cdab8ba7a028d62fe9a5088e46acdbd2039f01abd8baa7c695d9377661c3d406d": "0x0000000000000000000000000000000004988740c0cb624d6228e22704f9dddd8a526775c81506cb9eab96d3be870d4a04", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e33446753bac3f7d8d49e16d1c4f6a051815c5865058cb218fe7d460fa893907bd0cf8596b493f45a": "0x0000000000000000000000000000000004c21c287be88281cfac16666331518cf2820f4de9c29d7caf15ffb596f12cd953", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e33f1232919bc79e13a81aea610fd2332295967d1c7846599774a112f2d6cf7e3ebe92392b7b17779": "0x0000000000000000000000000000000004e62bc1402d84b145bae2ce9ac2e50f7f613b7a986734a896af65be8f51244c4e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e343126692e3c2e4112d49078cd721faa2f041d0cf96e0d8194561fdcb4ced457270e52f209e76c0f": "0x00000000000000000000000000000000049068a88ce95e5c34122578c16d46855386229be241a7e0656ef469a03db4ee19", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e34bd1b4448aed1acf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212": "0x0000000000000000000000000000000078c573b977a12a27f38f686571c67e01b848e24b49fb2ce07b8b0f12caf651b6eeeb14462cbcddfd07593831e6ebb7c4a2e5f0acf8c052f6d76aa550113bb72b688c7afec700f1f0c83226176063f349c34c3b100f192e4bc106c3305c1c5e4c386579df1779da496305c30a43dcdd9277e4984df2b941343e1086706c613db39364f9e43cd95c94ded79fa17bfec8a8d745932f4d7679f8b06aa9e13f915768b252e32efcfa98867081b563878242febcb31531cf4648cc496bbf851f39f31f6d3a5dfb7d614cd20d8ddf555c4a23acef0a71bd8723463f36f89e603211dd99b055e8dea9080f49b00804005fa39712a313dc6bc21c3de49f172b3f46e9f586e4eee6c7b76518ff52ab727047c1214470a0fb4fce60ed6ae06185a1501e9a4ce6bf4221d5348a254fa587bc69297dd25173e89f25220ec395ec495e3df9c41d3b47b5dc76e7833045cd155547da3afa84a1fe6b9f8d8556e8c7187c3b2f50a4675f5013d41624228728182b71bbe799dce7dc5df6963fc02730c6b4b3e84273e1bbce0e01ff970a8d2462a545370e0b992e069db055e417820aeb77e6870f9d0903460b53d4200f03a8183f00d5ed6c971942ddae9065693b4702f0f782e5c553837cd9bff26ac28b84a814643ab00556d90e873a921633bab990cc75b5a06dea8eabb61420c17a6e92eb2ca99f0e2cca15015784552ae332bf2105a592b80dc66ce201e876781c6466468f641ea7defd144b054fd1966e2292bab3c550f8871107598edcb29987227d3fc1d585227937f701af167165fb0a99b6a21983fdba049f3218e31dad244bf47477de316c3f46a721149ce003f4514eedc2042b854e6640619a9305b0571ee5a5666073612190b2035be70b6846a2f16c94e29908d38962d4ad80a2a5cef99de5288c0f299cb7fa7a3e41fb2db1a4c23fa44892be1360c5fd9b06ea650783b1d4ad13841ed6caf054ff5cbe72ec4636fce640bf1ae53bc95dfabf99a55a128f0cc1a12a58cdf161e58872515ee35cf87510536082d53dd69631266f8f9a76413f5f902d59578faf655a0dbf92938ed749fee838c81bd72f9daa984f4b569c43ddfa8b12c3f75e2e02f8c0ce9980e00daec2cb391c74a4055acee05be3352c7d09340c8c6f76c87170f1072bc0ce873e529381c4f5c8a2c6125fdd59c2b545e1032e0223a7ae0e3aa3c4ebbafe72576dec399441068e3c8af704356b5593f79cf9861e3c26748ac8ac6a4c2920582293228f56351d2667016768f8ff56cc85e23810144f87fcaad260080c7547bb6d3c20d0b4929b9d73245fa94cbc6c035f58068a57aee59359d7d464caf058fe55e30623df66dbca94", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e34cdf837d56a264302302a200a9ead164617576a79dded74ccf9094d6222cdf93ed575422e9f5837": "0x000000000000000000000000000000000408d3e6f92d4020b4a2a6d4dff33fe485f2883070668660980fdc064f12dcc129", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3533fb45c1708948625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd424": "0x0000000000000000000000000000000010c2e445df84e611e629ded39f69fb3ed7877398ad5ce82ae4028b1cbe997043cb9181d99f43daa05e74f15ff308adb8a4ef121fe4976904813de2e16ac447c3eefc44a7371ac4b798826aa05df8fd3cd5aa1b62f4a1a7cb9c95b7e83e99633a3ee2cd31d823eeedeaf516f7fdcc4c7287e3d23014e76f804b332d7b52571c2a6b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e35a390c3506c1387482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a7451236": "0x00000000000000000000000000000000108688b96ed623770a0b2712dd9661b3c1280da83237db214ba698be7783731b122cfde9047614f815e566dec170152a0e9a7b163f94d0a59e8abc4b84dbaa2e6348a9cf978cdd6826ae8be06a8a4c2b5080eba18ed88f5a01cd4db7b947515d71121cb3c0a7a70ec5db8b5e2ba95aa0320ece6b999a593c146471df768adad97e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e35c408ac02c2a02dfae63fdb20e3ec7589586b14ea019731b5089e2d1b22a7911e48603a5939780c": "0x0000000000000000000000000000000004fa98b8b13a1b03a3f86748ad19edb237b86ce74b4c4dcc08492907df447f7026", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e360c398fd5e777baf6d6531d9623034efed118d00dc62831eb6f017dcb45d66ec6af44947ef41431": "0x0000000000000000000000000000000004602d88c1c8aef782a7eba2fc345663405cce57081d4a34003b895057d96d8e42", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e368ce1bdc40db94c34f589d251903b0ac5a22b1d13d54696fba34b77f5d21f5244de907171144763": "0x000000000000000000000000000000000460bcf3dbbcdcb2254472d74e7522e08b6e35bfab991d39e17c8e35ab634e3c28", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e36a17a0db79ef688c664fbde2dbcea2d4180fc9e285ac56ecb6f89a9b88cbee9b407bbceea7da912": "0x0000000000000000000000000000000004100a7405e03b712786ff8d6b522fe258843ec33d366eb61379c98aa028bf380c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e36becd4b5e8bdbbe828618dad92559461b479508086bc781d88434e5372229cf66ffc887672e9b34": "0x0000000000000000000000000000000008ea17387e7283543fb633e2a9e0f68d39e172cd5624c7095e6d81ad3468f35b701ccd666d5c96fc362fd7fb1633ff09d05b3394ad29e7574e4231f5ab2e0f276c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3753decbc1ae388b6849627c337067117e864eff154c6125539fa6e4eaa980712e7594cf78447874": "0x00000000000000000000000000000000045092144ba4cf9a4997c6dcae1ec2f9b8cd1065ff5d1f97812c5700132036a504", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e375546d9339430d36aa9e19b08ef554ef0b123940b685c0d64eabd9a1ec487e43bb7e1f3d981c062": "0x00000000000000000000000000000000044ac0609d3d326fa83a76b4e89a445ff2c0e6436b338481041af7500057c870a6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e375605537adb7dfd3d6d2d20735ec00c7753d3e6071ad1e2280288a98d7d89c2a2b7fe08bf6d05bd": "0x00000000000000000000000000000000088e2499f22749aef04333796fe92b73c06cf4e358a552604ff3e550725774f924bad66ea053eac162ae6fa88c672a16dc18d932399e7159d0e2ef25c62189e637", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e378b219e43b8dedff0fd6298e6d06eefc52fb2f12dc1a6ff9e8958ac2a3efebc7f5673dc33808170": "0x0000000000000000000000000000000004b82ba825d0fa34373ebb741509f70042068219d805f221b75330b4513f62e674", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e37fc013628a8c12f22fff76bb4a0a5d66cff0392dbc083abbac3b3046f6fcc328abf0ddd16ca0837": "0x0000000000000000000000000000000004a63f88c1fbb368cfd13ca5e7a68e16da2e80b94fb382948eea95616685598235", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e38172c8cfb5a713e5a718199b3c87bd8c24c35f027b2b4ba2789a85782a79cc6a924f9e4241c3005": "0x00000000000000000000000000000000045a718199b3c87bd8c24c35f027b2b4ba2789a85782a79cc6a924f9e4241c3005", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e383198d18bf4db66169b1ca15010ef10b423afee4c0fca7e42f745b39e1fe4197436ec352b7f1708": "0x00000000000000000000000000000000044c50bd7cf1308738e5758e3f5063ffbacc50d2944f95506b8b4710d1f7a03536", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e386a2f35e87b835c78283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f525": "0x000000000000000000000000000000000878283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f525b842b822ff26324247b6ac5a4f3eaa2bb97ab63a9ca95c2ff07775a1858f0173", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e39a60ff17fca37777ec07e354ed4f92abdd5a1570470994410ad04181deb63229bd98ff39b73170a": "0x000000000000000000000000000000000454cbb80bdac7fd85808d631bc4007c2b928e88ef08e8773d7b26e0acce33dd39", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3a304428675bf6f7e6247d2909686256b09006b07e758ecc128364a926f1223ef04b38628a5a3a5e": "0x0000000000000000000000000000000008f2382813004a234ea40eacc434ee04b04e52977a2907023a2d2cc44d464120574416405ae9e2ded76e049abaac98028161a04e23bdd02ed40fc9e1e0826ff65e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3b8fa2e75a1b9c5bcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec477": "0x0000000000000000000000000000000018ca5164772b835ac12c7e86d391ec217e65f05be0f43b75a059fdb0b3e8a1c44c54e0103cb355b3f6f357104c4cea54675909f687aa106a4e47d741dfde35e376de4ea9ea77e628210eb1aee0c6816cca8de5235e04a861059b889c6b396fbf15a08ca28409640a6ce8108289d3a279cf6fc3f0657b60f3c41f89d04c0e5fbb2dd06a4dfc33d452ca4fbf37fd660a153b0d87011761701591ed79e5bb875960444cee1a8fd3bca977c086368843e54330002df861543497ac55e3818e4111cc26", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3de3c64163d245c278c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a7024": "0x000000000000000000000000000000000c78c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a70246eaa97150a12560dfe00d1cb77f161ab7c29b6243193186f2d02e933c4c4067c46d59d9963c62e1d8f82335ec3768bd5aa4cc268abdd209b779d139d99eca26b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3e3e798a3a6296aaf8d542920fa20b0dd5e126de37f7c0142db98b51a6caa4968922467b42b95a74": "0x0000000000000000000000000000000004739b4e65cbeea7cadf808f0df0154218982008f8cb4ce04a18b89625e69ab6b1", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3edfdd48fc779cd5a80ea94af8a39eb7ba8d9afb913147e67eae84f48aad7b9ce6ee05094fe0394e": "0x0000000000000000000000000000000004fd82c8f29cee3c6170e1f21d2d060586e2508f5a3dc977f2f179ed52d33aa923", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e3ffe32ddffac26d1225c1cf2356a5a5cd7e13c8e5dbee6c4c89e1c5f610c1050131cc58b4d96e75a": "0x00000000000000000000000000000000044ad44dc061d183f5adb794ba6708425fd6a3e1c306152fe63fb22075d1f7347d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e411a5418773a1a2568f8bfef657c69a5c34721cbaa618ae9eb2108566f9a2606cf5055578e0c2511": "0x0000000000000000000000000000000008bc154c7a8b77c508d364f2ad31111f48c1eebcd3367da39f5fd907b510e5e170f2395f3e80b47fe6ce9eaf63553371c59c73b403bdc28862c86ab1040e62226a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e415252cc5998dac14e516d9d6527c3bdcc45105195b8e23480bc0f257308b1f4fef03e06efbb1c5b": "0x000000000000000000000000000000000484993faa382230fb6bae24747cb90b01087b26817950513c4b313168b517950a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4229207fadf4b0c2366c1d734b33c714b0e0e9f164426e66e3bfa97b917b23e5d3674f4a2074f86f": "0x0000000000000000000000000000000008b2fde580d330e81fd2b163a77bf1797f3fd19e98099fec1bbe33217c7f18b77d74047a9abeb7a65811ffaf6ce18a99cb02e092d317eead7302b23e5b99ef3c14", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e42946832d384cb2c5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b": "0x00000000000000000000000000000000208a650412c92229bf1a2eb1c0cab9c133d54c5b82cc723b202ee634e925effa6a3c6d21b257bbfa6eaef65227c3ca8f934d4df946f53f65aee505dfa6b741c852fc1855c2c5d97b41f55fd7b122cabeb3c2529f1e27dd836d131e88f5d6a66a09faca0437ebd16050e22dffe85c091c5a8e24feb20d488444e9b9e7e7cbc78013f227ec6d922254e93c2342a87fe0840cecfa015478fc5ae7b28bb18c66c3a70de8b27a414bbf2ca10db6202c922e1d33359b65c8d4967fc76f926d93f54dd9165c05d424a33d6e9ac92c3863c26aec3515226a439192e9fb28dd47db38dff05fc6645597fb2f300ac88b96e8283b06d99319905bc509151e03dc83748708197e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e42ade399737c4384882a9309f1e5f87abb745dc51d5dcc338e3dbe7b818fd8a9768e27d97e57ec13": "0x0000000000000000000000000000000004d296d443e8532e4977e9d78145f6ec9eadbec4fd2b10158e82985549046fe568", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e42b0e5e788b77418280221db3cd2515ba48cff6c400cf4624b9459eca62f30523972ee5b608e967b": "0x0000000000000000000000000000000004005e13effb82cec8d1e3de31eefc750ea3afb8df4ee1ffc18a66cf56ae4fe178", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e42f7186af73e2c106edfd181c979c11a1d853c8fdef7b18e85ec39bb67ce723130b25fc24232c358": "0x0000000000000000000000000000000004acd510542672c65c7c05d56c4c6424a70a0e426f3899f2eb86751cc2e08ef124", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4315c981ebc9c224e49a94c01d7c0511480422e00ef7030ff64f314591b50d7057deadbd6411112e": "0x0000000000000000000000000000000008fa6bd8e8fcf8cd5be5d5cf808b5b5cb20aeaf43d7cf5551f1b33b0f029120016ea595939a7255c7eac3f67f54c75929152fb73018a56bb468445373c17200447", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e43bb1018fc2bff6592536c5469fd64b2adaee0a10c5936bb0d4c8e4c5e4d31185fbc0c9136e1f205": "0x0000000000000000000000000000000004d7a15c23db646cb253f769875604c28b184a2487b5dff9c282bd65087e7b4238", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e443ad277a8dbe9aba845ea35913a0fbdec49687ebc5b1579bb632c080ce61b02919ba40bcf889276": "0x000000000000000000000000000000000cb4105912d0268f239b12bfa0aaa290903ccbb52e0ad2126b73a4b20c9189bd1bfca8ea3766270fe9df1ba7a4a7298a908878ed61581b9769100fbdd4164b00607282bd520ed3b58e948d1e3ec6d993c607c87f153a9b90954fa973cdf3adfc54", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e44509eb7f7220ceaeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b2347763648": "0x000000000000000000000000000000001072795595ce1298481aeca61391ee534ab7955411342e091fcb079401a784d438d6bacc09599d6647899ed6734cc33a655c56e6bf08d2273ba8464eb1d4a0830b6e5b9e2cbd37299c34a07fe45c6f143aa715e1bfccc4db8c82814dd82a0aa35cfe41a0fab97ce06654fe9813a999a9d6dfb51bc7ab1f35dbbb27bbb3eac4c164", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e44555228869870c2e666c8204234e3e9dc671cc875c4f22316e6a7b67bb8b0538d8d77674468ed50": "0x000000000000000000000000000000000406419ac9e6a0b6d955fc0274eb9911fddac424b804fa29062ea417f05d64803f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4456b32654fe47f91a8ab26aba64d6176b6aa462a2a7ef6252ca1063cf978dcb6f6c64fec81e7861": "0x00000000000000000000000000000000082ed9d00721b2fe294f0f2af432a1a2d98a45cf3d6db2939ae20f5bf25625ecf8148abf367d1fcc88ac026490727eccbeb507e35714b327c4a3dbe404622184b2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e44a4a90b1106c3b5aed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b43": "0x00000000000000000000000000000000a078018b68f1983978069a54f1befb11b0702529b1cb9bb0163999d9bbeb85391f5c97521b3cb9261f89f6b05b6ad17e9d148ba5f2cc03daabbfff35e0bc2e3f0f54ec418763624a46b49693114ba91a0137b37c1e47cc3fdcb2db75c9c4b11c795058c8963e2b60c6f1e6c921a3893414f370b48ad0c2d2d937c7786febb29003329a36786940b598924622428c95d5c41812d55b9ea2f091ad99b2fbc944331df0825186ee2e14875b4da41144acdac7d5aeeda144951b84cb93c5b62388dd57ce304677ff08c2d76d65ad5bc3adacb74b685907cdf72fe0f155c31dc4c8b0472ec9fc5a5358c74ffff03b8712e8dd1e50e93ca0babd01dff5de303a64f07f3a5c975241098f4ce19cd95187485c1b0006584a560c101890f32d65a67e787700fa6c823ba7c33395d2f298934f304b44af030504cf1af0f1a3f29c78442e07508805b2b3d962de88736fcbcccefb08f9915ad1ddab9d1e31782954ef1ea3e622305b166a309fbb4a05d24e70b726218dbb1b5d3e8d4e1488524481032e0acb00041eda8cf4ea9ed59862c6f5ad3a51e7ef62eff19b629cb241a10d5fd7f96d22305b1686b3030de938cfe6a01467a664fd1b42e4f43fab7295963640c5128a7b305b166542492b1615c15fb92c573ee387b90427312d08338b9c211b85a27a20cca9c8d2749a01cf11872c61580b40f227d566afedd3b40cd29849276414c350b8d56768e91cbccbdf754d7f60db1fedd96eae27b591e65d2fc8afb99b27c20b5c97523e781c4c65e7df12bcab25d2f3ad96a2e73c9252da3b889bcf77aecc5a9c9d52f08adf4aa10b316922daa16d396cfb66bf6d3b87454d7a468e19060f683c84672d8f0f25ceea258d980ca234e25ac03cf2d78f925340ce77237844147c88d38deed3dd10c90cab2c1a5b59040baa3c1742b2439d6c4ac83df7da5d894e5c975240a88ac1dc2d87fb2de37a5d8759307dd7cc9281114515ca26876f530b305b1665aadfdadf6d13f6c8eb36db7e3868ba648e86bdb7d60f23677ea6b33788d38dd7b7e450c426b33bd49db5efe92e702e0c799a5adab42be4fb21ed756688d38e0b14f3b08bed993ea4fe1b8ab124190191340fe8de0466ea642fd56511041eda8a25068f57f573d5b152e2c8947c7ab80dead270769184cf63c77af554305b1689cfee594c19a642a2fcd554074c93d62181c0d4117ebe196bd7c62b795c9752253a165c2eccaa4dd8644eb754e3c760f586e935efbdd7c3b629cc06425c975241672d5275044da23dcd085d64949b82c83e963a2bae2230af259f527c5c9752508d09c36f243da599f0e850f3bea8f0cf5c43eaefa73bd9c6a075750bdcadf01d571672f755b4032af1cfa3784d389da711ea341209b86f840784937a88d38df37c92f9cee029f6290428a9848f70dd8f10d519a6c8a861101863cd40041edab68d8fa56e9c4845bb931beb45b2e457162753e65c440d11f83cc828715c975226ca9eedc6f15bb8f513c0fe5a3e813c4ea2fce105febce11d5b89ff01605cefe161fa9cb1c1649080f78f9cf7943320746e75dbb4b1cbdabbbd6a6638204c52b467988d585dd9cb7cebc94d6e56d8b89042ee692b5739f7d78c39a5545ed6723c4d9632bd0c61bf182c0904ae64fe1dde3f5f1ffc532d41fa14e2840588d38ddf4d661801a1ab2efe073a9f35e0acd5c3c896aa28d8b5b20e2e88436e5c97523bb1c1be25aad6bfb7a52d7e1a55fab08a78c2099daf42951adf7133535c97524a02c01e505359a29988f9098c6b1034dcb3ed8af5873fac659a10763c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e44f53fc133ec6c80a0d32bc7ae5d421990bdb847fc38cade9b388ce8138ab4e4ae957fc7ca59bd2c": "0x000000000000000000000000000000000488bc16ce9ffb289186e900a2c7bafd486c3ac4c2c612497a5bf14f8aa2dcdb09", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e453efa586e0ab504d20f2ce6c2c876745bbb399c6290cf4e3ee75ce31bbc7ec11342fd5118b98e3c": "0x00000000000000000000000000000000042c249c9b361d3c490f66848e4ad2fe71438455108b3a1f0698160c6d1d27fb24", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e458263f3dd29a31aca42f0b5c7957571706f29d2828291b148b4b162100ddcac72c507fd8ab69b2e": "0x0000000000000000000000000000000008766ebc87370f898dd73004e524f0019b36a511b071efcc5f685cd935cd6ac57ae2623f940ce24961b8e483b3b00c94e84fd32a5f13a67a09ef5a19d28af59435", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e459cc19119e455ad94b3d04ef219a8970ac5f76658fdee1005b4b7ffee3fc02355f60db1a778f826": "0x00000000000000000000000000000000048c216c3e8fe71b422c34003bcb536257a3ef17928e93792f8d8de4748b81446a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e45be453e8a7bff0f1c7376c9f2afef25e542556d2af805dfa691a414efb9e0fc9a8e33f625294f67": "0x000000000000000000000000000000000440e30e1462871a4a8a38dbf705b96b986d699b62ed53e890b8f42544e3bd7b38", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e45d43cb8401e3564f40cd7a2181289e32776625b9f3a193f749e33ce1bdeb76cfaabece606c7324c": "0x00000000000000000000000000000000046cfe88656d6a99bbf56d216614a02ef9f0182f63dfc21d7dfedacb4ff517f135", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e46374d36cdcac1f68e28e91f200ae0e50fec4354a429a7e4e00f684f594a33437dff6e8c4ed18053": "0x0000000000000000000000000000000004759dc44004f91bfe44588e84d9c60517627929b322b7d00b8979035c3fc0be87", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4642619111762c48be1c7627fbc96a38d3a3cf746ae545f60e2510ed80961537d9b4924421fbb562": "0x00000000000000000000000000000000041d3635e81c3048b1b2459aefff519b68d0100710ff64578709ca3da808412054", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e46b931982fa83f40c009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af66": "0x0000000000000000000000000000000008c009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af66ce26c4cd5d39e3dec824a79059cf0746e3aaed0821017aa493da14687d5e550b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e46fa647d7b60b7824ef63a0f97791221290fd19207cbb23ec5783221b5016afa55161b01dbb0125d": "0x0000000000000000000000000000000004ef8d3f3e96613631bf0c63444db7abcc063f40cfcd2f4b477615443fb8e84d5f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e47bedb9f0d77b46d6883b9f834076b9c1368e7692ec0a01ae97a52c5cdca957b5d31103423cfbe45": "0x000000000000000000000000000000000820d879dee526c91e9a590785b4982690fc4a04d41fb7e49c83389e6848132b0d0e794356479178e2d043755c671a3db6b1882700744cc0f570a84fd33e257e26", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e484f9e39f4f0e8475cce1eed57740222d643b9c92a594bec58f9b9968bfd4d63d495a7fe5237ab1e": "0x000000000000000000000000000000000488c83f9b6b21778914870c7fd18ce9b3b44831ca8706611d6b2fec736a5ecc4e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e489667186afa0e91ca5bc1915da74aba3aadd7ce7b809045d5eb5b73559259755fdcd85a40a5dc6e": "0x00000000000000000000000000000000049f7951a3a51ead847837ceb367ad2166b0dd1411c860fb01cf7ce94cad08022e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4900c2cf5eb1d4d5dce117ad72d855b586a1c7ab1e2e1400b00418037000a81a26d131eff8486b77": "0x0000000000000000000000000000000004027d4770a8fb3ee70bb1d12b64f93c794dae984ed5e991267c7e776c77470f5a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e494a0eac89f0ff78c63b6d81d7d307b9f4464304330a840f5159c78a804dd344c5fcbfb3da9aad11": "0x0000000000000000000000000000000004d693e6d764ce80662d891b0e1496fc7afdfd3470eeb4d703ce721460bb459d6b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e49577d51da67dbbadc86d7e1dba377a90f087a942c0c2777851b447a16af68cfac09c2e58ecf7e1d": "0x00000000000000000000000000000000082ec6d11607a14dd26f32576e47831719d548c856ce4c188091790cd93ba826061ae31e3543602bdd7fe69218e5c8d16c782f96969e2f7e323ec5096ffb294e44", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4997fd81d8f83eff7294d22dea735215a7ac4a2aee260eb25d1beaad4b02bd8dacf87bd611a96c3f": "0x00000000000000000000000000000000047294d22dea735215a7ac4a2aee260eb25d1beaad4b02bd8dacf87bd611a96c3f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4b290c17b4e25a4a36e132f4b16bd325ddb6a3c63562f23c18dfd20bb2c785d391f625f481097c1f": "0x000000000000000000000000000000000432e223d306f0e5bb9a9d6dcc9023ef06edc7717db691cd8c5d85d33b3a1fb136", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4b5632672e4e08b2e2fec50feac8a6c83a3e9f869ce04ab800420b2c80c4310f2de2e9f0adfa301d": "0x0000000000000000000000000000000004764e2315d026e1e02073b27ae98b6866388a0208294c4ca8e4d70e25f4ddbf18", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4b9d785f0afee887423e5d0451428d77e1f81f6f20c87427e355468da3ac8eea9eee7f041871a733": "0x00000000000000000000000000000000046aa3fa5a328b8a928c0aedc22aa88d14e807d2552c31bda8b23f3ac2cf01565e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4bbfbd1503dacab9f01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e042360": "0x00000000000000000000000000000000180e46029cb6daf09d2408e111ffb14010387ffbe77b16539839cbff1473a3a4023051ea9c01a7134f6a3223ea95a09c4dfe0bde5b0eb9ff7169fdb85d7a9bbd73a61a8e0ccd37645a2dd65916d9bcf3b77ecdf395ecc3beef72f3ad5565bb3353dea318de2228da64b91c671dd7f325df63959f9c51c86a36f28ec94126f320709e992661473c1dc00ad7f67b734bec003561ebddbb7fe0db3759b717ad20fd2546591c7794e2cb60b8a342f82bf14b2cfea945671453f92e330917366ed5f946", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4bc05de7e42ebb50ceeccdb6802df2253998f9d4f928b120d51110d1d2afd969b95232bc16768702": "0x0000000000000000000000000000000004ecfd5be6a880094d44062af80777e61f10e15d6a8910cf7222bb10dcff874eca", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4d35c327c115f99b08745476e8a2fb16504c77a75b2dd20b6f56cfb71c87125f1707a702753af24e": "0x00000000000000000000000000000000049dfee84695666c414061c119c231b91511e18267044792868388c73f59306474", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4d699313bc760a036a81f13352076dce1dfe8f357fd805bbece6ec16efabad52a2c24e6824e16315": "0x000000000000000000000000000000000495d056d702a9431c14cc2c46634fcb656e162dca4b5a2100789373a07695f6b8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4e0e08d8f728b4dd32068fb3b800c5df40df16619761b3418e40d9455784b6a293d2425e35ef2c27": "0x0000000000000000000000000000000008831b9437615fae78c29e32df5b9ca228b4e9b4b31eccc8c090834cf6a85c8e29196375cde4e10495687128f72d513b94bc323bbe7dc36f305133ad7cea4c6da8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4ed12f7f95496d053674aa73951219dbd27b3e3fc5847b806c68c1de38fd4f22f9493a461c80e903": "0x000000000000000000000000000000000cd0accc7028daefa6de2f047e4650d3ad13d5e25bb0bf2fae4eb8ff8e216749199e62629f1f1b6e219c95d80577ba4215ffeee870b4c6f6672e2191bbc3a4b7502415e5310193e362840035d0283a5911d358c1553afeabd87ea4d66d35351128", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4f133aa79b057d66fef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db61": "0x000000000000000000000000000000001040ffc76cc196faba27d81c0c8925911628bea264b949bff7a26edc041bfce66af8f71fd7d5dbabcdf5a640f194881f3f16c13e2bc18e54cacd08dd60fba0907ce00e404cb030e7bfb50b9615ea9a2f8f75601ac9f6128d1263a7fb5d22de741bdeb6ff39e56549c7a265ac798934d66b541c41c2e2212c34bd76b29635b4cd23", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e4fc324df3bb6d99258bb56063a47ee6e4a4d0bfe444682394a1e4657fa39f4622f2a0285689c1b3c": "0x00000000000000000000000000000000043b839ff2a9cba91f5d0a511651c76f3ae7e0eb8bc76d7862338f987e506ba6de", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e50004b04910a1297929aa2bfe7b52500b288c943b7c24a90928cd8a6f7ec8eec44763d9f74198401": "0x0000000000000000000000000000000004f2b7e775b59951428fefeac1c8f7f40b24103e02315552065e37d58ea80c7d77", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e50079469344a3846844f55022b2b8667129c167068a9c2a6bc292f2d312336bd98339d686b575a1b": "0x00000000000000000000000000000000043e8086aa5e41114ace08f4330aa4d5adca61f5dab191bba7ab6b2596f1c40c18", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5151486ca217f604d23f678af47c89d76031edc91e43784bcf9991b131f957d312fced2c5187fb47": "0x000000000000000000000000000000000450e1946cc920aa86edf541dcd4bc35efbf4b28671b87c68b5abfb22f655de453", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e51db8a617be61c665e0a4ca74bbb4da39c79954e7875519fa67049795c02a360412f3ee41a020506": "0x00000000000000000000000000000000049406aac741b57c529a2b06b06124a2a9b8f8374e072e4b251b13a5c0cc9f617e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5296f5f3e605a0e3e8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e": "0x000000000000000000000000000000001070d7ff9f5cd0e46762d7d7d1c8dc840a4026755fe13c51237ff8601377d4fba36964958c102b007555e5fbd10a3f98ee67fb2bc270fa0d20fe2371916450079b86929ec01fdfdecf2c5ad0c4f9b537e65084f053980fa1215fb9377dc325f52d06b430745802c7c8d5cb3537dde6dda1c74dd2251837c781be4e0aebfde8d673", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5361b1ae059eb11e0650a2e41ea97b60bbd3f87aa30d605562069075deaaf79559959230928a2487": "0x0000000000000000000000000000000008463fb9341e83f58071dffd0feb3915815e4f7055c74f0e4ac002214cf06d6588fc46341527cd1a52b60dd5884d8ac5aa272c27cd3b3cc6750ffa51ffe6b34ab6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5439cf6aa71671f74608fc7527698d3f4d4cfcc6074f01c2ed59112ad670dd5206b3658bbb62a073": "0x00000000000000000000000000000000042aac721ff23bb9448f8ddec8ecd159961a23f604f8fd22d729c3390e9f36f843", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5579d397caf9629d608aa0febae80d8c228709183cf997bc87b0aa219cda0928408df22ac7ffef39": "0x0000000000000000000000000000000004bcf0343edbf88dbd0b2d302af4a027cf7a1b45be2fbed9e9b11b6bb6bcc426b6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e562122059d1dbce57ca460cc927a04fbc91f4ddda54149556d1a85196bc753d054aca1fb7621e349": "0x0000000000000000000000000000000004027b1e50e1acb6c1ff8777599be3350bbbd0236fd3866c367f420393d3adee41", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e567dc72806fd2ef9d453b6e497b6a89979fb34eea715720d37c2381c8c51458be04296fd059dcc3a": "0x00000000000000000000000000000000086ca5cd252f0f61e8a9c5eb72ad6d9452fcc1de451f7bcffe04cee9ce73c8ff0f402d50604742f5071645e00cf27f318d0a0fa805bda1daeec21e11ff9387e923", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e56cebd3283e0ea933a3884dbc6806e8b4cccbf2c407d800c12141c3d7cacde442a649a6a2822ac17": "0x0000000000000000000000000000000004f49bb2abd8dd96beaca34bd5bfb81b5edb5186922b92c3b1f5977cc401b79554", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5786fc402111e82d5202845d849d9eb6a7e5a414492a86d205be4a374ede34e98fc2440de4809a3e": "0x0000000000000000000000000000000004d6945be0cef12df3e9d25d4bfed7c4f6fbe980487ccdcf13891998454d4c7d3c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e57b1fed518565181aaa635f88e75ad58af28925d0c21a804d87a449469e45970c3a52f57aba7b366": "0x00000000000000000000000000000000046a3770dc90105517476a48c8280337f2c1e39dba204c254f7bb51c8d4ebb435a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e57c41eaef46fdefb2ca8e96b721f074e95a3f7d994c370dab688fc85134de7e2e7d4589d0a306c51": "0x00000000000000000000000000000000088e4ac154f73a0576603db7786e98d6a1db1e72e3a2b32d2540828395dbd3f7d786d678feab565ecb54f78dcca7036db237002aa86783283b8721de7611d7fab2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e57e0f36f0fe2bdee54efb33a98824d6330a8f074481df98b5123305473559bef960180791f849252": "0x000000000000000000000000000000000492a409f971d4db36b2d2d520adc5ea15c5ac9c012d22e4e551552d250aaae57d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e57f4780677cf709b4ec0381e4427ed6567f7a5c328288ced36c33becea6ececd8145001f4230ac1b": "0x0000000000000000000000000000000004564491c88a293f54f2fe2cc09b0ec63f226bc77ebf6df8f998fbc7551d0fa10a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e585c0f93d15e98cb42f3c525c66f2a4eacfa88479f7537670d2e1f45f4ec25703a111f5f003ba15d": "0x0000000000000000000000000000000004fe57cc05a0401fad57f17da9b903ef6d679b4d16c107a89f7a8c3da798d10919", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5879c1214022b88dc8566f6d3669729e877cd5e453d59f6be01ae6f31b7a9c9925160e70072f7242": "0x000000000000000000000000000000000434a2536cdfc1e92e55a4f4c1310aa2cb76257a87b0e66cea1f2d392c7080be22", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e587c6bbae1bb420cf2d0eed0f21b82d4b15802153cde2a229f257f01d003694b2973ef785a734766": "0x0000000000000000000000000000000004603ebd73cf850b644af5650cc070cf1328601427c712b21aa9746609de2ad447", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e58d8557741d41ae44e4ac8070fea95496b63cdcb6987de88f63dc75a295eace6ce5079149169300c": "0x00000000000000000000000000000000040879c078b9026ffc8f5b7ca4f1af1ff0f51c592958f24b43ea5433a34f0cac02", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5a5afe08a0a9de9ed6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d": "0x00000000000000000000000000000000186817038f23e3b1e7d91f641929205495b7be633fc2247d0bcc5a6f9709a8f82d68c1fc61924efb992b4e4c2c7a21d528dca21d3073fd304f536fd99a5cf1794a6d6f646c70792f6e6f706c73014d0000000000000000000000000000000000006d6f646c70792f6e6f706c73004d0000000000000000000000000000000000006d6f646c70792f6e6f706c7301630000000000000000000000000000000000006d6f646c70792f6e6f706c730063000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5acf1d24617d25ba6a88b4d1ab30ab4708521d6c6d480a858d92692c0b0cff67e1a6904e23b84112": "0x00000000000000000000000000000000041253640274e26277dde50bc1d72ed0b3f627e4c6b66d8343d4c52ae97afd0f03", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5af3c641a81d6a63eaacc14e67deba7935dc28c86bb8b6bdb64239065b718fed6b8691ce14163350": "0x00000000000000000000000000000000042c01bce1cfd949c169cf6d216d5c446a8c947147b5b7f128b6a46dfe92f90f00", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5b4c4e58d29949859a2cb674ea2f4866664769a1663fd6aa321d9cfb89b67c402c881891700c0f57": "0x0000000000000000000000000000000008801df817f435be03321e6a77b0fab3183b9716117accc0f3db95c9f6f9434954e04176c772d8e5b3758231c8155b2265e9522e5047b15f388a23cc707767923e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5be79f90404ad9e0e4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f72": "0x0000000000000000000000000000000010808652b2296e43e858df65b69d5a3942ba76744dd8d0cf390ecdefc89b3a553bf4243300b12f9067d1fcf01c8e05f598ec2dfaa142a33398177f8b6e32ecfb2f8e602e63afb364ac583747b0a8bab092d5b20ee98f0495ce7562a8c992ac9f175213e3c8881ed30ead22d177f5c25c4cb8bf46cf2d04a8ce55ddbc06118a9516", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5d3dec38e02e37251c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea259385609": "0x00000000000000000000000000000000402889d414f8bb29201637b8ae394fd131642a3eb4764a82730e494d6e60a6c4bc36ed432555d82a6fe15f2517dc871f1d02c72d8d5aa1bce703288d180ff1fdf6be86d32d322797f67dd5d386d29d8285cb32504a767956fc58ed8f04ff703c4a44d50e5b2db8b483e5731d39c1e71f33d6ab32318c144f5dc41e57d1d21ee779860a5fb3fb398d56fe3180ba927cc0f0c9308cac7f6af98d4fc7624627343c4aa243baa53ed09e1a0a8879b132121047f10b53b52b4e8111292a196a1513673745276fb671d5e24c15c73f6766680b83e94bd709644fec1d5829f1126ef1fc2a88508e0d4bb18e50ed1435a4260541b1c53ed009a64801727c195d1f81c08fdac48166c755e708cb83a61db9dc635e91cb496e2659e07fde8aeb09130802010e6a1241c7ef9541ddaad26287d92df0abacf7ac4a7fc4df046e4b866c05db4aabf657af299a3b7d16d7c4d27876099924e5905d4d85d683988726e31b25037cb612cc166f2df9f0fe89f79e2b568a6e92d61ca5f5f53050ef8744edf74aced0fb49820d872869c2370f72f871556e9584aeefb7b7de62e6559c69f1503cbdb545594e4ff12db88b9c74fecc23b4a9bb35e999a5c9a6424ec47f3e0f5529fb655e7c49a3654ea5a5313645948de60749792de736cb3870da7b401e78734eac3b60679d98218b5d055c770d3a2a406e2e56a97083100bec05cb83f530632dc8c313", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5de66fa01fb4c2d708b3b1930f36bf7fa336c7abc044e75fea45cf1c903081e7e0bfbd664a80093a": "0x0000000000000000000000000000000004c94a444165f95b45857e4bf1c4b0f784eb2e6f16054a87dce443de41c6d09c1c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5e25f5c22e4254863073c378b0833da59cda1d49d711f37c9ae20ed30dc3dbb842ead63dde578331": "0x00000000000000000000000000000000046a7db4fd5d907242e97c2db57fa12f1eff6a103556f8e99f916483ac6674c372", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5ee8405cff42241194339db8b404ea216d60433f00ed67b0cdcd9e29d21355615d967161db0cb04c": "0x000000000000000000000000000000000414b04bcc309f1abd5fae50084923f7d14fc5b9eaf257c0e2c5dafcd83e3cb363", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5f1b8b6e45fb190ccca9cb5657907dcb0bb01d335b17564e77994536edd05ddd50524a9355c2221e": "0x00000000000000000000000000000000046eb0bb735fa04cc282b87141ed4d60afada62fc213bda5ea0d0569c2a8c25d25", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e5fb6a4114e90fbedc87dd7c321ad3dca39e53d05541bf9d17306d681ab556029b0f172156e12b603": "0x0000000000000000000000000000000004e8fc1e37b0b57aae49b99fb66be1cd0454d275d34a1c031ae4b796fa30d38736", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6067f41bd57795d6945e90a1afc83f0c74a3ffe96b40c4ebb5397af04126bc2db23036c043be4a63": "0x00000000000000000000000000000000081aef0e83444feabcf8eda628195f0d756082152cad2aaea5dab16de839b50931c40595c253aabacb254a3a476c0ed1b1fdc9368157d2e6d85dc38f5eddddf13f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e60707c14d6e8780e128e3b8a2d3b98071ba399c17206f84350e65653537dbbd646cb5908efff9d49": "0x0000000000000000000000000000000008120460743583c4ebc3076d422b73bef41b48b87e6c07aeecb07df3cf95565eec4ec19498a19021a78fbf00ef07d366245bad3cc89f5837a7004b97a50c4a5e0c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e60b67be86271e2f36e99996cc6c41e39696f7c3bc4248e548473b68fe2ba26567771be07b7eb5b19": "0x0000000000000000000000000000000004aee302e198305536eef798b55edd01e28516bfd2d16888597da705ee0e74df0d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6244e474aa91e041ae9749dfdee466ed67835efa51f04d74db27d75e919d7050e4f5b7f481f77a14": "0x00000000000000000000000000000000041cf675676957827846bdae1e0518c92b31a6e0759b3616955445ba3cf8a8111d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e628acd4748784be3a2da2913d7db19baf0a41dc40a73d75bc6001ce1691c3ded78e4e86387881b4c": "0x000000000000000000000000000000000c8ab2f02be4ea327d42477029cd7e8ca99a1b1ec34a9502cbf42c1701cdeee77438bc883d8fb7ae97eb3a7862cff1252172f4a901264c84b7feee0a900a64f77db2dbc35ccf086294a0d24e1091d08ca3b5c2a487071c4fb54070e666cc99e02d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e62c6144c430228802e62b548856a9ff975d160a0df8219bd36a7807620ac1ae2eeeb34498ba3e470": "0x00000000000000000000000000000000046c736a063c16e476c5d534aedf7e9c95a40f13c95aceb085ef74155d4b37800b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e633914b3a4ceda021eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843": "0x00000000000000000000000000000000186a92b1cb54e218fd9815b34f7a3a35ed39165a29edae89c7086040b59d074c725059875dcee1d4a9908203728cea5bc20ef93a366beac56fa161e04feca0344316a025114b9898b0e78a9472f31364689261cfcb35daf692c62f36012706db1908ec5cff0e253ab3a5d73aa4cf0db459f5128ed41f6b4d3dfbd99924f4346c581c6861821c1863896ec24a799c6ad302e7173b8674e399251bcc571e4977c7293cf08a632438014746be9061a9a74ccd8d79204032cf03d8fc605d452647c133", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6354c3c5f32f80e56ce8f0f322c021ca4991c83240d0feb94ad1678835b51d228999252bf9223e49": "0x0000000000000000000000000000000004f954fd2279cdc545fb8b89133ef97c121308e4ca8e26dc2f7d3c3d9b2dc52dbc", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e63e8632182788bd60a439f839504ef07c5cf8daf62beb17546e808ed1026c8a683be8207245f300f": "0x000000000000000000000000000000000809f7f25aee06632399bd9de5e4a311cfbd1846ecc34f8abc3bb8118a45c98a2eb4b4df0af75ca82e3289a23c6c32eea3d2ad337ce4d335029798b3735c8d6367", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e63f4f567548c9f8c2843d91b23b106e3020b7a903da075113d1aaca1db7ac30e119d6250fb6f5961": "0x0000000000000000000000000000000004d6ba1aefd3bd5f72b993e0b6c5f9ab818e96e654e2500b1a547f5104896aa660", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e645a2111e24537a2c088a8a35f9a31008c7ac0d4103078bb14b3d50213e4b92bf03ea98c081f173c": "0x0000000000000000000000000000000004ea4565b84bbc645ba42d3ce16887c42062314fe6aca7ab36a1fd942d7f31c76d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e64acb2a5e7697e7428778f95bd35e3fec4ee72a0d252c47097380c3ffdf93a9600b364ea119c0502": "0x000000000000000000000000000000000424d573f4df9151235e457956765e6446cf33077033bbca48d8d5c6c9a1d7fd33", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e64fffce989e2fabc6a0051ef580a2b9dd19a368b82ec20f9a605b0207f2e8d364e6c985b5b2ba871": "0x00000000000000000000000000000000040a9e884e29b1c07ae4918e17e7ec48bbfe9622cd9badab882d14064c8d672b3d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6553c10b93169dc66e8a3622a7355ab70892bc48236c461076d5163f55309b7e5d0a459d17c6272a": "0x00000000000000000000000000000000047a1b5cf762b0c34865a94bbfb0382ecf0cb030a97e582c4f219c51441ec0b805", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6670b1e816a2cedaaa2b3e0a8702aebcb83d552838a17902b2403b0f16c4e52a4514fe02df532e3c": "0x000000000000000000000000000000002460a8e45eea9783d521beeb12cb15c6e9094e5d755749b801ff1a532d0934a90de88efbf462925faaafc04b00555e946a843a6a018de2e47cfca41b0804a9f128aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164aa5cd92797a91f08d3feb5b497e3e329800710e13726accb52d2cec9f16b0164", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e668bbbac68a19cb7a02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d55": "0x0000000000000000000000000000000010f836649df542b24a1b63d80916ee743d4734640aa796648649685dbdd430c3626418bc819ab0a29b18e03aaf851463e3718bdb8649f5b864ce9654febf64c95070610bb9d4abd640e545cf56c9be0e8886b9ec274ea2e4d7facf8dbc575a9447026d79399d627961c528d648413b2aa54595245d97158a8b90900287dee28216", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e668ce779b7a9f3801e76b9da6373b204c3db21d2a7097a79afcf32f642a516980ae26c910e70a35c": "0x00000000000000000000000000000000044e7dac693f453f3c407caea7909b1f56c8385dd3ea46059c9b0cdb32c19fba3b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e66d850d0167dfb3ff429460ae52548e754c712a7cfc75f1bf7c9295da165293ca52ccc686db5c02d": "0x00000000000000000000000000000000084613a2044c0cc5b2f0faca94f2d6e7b7533c1ca3610cca54ba03ab9c5831d82664dd9ec1480c8ae7a38a6566f4634c7f1b5253a0fcd426b3c712d8e2779ff71c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e68180e8198681ff7e0d744a6f291a2dc1e6d744d5ae0747e314b046739be170638ecc185ff4a9b5f": "0x000000000000000000000000000000000800c703a1cde92ffaf1f8312c1fdb3a81140f7e76789d55ae1f0683025c428649541a4100aab4ff5eed5dbb5245c488365a4ebe149b8c3d5462a8e7609dff226e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6823ed8df7d5f458c46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e51": "0x0000000000000000000000000000000028845c9d99f3070604aeab0b883b0f8774de633c1e7b91a0376df2342122fd41489e7b589d0d5c36284021ae227a2e2be43e1dd1b67c0df432648e5026dfac6f43c0f326fa9866f007e8ea4125d5364b3d7061ebbbd9a24341c40a3ad8de3d113c809246069a0bc7cee32210e5e5c1a523e10db11d0d86abd29a3979e68dc01725d6e2246ffbf94311de0e749da628bfe1b40ec0251caa056fc6c2050b09074a3d8cf5dbc7c0ac18cccaaba93224d0c254df33169cf4d38befa64b443b6c4fb75b600786fada3d88a3e440751d50f3e522f9b7b28dda4e0f674c9faa24360a082e7c50145c707078b4d38802058b2d16fd80748729aac222af64be9e55e854da2aaef5713b3583a5730c08c16d252f9fbda97536c8a26168256b998f7e9fc1c60200247daf7503a9b41fb6c52c11c760f769266b44fa97bfeea3e0c68f0e3db04f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e685887d42c2579e03839e4be40e252a56e2d7c8e89a0c8eb990df5910714fea61c6e1d3b1c4c5502": "0x000000000000000000000000000000000483dc7edbb29fe81e5e29f18ee1c35a90b6aad5637057e3087699d38e7eea7394", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e689a20d8714b51d538cadf9abf7492ce1df73d8b7ee82e10c2a0571970e2aa5ded4b9a6f91a49833": "0x000000000000000000000000000000000488c3d536bd6f68f296a34c8c3df53f1fb5321622d5f21739b6a76670500e413c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e697ead568e820ccfd2eb07f02043788e254d9e2df57be11566d241c56302b91199b4647947af3020": "0x000000000000000000000000000000000852ff057f98f0c1bed31b2fd1ccd8de4d4acf957e79b3f71eb69820bf0dc1d22d02881d4f53d1205e5bdf3864a12c724927270a38a1139e0d6434eed97b930163", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e69937a5fa154cc0722a58635dd1a211d33750333282985df00d84e87b160293d6b39e89ea4bc7d67": "0x000000000000000000000000000000000476497a6036a1ef7d02ede96d44f39094a5fd50e69d524990946cf5e6e6f1da2c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e69b743ba383eda3afe7d71599a2b67c5085142c626641ccfc1f44919270fcac28d2ecfd41e0c7e3c": "0x00000000000000000000000000000000044c9984b5187f51b9b35d16a7df5b38a2e069e568bf813532ba08068477772205", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6a2edd04aff025a00a71c6a0fbf9b63ac089c5395bdea4917a84aabb3475d4454147c4d24ce1013a": "0x000000000000000000000000000000000c2bfbb8610a814c9052c287849831e4e28789a020afae5a23c9a19d3f37864a4986505f7c520a5d79d531e99903d5a18615f4510652500f511c8052d8e6a42721f64689da7688eec693a364879994be8568da0f7ff5223c391b6b58626f827527", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6ab589167a0b898fcc9f261e20561ee1a137a7c03770706d09a6f85e36e7a313f04d92faefbd3d43": "0x00000000000000000000000000000000040002dd621e14bf09425ab305ae1139310c1c0f78f2d3632c7ea507feb7f82900", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6b6157a13ed645fa040298f71f02d7b6a67c0ecee7d7a62ea51dc6daecebf4dd9ad72e0510537a58": "0x0000000000000000000000000000000004fab7ede8984030252e6392d2201f91bcd558470d35785c4bf89f6d7cd86c6e66", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6be5d0bab82378087042479798003022a5753c8547cb0de8ef25e2471e40889ff3909fe714e24c5d": "0x0000000000000000000000000000000008f20ddf4f2db1f9f800d70ce19dee3812a5d72bc275f413de1ee186ea7473bd18e0169ecd64ca393045cc15687b0f3355f7c86eef2d25182c731a45e55f2d165c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6bf9c9353fd020348c33b686a457b74f9b1a61b4446404e522d122064d6713ffacee88bfa9a15861": "0x000000000000000000000000000000000438cd946bf9de9d576d29db5fc442e5078a03f73b67ba76d8717634b7be4c5a23", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6c4d2026575763437cdc1a6a5a7f23437b6528edcdf553d0685f940a4e6e85579727ef3dc574563a": "0x000000000000000000000000000000000c6366490cf9fcc50f7edbecb28e3b78330a0e35d3e073cfb3538ae6540f0542b0815e86a39ceed754266101e55e352c131c877e72ba6f9652dc45fb3fd3757be4373d025abe0b6342867c03f3772e5e3fcfa7b13d7d5451ddc934efee37894a6c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6c53b7f96dcb583d9c2b14c09923911fe0ff6918b7c7702a91762aede2c2cdd0f1f0bdcf7b9f2a5a": "0x0000000000000000000000000000000004a56bd842d168e9b1eae2ef3d1f6d323b9bd4b8db997ffd2ff52369e5c0ba5512", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6c7206770c39d9295a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb9934": "0x0000000000000000000000000000000010b3c0b3afec6c57fc99dc2656c38ecae97b5c01f2d44bc9da56714141676e3ff21239360b36af37935b370032d2306b6c99c2e06b0312c2de4ad61c263b82886c067a2e439cc384440cf187331543175270b479ba695e2c4d6ba9528bbb6be460f201e84471e485a37aa3988c97ad57db1297d862ed5405d864708654e430260e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6cd2b2fd45e2e3d0702a6dc9592ec94ce9e1f07e2a0559d7f43f932101bace2400d0e92419218732": "0x0000000000000000000000000000000008befe117ae4a987baebd13ac5c3b611ded994a75dc9ef2dfcab5071688ec9e2fbbefe117ae4a987baebd13ac5c3b611ded994a75dc9ef2dfcab5071688ec9e2fb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6cebd0b9de064aab0e038990f47761a17f45c2bb01c4c7746f4ad67c7d0c1dfbd6915372faae911f": "0x00000000000000000000000000000000080c92d4e41eddd3bec4ce4caf3610213e3b3b143a6c0319766961aecc27e124ffa7f6170f731a0acda2c9edc8ac9fc21a0b33e448378730b2392cc0bb76b55546", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6d301a445678938ac43aabf384c6baf54ef9712a96be7c46533b538c05d4e6c687fe09b109664b28": "0x000000000000000000000000000000000875a6c848edd2d131588ed2fb322ef45909d4aed3b7ea1197fce14220a68fcfe3611f3cd11a51748d355ff0686f5c5bbc2a7b0e91b6efa0fb4f9aae77c53942c8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6d81d41850c8478a76016fc20a6457ff8953bf29686c5698c28bbfa860669ddd07b386c910f1107d": "0x0000000000000000000000000000000004cc4790e6ee2ebf4271fffa10d4bcc2a4460ab377a49ddbedfbb647090c6a97aa", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6de5c15d472fd831e4e00e63c3647fc8c0a3d1b163ac988b6f0a7c3d05a01e209d4adef8e285037b": "0x00000000000000000000000000000000041024e48276b150fbff7c44baddfce92ba5d90057d518d3b29bcfaa421c13ab7b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6ec642500076ba25a6c5f0595d6ed85d6260bc682d4a68a4b4e605d43c67d56f2765d19698549772": "0x0000000000000000000000000000000008e541547dbea2dac6e485f82ea71b8b1f6fb6696aa65cab783b20f9a6c574e6445c8186e944c4df5cbb64eb1080932db445d11f69fb4da145a98d0d6aabb4c009", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6f3d6f5d8945a2a9d896f718b4ad053ba53468ba0347060b4a80f03fa72e9c14da5e2e7ea80e3f2c": "0x000000000000000000000000000000000470a8fd1a49157402789a0c495dc9c9d12e87a64805374661b32f1d715ca22f5a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e6f9bf1c5c47f9bff1c378d545f64248bedae80ec34f8f29551fc9f814f8491f8fea50f10fff6e229": "0x0000000000000000000000000000000004599aa7c71c2716d534f7f4ec936d9bc547b4e32fad199466a389b09b139f3f8b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e70023b9d2a2c164748ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54": "0x0000000000000000000000000000000048e4dc1df8790688cc413fea804c4158d1142db0312e091578306e1ec9fcd6bb7772ae12a9ae7729206f6988826c71f0f3076971462d1ac94efff198392464a6574aaa077ac4202f4f7e1135489106099452441129dc5aad89cd5dd4335918fa3dea08268d10b6dd05b9db75c7b7abc2b95e9b24d47f7b2a6147a56dcc745a0b4f06929a0b268c8a51c457e031e971ba6d1624b2ecccfc94185a8b593549ef7b401ad58fdac86f68d5a3a9a8e07163426d717ef0426d3e03604ae3bf4ed481a9236ecbc9b76728dae4396541cd517384e9898d5bec4875bdd1971c97041fa281119eb6835f83b4313045b2a156d5af104e172dc687b2bd07554ff3699748c4105016ee0e830501e14db6f33efb672620f030b65bcd30a91152c9b9abb66f4c117c8a1e84fa7220a6f820ca42a6dbe689b545ba1def88a7f1bd98d7aa46a9ab742ede38c0e7726f26fb4ce2b3bc8a17ded6197309efbf24d70d0425728eff597d50e28ceca047d61c081d502fb5b66527b2dc7438684d607682e9dc082640667213ea6f0d87d39b6b348f609c20246f065864972f409b809e94636fad2e6e779059809275c61d0a44ede0bb18a54adf2b684d44d1759e516e46634aad562fff1c2f78905d56c02810911e1ebaf201ac246eff919f4e71a5bfa5b29eaf6819663944426c1e2855920b16c78a37f7b6f480163f2a876a889f78b1ef2d11ebc9fd14592cd1a4b07571dd2c61dfa5ffd65b190a203d082e9176e791a25bcf242de28501d41ef941dae80043db2c5bcecb8501ff3f159ce810271ab6fdcbf979de7cd373", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e704211a750c9b855eed08a5b10b1835610d66ce4fa273c8e2436b978c9f65442efb6074871b48a6a": "0x0000000000000000000000000000000004c83b05f03d7e0511d29dca7a11f3631f6a0bf373ee6f96bf99882421dd261a4b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7061508d0facf9d35a1a549172a49f7591155007c51680ad8ad77571cea04acd1b0b84459e779234": "0x0000000000000000000000000000000004ba65343515a46a4aa9932cbdf0105d123c9d4ba9bef3be885c46f52c8c058d66", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e718a792663e13c111e015452870e49b4e4c3e054556b19683e8895586bfa58638a74a5782ab4f712": "0x00000000000000000000000000000000048e57071fe8c6591960d214a1100419ff2e2e92d4989a99646354df48ef91e664", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7214db08aea29f4c2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57": "0x0000000000000000000000000000000010527638f35f3b999cb645e1e70a49e7b798a89c36b289bd366056d39115c18ae420cbc85619baeb354c068a5799d8ffa8b822505221d5357d7e70f2a3ebe08ea11ea9ff7a769863d12182a9439c3666f3fbbaedec8b5427d3c3e93633cebb4ae00da80f8169a692da1a6a0bda931750ed897b1ef4b0bc9bc6e0cbc906981e2b6a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7231a73eec660398046ff960b0d51db710b8ca414171afd47c9612311b69fa9416622dfb42a33124": "0x00000000000000000000000000000000044f00d8607ea768fa23a0befe7cead74f5f99102a70f53aae2cf68922f526523e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e73006ea8baa58afe58f26dd10efac24a7fd1813d6aa72a8e60bee976f7da28e492ad033fc1822315": "0x000000000000000000000000000000000453b9577bbf862a61bfd4c7302c3a43bd26a9b50370e3cb6586c8e267c1b87180", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e737675dbae64b33e3284bc8ce3083b62e671d1c5bd61db5b3fea95a77967341ca8834a69cffcfd5f": "0x0000000000000000000000000000000008d21bad21a85a2c91d823216610c964d9fef7dddff9f1864b2a7b4a8e667c1f5326e07a9cb1d3b8827960bbbee94197ad2204ea98db2d54da63b57bd9eac4374f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7396af96b1f453f59e826b5434525d00c118f3f6b0a29b7f432be7bbd18659d472c5f07298e76949": "0x0000000000000000000000000000000008847074f1fb351eaa06337823c68f2a9fb28c98db976bc5cc16867e4b84bc1060b8e7e832b85afd9cac90cf30ab4477265f14901bc0f25b2142c2e488bce87352", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e74083880a0b640654a003aeae28534daddcc861d7d3e91b576683544217044cefcf4803ced1fbc69": "0x00000000000000000000000000000000049ca08cd9b7fdd71d23d3a07906fac5a51b77c703f290adb2b5099b4334407913", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e74e73ec4f7c76752d65d5c1484e5faf8ad32907ab729add8ffc2ffe0f29bc18015bec2c3f8ac7c66": "0x0000000000000000000000000000000004c99cae7c82bcc7d4c6d39b376a3f9a61242bf4ff1225866f5f93acbbf8ac922a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e752ce2fc0e55cd08ac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064": "0x0000000000000000000000000000000024463e61911efe5b07ac64fbdd0b388a7b9569d067a6a34f01ce88bbfd9357f29f2f9c09c8a70b63d73be60dfe13947a17839970667250b900c8560ed4d042841d06beb838b0ba3114b2d1342cf7011c397879da3fb4b4ffd4df534e6948d4913eb8270b6d0325eac9f3ffd34032017f7848eaa460ca9a96a90a5296e34af91f96ea073956416e6c3fb74d4423f458a028c9674f147468dc0e2ca6d2c140bcdf4d3525a2d8318f0a082d428d90eeeccba905e0001fdad3a04d6abe49dd79e1518670375a0d07a2172cf390b17cce40e34997aa99c1762e9fe3f96a91ed60c7354b5767532cfd7c17f35bb22551c3364d9737749661b25f431f04df8364c9db3954dde48b0a82d440116e0620963bfc19d1520435a7b64c4b36e5b258be8a9974e0", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e753ac717444b23dd1cf3e5e0a3f8f198a63f5f7284fe493c23e88161d92d2cd418e52d050e3bd22b": "0x0000000000000000000000000000000004b0495e49f3241a065bbf17983665997e582b1535c5410530897e3889993f711d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e753bb535f9a5c087d4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b460": "0x0000000000000000000000000000000024e2dfbb25f8e8e6047e14474e054090c283b6c8d34fbcc7370fff8292592f934eae8c6dd7bf2e52a684bbda1831b6eea8040b7fa459da6a487a9988a9d84f6b0c48f5c152ca97d46d67467f3b6c7e2fff11e1f95abc0ea7298255c026ff65d92b280daf6efb2a16974f928da1abda06f2997f18a8db3cc73dab3cdc97d13fa52094082abb5e84b31a7cb7e0e69fd711f013ac426d62f1e157b762d284ee6efe2be6fe75fdd65d00f6ea16c22ba1ce89e45441b80c597eca58690664288f1ca146f40945c32b5bb894f311b2a680d927a1d26080b3b4b1c8b5bcabb196918d0e2da6cf293e01355a99ab2429bc7d9f56bd24beb526079ac3eb0a00c3c70e4f64655ad5faadcc4848cc8acadadf39c4a9893e13e8993e270364eba8ce53b8374c6f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7571a6ecb5a2dbf4548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b": "0x0000000000000000000000000000000018f87441058c9c1d89f27cd68a74ced729f5393936f7c041de6732df7217d17cfcea4cf3795941a47d46c2b433ee328d7d2a71c85007251569a6e1fa5535af173dd38bb685e02bad927a5425d733b7f89077e5b2b6c09e8e8990c98dde3275067c97a214d9d7e4d9756f50d6b43a18a8ee671cb1512b46f2c2c8c1309694dc75bfeaeb9d2bee9133ac09633b0361b04567f3997d6aa139a401c12f929be161d9f65c5c5a4a025f3d8be84fa9ea36383c2cd168c8a018d50c88a34154afe9ecf04f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7661b26815a3370c9ef2c74b5a6820a16eb04205a9d177c4244a94cdcfe1275039ef8704480a3905": "0x00000000000000000000000000000000049ef2c74b5a6820a16eb04205a9d177c4244a94cdcfe1275039ef8704480a3905", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7680539dbbaf0658cecae006fbf10a81337d87455340ce6112b125a971482490e02d75a27bb2c33c": "0x000000000000000000000000000000000478c0205b88370e3af02a0d22ff0411cb0335a823f02f604c692a9bb1914f2262", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e76d10d82508ddae096e24e9b5ab82dc275b82318a52cebed1cae3e25be096d5f288229b256359e43": "0x0000000000000000000000000000000004c2de6256e9ff0ba9b97f862290f69ec0f72b31fa0a6843e0175e9e81a0165d6b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e782e7be4e56dc7e9ae963c00a7c164fce3f4a8ed94ba0a87e83cc1a7b192726836819cf1f63c522b": "0x00000000000000000000000000000000048689cf01de26619d9e77cfb38911661940f6fd4b6379d8bd5558b8b967d51db6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e78331d8cc49f0ef276f45a1045fe47a639befe802be7eeea599080222e2f45fba46492039609cc07": "0x0000000000000000000000000000000004ce52792eba24d1a81f5979865ac647e16fa810d48fa38b2840de291115171e06", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e78401030f0261c10a49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e": "0x00000000000000000000000000000000142494641f85af0c7f9d2e3c942fd250dd7c2ecc7e5dcc401fb3ebca0573edc571be6ac75cc8c52d2d3b88dd29c0352b579f4891c52f76508269f2328fece4d07d8c600da2883fe70c639e6375b81f45d5225acf4777c4586a3672c2568b9c676cbd65fafff9dc200e3945e786ca92ba36a9aa333b09bb500b632e8827f8f7ab380e8b9d19878dc5c50ed1ab180f4e76cf7e208851fc6a869b28dbc1ce6208dc0e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e78793b4db20d123c8e111a2e445cc0f64b5809496887b3130718d969db6637c0ebf1118c39b15c55": "0x00000000000000000000000000000000040a16d6fd4dc2954c449699e5f6e3c7d2f0dc64df5b8008135fd60eb3eac61e6f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e792e04f3dda19263a61514d5cabf81b3f62650806870ad83b2e5059538b846b6dd9963e010566a17": "0x000000000000000000000000000000000446105c0b02b08c1a4e094e2bbc42fab06c13cdd155bff92dd844d3bd727f2612", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e794c7db721956af68a56b1da8dc3f4bd58630c15f5754ee634528a007ab510c86a7e1fe6e62f4166": "0x0000000000000000000000000000000004b497cbcd9414ec2922ff86acf2e22ad1b49aa07be1182a9490c47d3170e6861b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7a0fd3be900ddd6b0a7ac5be69a8243f8880d5fd015b2e8f8f30ce6c7162f8bcb5ad1a1fa4246d32": "0x0000000000000000000000000000000004080bd036530545e5e07ad813a408fa757bdd643e76b9d1171417d7eff0d7fe4b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7afcd22bd458c5e66aa7f16d0ce7a6288dd1d2f1779fafb18d4c60ee78e89ab3dd3bc0979aad386e": "0x0000000000000000000000000000000004800bea28742b7e03bf213fd6cbd84e862ccdc18e30b94635f5778a8103133f36", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7bbbb302ea3c73fd6a1e7cf7558378809fa376f7eec7b065d30759f8a4e7b721ec2ae74b313f0855": "0x0000000000000000000000000000000004a8c96b926e3a1baf17e8f1cab2e0df7229b36c661e9d29f4c005b2dfb0835218", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7bc80f4306d5529f7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819": "0x00000000000000000000000000000000200650217af71d75baa1bbc577761208886a474cfe4c24435b0295586f2f66a571ce00415c4b594b4c5085fc803c7eb7872847b7b50fbb0ad93cf0fb95c7a0bf68e2cbbeac13b1017c8a5a32551d77e89017551a2f9438743446de2dc2ed13ec4d7c731b26739bf75d9607468391f9d743d3ee7f65f8e668d770174f74dcab7f433818c289aad92bbce3185cbc77619f99bb38a139fd9428ec6c2c97f964d0146770d4121446293f928e59d4f8a5eea096ebe1c2538002fcbf7b7845dd2e19ee6d424ecaa1e5d069bb89c743c3ddb44d9cb023aff0ad78e3c502bd39b0abbf7715e2c6bbc2bf8ac332d8f9f45013049439bd2d31008db521ffe472e8c4c4e0c348", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7bf2c0491ddcbed34e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006": "0x00000000000000000000000000000000100a750504f5da1835d98bf849ebc018742d544c86edbcab2525a8acc2178fed596cdfaeaa8c9eba3e4d30f66d1b53a97f830612cdcdb1ee1d203a797ef4973125c21bde30a8d12e4e5d4dd612ff510d84e23afe81bdb222e1037a7c7fafd8962b4033dc4a810332f94b2874b5aa564424b0583f0e866c908346ae4b2bcb4f5e0e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7c1466766d8e06522ce1929ab903f695bdeeeb79a588774d71468362129136f1b7f7b31a32958f98": "0x00000000000000000000000000000000048e9871679378b82009f51f30eec29bcddfe60c4f7d22c24f74883b47d935a565", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7c9b151305dcded7e26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04": "0x0000000000000000000000000000000010e26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04fca5925e677ffb072b404634eb297becf53c269e32c7393c9b9dec8d256dad21a434a662f5ab9e81bb83c07ab5282538bafe448f142d2b6b119362b1bebbe1767493915ecb44badd479418bd0ef0f753952690f6ceeb421a0fe567edf2fdb228", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7ce6fa220b1f0d1ba06446b3474c3d9dcfb759f3df134cf4b6620b2559c4e1b99d3be4d010378f40": "0x00000000000000000000000000000000048bbf421fcb86d5fd3e28a4762d295b722fae2260d0f3d548fe6eb8cd741c286e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d26f412c600f65a48745d28d9e9596ca41b7f7bcb03f874757f4f0716a7237e566662a6393bc125": "0x0000000000000000000000000000000004483ea32669fca11e7415c4e24e088cb3df49defae82f0f9d069ea0aa75839e38", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d2dd084386fd77b18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc0019": "0x0000000000000000000000000000000018c0dd6bb9243edbd211dac2b9b37fd29003be77cf21455af7c2c680af8812b6041c761954d8265833c4b21c7296a314229af2391b34fc090aa76a817b2e79836af4c68c01b58b381bcb8b1fe58cab96f90271910ec55c23214c68815130b5a81ba8ad44d6bd00b9ebeda2a48ccdad36d0ca29bd930ca2856cc8ce1c109f938625822adab3c579b87a5731f551e8f311cefbffbf514b27b94a6af35fc23562c945a6148a5ba31e548196ff678386e2c8792fb3bea265b6c2475e62eab64254946e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d363e805ca7dc102e6dde560aa0f00b08d0db5e3c2f199181be3ca53d2e7a0a742aa5692433060d": "0x0000000000000000000000000000000004ed1d56154af1862efb63fc12298d73411b024a7b5312346ca95effe7011efec3", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d3c67d22eef172a8c20d46f86242eea89c400d5c478207e05c76bbab29a748af8aac90d627e1a01": "0x000000000000000000000000000000000888624098732487bb9f92045e3d405bd1b7f9432dbd705c3ba58c5e86d1353c696679005100a874118c6c38e5b3183ef6cb71193480d1de0699f9bb6bfedf1f24", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d73ff709d9ae6a4d53c9c6e61431448ceef1eb49542ddee942dd3d6c81c19d53efbab8acb02f00f": "0x0000000000000000000000000000000004f45c6d9ac359665373662814fb3b30355638036ee2aee6807b2f2b228ec1d6e5", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7d76b3fc859618eb1a41e8f79310cf5b804b038d19f28b535261fc5c1c3d1dcfdc49e6bf5a946d32": "0x0000000000000000000000000000000004a248e7a6ef290c55ae9f1383eef475298bf04a1a78fc22f186cce5a797ebf508", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7da4d6e045faa8163a731ac0ae7375a2cce5b504484d91f1c49923b3425072e36e12b0afd5f2a857": "0x0000000000000000000000000000000008a570c6ce21a0b2f432dfd11756cca948259a8b281196ccec975c681372a06280cd5f012106aaea7652374847b9658c8c300f0f0b26e484e99f7c1e3d32d83a10", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7db14798f78c92e409ed7dc92692f6d1b8bf5e71b68f9019a16f825e4eb71bb22c5bcbb9fec300d1": "0x0000000000000000000000000000000004e7934d8edca47f33d004647a350aaa7ca31871f8ffe6038f187e1689cf34dcdd", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e7e1d98e7b551be5a30fd1beaa72357f61ba1fe7e90aa8c5080fcd49b2c82e1b8315bcd9a223cbe41": "0x0000000000000000000000000000000008e1926d2b7dcec1ba035361a2d58a3ddbbc4386ba5bd61d5dd57d22d508154decd10cd1c9ae335b7b25abad42b89554a8d9c9fdce81a11b856604cdfa6edccffe", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e81a8aa27b7c69abc7c7d2fe83c4af79c49136f0f8c5f1a00cd8d0aa91c94fe74d0145cb96d688f66": "0x000000000000000000000000000000000c2efecb509bcbfa0ebbe40f7bbc6a74d4a90cfd7e982ce06c2f11fdcc70efeb5a8057b9f8b71f7e97f0bbb2dd94b1a047992ff072d07aa77f0a3fba1c288840251a232a8dc0c50a8faa639ed22d11410c00f5b812bd14ffa6f3f554d8edad4172", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8337944019a68ea6a6500e450888dd3758b301a0f99d433264362547ca7d0f7631ea53871aa3be35": "0x0000000000000000000000000000000004007f0252d2dda00e8007d8ba227234f9407f28a0584158c1a74b2e4401ba921e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e83ad6aeb3e5890e926090dc5275e53b65763f135108a9111289aa1ca6331a8ddb3440059cd33d75f": "0x000000000000000000000000000000000426090dc5275e53b65763f135108a9111289aa1ca6331a8ddb3440059cd33d75f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e841c66ae33e977e77eb07fd02281d018a4c45bab914fc6e2a0f81620663b53ab62432ae62a07194d": "0x000000000000000000000000000000000448b36ca55541b8f8c030a3a844a247a85e731764d015bdede53205fb5b355a25", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e842664827980e15e54faa9f0cc59a977e73147865791a9272cd4980db5ff2eee27096d34ff2fab69": "0x0000000000000000000000000000000004fefa1659ff7e86a20f110974463d76eb0238f0e02f6b526df7d586b0657d52d8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e84ccbb22b59b800b7213534fb02c7638d8d7caf1f62b983225c5aa76b8c14d249f7a704b50ba850a": "0x000000000000000000000000000000000430cca6318e5c3cea1c72f33f541532ab6609b50853627fcd587bd5883d52f75c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8549b7fd2bfcfdd9bc0525c374a8198f3288a0733918321dfc26532e253d94da3a6a27a4c3e31760": "0x0000000000000000000000000000000004cafd506351cbb8a3af1f69479dc08628bcdc05de50e86e2f94aaa21306727b2c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e85d657f1acd3f2c92458c79f1b8d080257ba31830f364170c90b6b173be1832ebace48595d193b2b": "0x0000000000000000000000000000000004160e772b488c83753ee69cadc56cdfe71937dec6a69b4bee87e4cfeb4bf8d475", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e860033e5e332e23d6a2bd95c44c00bcad3fef2f7226ad90b8b93c3c1b9679236d5abfdb39c895844": "0x0000000000000000000000000000000004bf7c2411b8362b3beedd04428317c3eeb3639379c64eaa724d44eb77b15cc85b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8621671899b86161726ac63a0a6a700ad7e1178fef89a87620bbc152a19f74708defc7f08bbc6556": "0x000000000000000000000000000000000410a315981265a9951067374fb624c1976dcf865c9dc43d08e3031ead35a06219", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8641dd739c11a1441994df5bf0f44342b1719bfbb1561286bd81b6d84f577f55ef45fe7ad6f50e4a": "0x0000000000000000000000000000000004e396927763007571ab5c30a835b67c150993def51b98681dd7a69e87d7125cf7", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e86672c8d8603d645de7fc70edbc29190008415c3b6122dc6390b738453c6f1213b59942b2b76e54a": "0x0000000000000000000000000000000008c2e34786dcde41bcaf6c5c3dedd1320c792f0a0bf3c448e03275d7f9cefb765312ba1a34fc5e9b81ba8d7e486f223a2cb47e30c8dc185888aaac0eb25c5f605b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e867fc6e4929b002af04c95a6ac10a0db5af28ac44776f95949dd543f494f8b8787925c41fccf7e0f": "0x00000000000000000000000000000000045e5085f483896c9bfc341a80912faf167a1ef9229fe8b2989de7b6bad03c63cb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e86e553fb01bfcb3d16f24ecfa07199b88f010d94f47864ace2c0357aa4f37898f85cb39992e2036d": "0x00000000000000000000000000000000044e6717194ee8da5cb1669a5636c8821f764ecffa0bb0e43b610b8bb1fb1f197a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e87843e0e467379078c79cbd600c63f0cc90b34e7301b7cef8c93f7a404cbacecab96901fe53d4640": "0x000000000000000000000000000000000418a06c67746e98a3cc1680079a706c133d5e77d0c8721728cdd7c8525b42b752", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e87f8d378447f4f51b8a038b439b411fb7c6cc2d7315292a3d1649601641cbbe0825ab7fa90ce3002": "0x00000000000000000000000000000000048e81ad73b19ae9a28e6e7020f70d862a8e379ce88dc1546a2a8724a7c4b5601e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e885ebea0f5080b1300f53cf59ee4bae1fc47b5df521d48a3cc2d02d5c15fd5d3bfa3d6a4a2e6a576": "0x00000000000000000000000000000000081af4af68069a4772fc4e73cba9d1479943982c64e124ec73bb1cbc70f66bcf3f3a6a0745688c52b4709f65fa2e4508dfa0940ccc0d282cd16be9bc043b2f4a04", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8876172ab0d0bba3f89b361ea400867da22fa6a069fdd840819fdc24fee6cc3763b6cf3a8a20246b": "0x00000000000000000000000000000000047a0d37cd4a96cb4e0445c91d19d6c84856f994d5e099e0f911b6855605833860", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e88de95e48f84c3689085297d964ea873a23b63151b4c82189c1314c31fda6f2d71f83133d0877c5c": "0x000000000000000000000000000000000cf25f7a8dd6b648eac453d60b0052dee3cefce2ff56830eb7cc98292c8885f958326e27145577ff5e9bcd3f75bba30fca9622705f65a07ecf04a5d692b284ce72547be45207a849ca9ec68e16de6964b581b36449cb04256febdfdad833e7e670", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e88f2bab6b4633034bee287e579da5137412f2c3bd4d5ae4c6a11c4c420e04261157e04842a2ea641": "0x00000000000000000000000000000000048cc54beb3db37569467a12154f037da2f6d859d11b72db7cc8f615c7456bc923", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8902cecf825f2867273e55ba58de0184bb96e5e691dcc9171ec58658d2b94c42c7e4ca7574f6a076": "0x000000000000000000000000000000000433815302aca0725e74939106884963f32a80056aba37aa94dfe6220c039cc87e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8954d9b6c7704b5c0a912cf4f0c7894598d81d26f2c24f6e5c2541f312462bb576593e9dc549146d": "0x00000000000000000000000000000000040c8bdf19914b8931589d6658da943de4de04cc1102902a9e30d3d3bc68892c02", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8997871f06793d390456840228e994122a2750c966571ca20d2456db20a7cb84603ed8e2d5503776": "0x000000000000000000000000000000000460384fabe173278be399e99aaafc7d5b3eb2547af81fbc8039eb6fc49ae008bb", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8afa4a7f5b70a3e0904168b519b2745aa1480867fbc7db364c79e03fafd6e30ccc1691e7214ef860": "0x0000000000000000000000000000000004b20ba612ec45aa1ccb1ede3e2838ed2b4f5eadad5d80a873d74ead94b9689850", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8b299234c2604004face99d3401cb9b45ee1bc0ec52f4cb35914dc5ad27806230534230eedb8413d": "0x000000000000000000000000000000000862be3477b75e8497245a053f1f51f752421fb039f6bfe04a397e85be7e193440f69837f9346b574bee364518dfa08ec7723533632fbabbab594623d83157a67b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8c1c29593b2d5db604c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b3568": "0x000000000000000000000000000000001c58ac509e6e93bcf6ac0800a070f28bd477fb9e9717ff7779d035094e361b150438833de858facacb267fefbade2fe127da59cb1d3653e5acdaf5aaa1c0bb6f255b7812d3e31417cabe45153f522a4047b09e9662795cc7c7372cfb02f6dc39192a30902e14ea5ffdb5135aed31d3940e0df7027a27d079c6a67d135981f4760146a4204de252ad6bb8587604684eb6b0d8d7c5f9f8e7ca0132bcdc6d53131e47c49ea8deb91aae7843e2cdfba3a91fb9910efab535670b9da55bd5abdb7e542a4ea8dd0f74def3f37653a2bc9932edbaa87ba9a185c55cd8b5bd733ea86c6257", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8c24c3ef8bc4c3e412c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310": "0x00000000000000000000000000000000910112c0e71d46088235059834f57282e18f93197b164a04be4082b6dfd88d86f53112c0e71d466c86c2834663f4edc4bf268a2746f02da7a7334344582db793062b12c0e71d489fee1707d4857f5f4cca6e9ccc10a81fb25b9cdf5c2d872d0f3a5c12c0e71d2a6032287a5bdb910afd1522f52f26c1d619395f3c8d1d18ed23c12b12c0e71d133bb870cfcff34b784d933b5ab71a4f90987f854522f076bd23f21412c0e71cee9f575993304f4b1b5dd21ab495dbad0b4613f39c8c4f49ef24140612c0e71cf3f161c02727017e5ce4f8f6e245fa61bec1a3a1ac960fe11e917c2612c0e71cf41a90f7205b9034bdc9380a95bc18669cd5b4d6b9452f73d468e74c12c0e71cf317d94584299468b9a292c7e69d3ce2ba40e4819166c78dce18e85912c0e71d0d3a5ede1ed512ea065c3970ff43788f057c99ffa3afe8ede608da0e12c0e71d10a91f1a202191134bc06e790e98829eb7d76881e3c8b42dbe8a6d4112c0e71d210ce61c449fc8f5f3f521209d2906e445239a938303741301d0ef7c12c0e71d208c668db313147edb94aa31af86ca4e55d4900fed5eda638862b80312c0e71d1e59aa52904247d6ede8d053ec5c65dfb3dc8c1e632acf34c030a25512c0e71d25be2e5d1c5893ed30710dc6c645e8f26b3e1c3ca43800fb99fcfa4a12c0e71d25d4ac0ea242b6e44fc9625e1a4dcfe17e6cf9dfdc0bb233ec58955612c0e71d364ec914b6b740ad7c055dbd9a15aa2cdf4f6b3349970e15b6b73e0112c0e71d43df157fee32bea33e2335ca841ecf4689f61b53af12109a990e8b3812c0e71d4b14d52ccb248e416cad1ddfc7283a09f2625c601528d29f9a294b4f12c0e71d4ebd6afa6a6462c87da8f8da65e320b207a3958a76e854432b5cdd0212c0e71d56bc0e445558b892aea1eb53639aaf99ec6f51aba44607213c3dfe2e12c0e71d6034eaeb56b1637b948fefd184ecfebeffe8dab40a37c6cdf3971a4012c0e71c47eb3e0eca577bc8ce7ec63eb978b1e36e73daea0449935e5496850c12c0e71c49ca78c235b4cc7c02b0dd42d2ba68cae14091330453206d11f34a5612c0e71c4fcce3bde2baa598b4b4b15e3674286d0dc2c03441be1bd48408d92a12c0e71cb40d9d91814a130bf4ee7008a6e83563520ad677eb2034209fa20e5512c0e71c6d383ed080fca5ac67242f4365fce824e3b989af1388d5a94f38b93412c0e71cc202669b8b8f008fd88fc91048ddec2434e536b37adc066ae2d1653e12c0e71ca519959bc745598c859160abc7bdaac3949ca44ad9712c4a35e80c3e12c0e71cd7c05aaf2bd4ceaaeddad56e206f8b7be033b915ca7e8391aaa56a0e12c0e71cdddce276170fdafc609d13aa23bc51e46a52772dcf1e378130b6b01412c0e71cd31ae09c2af44df1c49f572234348e1637127de385daad38c2bd363212c0e71c92f12577507a7ceef4da940099fd984e976858d6d4c6826ff76e254412c0e71c73acdcfb922d6d2daaca383ec2d7a0cbcfe42ac84bb16da1c25c8c2e12c0e71c9f53cee8937a8a3a30c639efe4e9e61faa222953bfff2cc0a782956c12c0e71c712fc750ea7987ebc3adbf181c53f54133d3378fa5d7268bace38a0512c0e71cac0a27a2fd30bc24907dfcf124197d52af6e9c9506f5bae59bf0887912c0e71c62cf1da0300cb62510765cc22eb8eaf487bd2abe160f4c231e28a34012c0e71ca560b3ce013e7ea6f20692d95ceba300e0b354cafdb4095a94a27e6812c0e71c651e27773fa58160878f81a68b7b054ccdccad776181f757e763e51412c0e71c512bfec8bb542308c909c7b50f401219848e9cd7ee84c2bf2519644912c0e71c89568cdf09515dad33fa70b04cb39e21d8be64dee93e17569f96212912c0e71c65c6d73c4787dc93561ade71071ffc5d78756ba4f606fe91a6e3452112c0e71c6c063c135438f8997461cbe25e61d7569fe4c3f9f07db032f75a581c12c0e71c83c45d50d2f831c6574ab25eabed7842fc69f51bba122c617531d72512c0e71cdeadb03446fd3519d1dcd4f690e40df4ab0d193b476a94a0b6588c2812c0e71cb1a9c147998723d2dc7ef44affbf359be54830a570a5840e2734c47c12c0e71d06dd205beae5054c937e4170b53866e429f4be7a98318c261b3a0b2d12c0e71d0f4707cb93bd1de1eeec36c3e1f995dc51eeedba0cb52287d2fd3c7d12c0e71d378b0a623f2b9eb1b44430061c4f2bab9da7943fd286326a98b54a6c12c0e71d2b06750f95b1dc2ccf25272d0e77de2fa9efb9499be95ef938d6d76612c0e71d5287b03cc78c4c2faefffc4cacd47bf65ba7bd0bc5d4facc08cf932312c0e71d4911dde07af70a1bafe6ae84ef07a43280a736d0c19395a58793541212c0e71d2f08b6d34a5103c892d4baa26995bf4b184eb7507f9e111014e58b7912c0e71d17404deaa91eca3e64e911f5e43ebbfb80fb21f97c4d453ed79bee3612c0e71d5b27b11da4fee8ee2b71b1535daaccd5775846c26ba02d082124466712c0e71d3ed7229dfea16555ba040cce63fba1fa33cd5296c4393fa61114a86d12c0e71d2ffe345813bd81eea02b361a65b0b88ef0e5ee8a0a2268a8ad9bbe2c12c0e71d36450dd3d651da12ea3ff51a9f306650744f4c164ceaa7b2cc08454612c0e71d122033fe390632d7275542273a8afc911afdba254ba4b7f33087906412c0e71d5e85f0442d53fd7419af7a23a2908f88ebcced94150e396bb64ef64412c0e71cb2e754bb49f1758439d6729debf9a30cf5b9a797ec564f00592a2f5f12c0e71c4aba6d53775e0a27ff00a6090b2d9bb4171096109a5aa2a59328df6112c0e71c4dd67a196937bcfc45ed0384d81a3b7e8a5b9746ac82081c4bf3096412c0e71c5200cf1cf22ac62ae2910eb3e485a104f610f1535ed1e844b78e291412c0e71c578bac3ac4c85fb1d9f0645451aa4503782c3f0f3260486b8d3e612312c0e71c6323105cc5215aec99c36c3931fabbe7dc4a439329be146133235a3612c0e71cde22f076b79de5a6fc30cd47be3f5629d4be7fde35d769e7480f491112c0e71c4b17ed34d92d3794d3cac294945580552a9200d74dbaeb0a17a2ce7e12c0e71cdc8163ee018634a900a6e973a87e8740b6c9c4400ca1fae2ac8f4e0412c0e71c9d62c402a345adadf6d07c72b92a9df6035128105150414c0f759a2312c0e71cbbe5966e17c328e1a6f43729e44d4dc326af5ea40f9c0e103b19cf1e12c0e71c74bc9329f210cf3871cb0df4e3139420f8cd1260ed214f6e310d596912c0e71c8c7444fd30b0ba7ccac70112280c31a7b57682c59443918e741b713c12c0e71c471767a1c8d1f0fbdc97763c8730745526c890b3d603d90337caca4412c0e71c85b306f02dce509fbd905815ba90fd450199f70a6e00a5634134036012c0e71cad505181147127f5267ae6187fe470ce00c91bd1d1adfd0227a7333a12c0e71cab33ca9929a6406d6634c55c8d28c63c99b18fb6a2c1eca3037b144a12c0e71c9fdf776b26f8b4def79ecfeb98cf14bba80546f54124e4725da6036f12c0e71c9c7a0df0270f56ecec10f80525ff477398256a84db44f8362cc9cb7a12c0e71cc0578209ed2ff07931f254566de682bd7407f07913ca1c4a30e7a63312c0e71cb50b65d27c7147f5ea52a5a805f8f75301ecb5d9577244659659965b12c0e71c782aad6c734c6714946bf965fe464aaaf2e15c7d43409f936540ea7212c0e71ce93b3b5ce42fde862b4d609631d600ee1cc3f3717268e7b9b3e1467a12c0e71cba3dffa43d603a1637f373c134f4eb3b0ca902a937e218cf992b4f1b12c0e71ccf0639294d8ecb643d6dad93d9660836463f91d1b66292fd9b1ab05f12c0e71c89b2c75caab9eb9b3ee5a918dc734c5c595ee569e64ed37a306de97412c0e71c8bc9217a6448d34afd0c1d226663a864a4141b65d13f8bbc743d133512c0e71ca3fd568c3120f3c6eb7825d957104fd5e9bd9848ef36a1d5de03b00812c0e71c7daf0347415ea3623b1441a1f89b5115bfe82a57a132f72d186a246912c0e71c9267977ff8cfbf27005fca3918833daf0d77537e8f879fb9fcdf2b0912c0e71c55443e88a1777244fd0816a9f44562ca36e5b9d95d45f3d79a1cb56012c0e71c508ea654da98971a9a27caa027e9478b84c319ecc1fb63288ffd9b0d12c0e71c536b024440ad0fd64324c6eebdc0e497207ff42489ca8a2489f6e32712c0e71cfab0ec8e02f65d8114492d2c9177d3add541219bd8ddc00ef4e9b66a12c0e71c648c0ea092b2481ad9657956548a531fa3a89a140d3d8f9359fce54b12c0e71cbe21aa863d666ff694ca4aa3a1f0e89a9e75ffcdb6c629fa1d00646012c0e71cb214fffe90a9fd96c396cd776ae64fe664bd26e6072e7328b1df575612c0e71cae4be30aa91dc1e77bf2bde98af86c4d385e9c0868d8af4a5025880312c0e71d330bdafa9c3a6218dcea201399a6cfe0fa73c2692e7a83492614e40a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8d136d7c7984d254da01077bdc025fd779cc21c9760727ec07e52aa132410b82e5fabacb6f45b055": "0x0000000000000000000000000000000004bea06b45bcad97ae3126af1a6e864197180af4b7e6513da3032228b2bdb26368", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8d5f7ebde4f481a866f7b3f3db597d3032c2d767568aa550249c946600a61276910b9c1d21a93371": "0x00000000000000000000000000000000049c674dc7b750bf4d5d5d0db23578adbd9602cac61f6292fd788879a44c87256a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8e029dc73c6ca9b6f00272047a1369138c7948e8d193757bd7d6319254926d2b91175398d8250e30": "0x0000000000000000000000000000000004ecd0f078418756af923fefc497d98efcdd243170af2694cb75a2becfe2811732", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8ec37554e12de10ab08b555a5a3b2725e01ba15eb40aa32dc5b781532854b797808ed45e752b047c": "0x0000000000000000000000000000000008d85561d4ee89c473f4220a4a5ca0c8eaeb01fe8d0740aed291ad796d4b2da175821bc7f162ddbc6418c08a018d072e2980a4257c8584435e5b6251f6e27cdf19", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8ec91a2d2c36d0707a8b217ad8d80016336be124846210559ebf720aecd25ea0d0d11c10f1839e71": "0x0000000000000000000000000000000008d84e08c6dda9a41fd1d44b01b65c7787b48723679a1d0c83d1d9a54798ccf01e5e11390e1f7b87f6e2a59603d7979e4e26259c41f011eba0e6f3ed6996e7151d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8f10571113e0ae6b447326399643ec639a0bfde97d8b37f8dd0ca9fcb3c74a1ce017f0476f3e2770": "0x00000000000000000000000000000000041644a3ce3456b8954eeca77a5b67d7e9d26eba9f922b82daff95057f543ed03f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8f88e4319e34d2ea16476866c0074663b7d9046023a2b3fbf447c833f4fccfa3dd7a482235f1ec7f": "0x0000000000000000000000000000000004848acf74babbd40295e54caaaf41e505891996968bee93eedcaa8e5b4105c779", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e8f943fb275b495a03e3622fb285dddefdf8f9ac2ab59aa34e2abb5a316e9ebdc020317220e75f879": "0x0000000000000000000000000000000008a227e750a30259349ff46ad36105156f552fedee92bc3b81470cea913d30d6cde81c8e2c7bc6a6b6de522487e8829344e992a3440f957a52c86d93038b9b3dc8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e90073106f69e036ffaba4f34d61e2defae2db1f7c712007824c194ad921959efdb4a65dd174a590c": "0x000000000000000000000000000000000c40de8fe2227bbb0358570c01c31ce0ebb4b7540c1302ab6a6d021cd0ae5d5942f206c1276f16bd43aca4fa9d596a7164a310b83bdf34350c1480ed4854cf9729a83fc2798fabbdc8d93db99a27dda9b8f6615cfef0b16a3a0aca93a49e527475", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e90b1c53cf7dcddbd8a320af9e031a3396f15acdcc65c43008124068226505ee7e12bbb0a12012e60": "0x00000000000000000000000000000000088478f51feef5a376deda20303e61c855e0b96451f692ead53d838130bce9cd086c98dfc795cd34290966dfa3a4f690a2c703dfaa31792854885295a61cfdd670", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e90b34a3937b9efce6482a21b7e92055e74bc9b182ded5b0cb86e6f7706090c916f60e8235b8fe51a": "0x000000000000000000000000000000000499a833467b3227e480dd06ccad8eb537c399e3851d8acd1b3d1c3e711db83686", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9155332d1321391214cd612ff7f390b9e90584767a00a4e9b740b61c0f2134698bbac79c6649764d": "0x0000000000000000000000000000000004c61e997a53022149bda8907ce19e1780b9ae75e23fdd6b44fd5a6adb4ff91801", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e917bdd412b89d0510cce9e210c473fd1f20178fe889c178956ea1cf325c54b1a439a88bc62fe7851": "0x000000000000000000000000000000000434fe2832004fffcc1e28aec7ac35d29142b892f10d8d0c301cd26c37860a0579", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e921d891bcf4e728ce683743954d0cb555a54ab21cfb8161f74e689a051d1ac1dbbb94df70be3d81e": "0x00000000000000000000000000000000084409776e3d248cea53e8d6fce41bc1795b83793fe794119a63b82a7e837e9f59f45cc1889ea605f6e375289fdb22c1acf7e99fc60cca3ba5cad46a21661a7720", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e925643626036602a9a92ad7c6dcc51fec9f6d98f8316406ca42bd04dbb029d3ce454330a20fac077": "0x0000000000000000000000000000000008148e8ac56079d875671a8e379e8ce3726be04f32f36a3f8237c2713dd354be1bc6379520320c2c68f6e75938afa22a71c7f3bdcd1308ba1e7795a2fa2d9b9066", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e927911426652f14cf4492a28ead0b315fc68069bcc39470c409d12b4e48259384d63da411bad0129": "0x0000000000000000000000000000000004d448d47466cd9abc75c90e52f3aae5d03e772ca2f13db8516aad2ec15d341d2e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e92b894b9740836cdce2e98564f421ca69a64608d68480080f5f317f4de4e400af3c065181e0c8a11": "0x0000000000000000000000000000000004ce2e98564f421ca69a64608d68480080f5f317f4de4e400af3c065181e0c8a11", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9446885b0b18680ae8e0ac0aa68a0c138a3aa84813f0accae4ed7d6ae4b4905495026f16eda4e069": "0x0000000000000000000000000000000004e8e0ac0aa68a0c138a3aa84813f0accae4ed7d6ae4b4905495026f16eda4e069", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9464a51c61bcb648ee56126859de69a3539f0e8910ca7e775243f18c6257954a65e020eb229be912": "0x00000000000000000000000000000000043e4473a8a5c626a2b1eab5002c13537480b487a04ce85ae09292a7c458b3be06", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9512e7cebb2ab2b2206dd955d4ade8d59bab18cba031e664ae888491d173084bc9a0efabf0be195e": "0x000000000000000000000000000000000454c3bc9063fba6c75163f3e051f1387121c0120d3bfe764e68764f02ea33bb48", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e95e5354b81f0f460da9f7fd3d9612a68d2ead69dde53297b172b7db514d0d261e7c5be987df7f32a": "0x0000000000000000000000000000000004a65bbeb4425c55a611da4116e848b0cc39686a11f88dee6aacceac6bc5eca657", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e95f941adaa91654a28322946bfaec48af9564e56ee4134655dc1748ffc206c3694a9c6bddbe8332f": "0x000000000000000000000000000000000438684912197a8fb0da1f815281bb2f52f170d07b4d96450ac6ac06cb4bd42d6d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9639866340f488369cb0d4ddd32f9332dac7059de238b8e489afb55502d1756d7f50b78b58e20c70": "0x000000000000000000000000000000000cd07218db071b0b88f5979d57b52ad2b7706856f7be0021d30df75fc9ecfd2f64ce4f4b5eb5e648247f1796de1f52ccb6d6e763684ab786e21239f26af6d8d252703d07f2ac096e6b0b998fad5997c7c9b1e1f417603c350e76ad99e5c19aec04", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e967dd10b13066df77243fc7f5f476ee7c5fad9de673f1ccfdf59c3e92530c09d6d584ff19452c87c": "0x00000000000000000000000000000000047243fc7f5f476ee7c5fad9de673f1ccfdf59c3e92530c09d6d584ff19452c87c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e96f4aad0cdd32c3e8a6d7fd62a2ca5609d25c2574a275de76a6fc5322482aa0b0d29f0a8f8f83b53": "0x0000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e998cd9a07d23d28d50ef3cbba6eefa5127e662a1286c69c3f8cd10aa328d394df9e69919af449b45": "0x0000000000000000000000000000000004f4c6e1ea78fa82de3a28d27e20c93b4b8109fd93489d864a73fe7bd4eadf2061", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e99ad9accdb6256f3d8783497b4c06f05dfa6ca91a0502e77ea7ffbc5c33c7142a5d9d1f0322d783b": "0x0000000000000000000000000000000004740cfb483a7e7c4d04abc9fc3651beeaea5633eed75f65c0380d424312412357", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9a24c66abe29ea3716d5b643fdfb1b22d5dfd3a50157104df0580c910d2754987afc25fe0aaf5827": "0x0000000000000000000000000000000004c05795cea6af4d0bb72417772d60d0e8ca43f5790448fc92f764088b0d4f4b1a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9aea00c445f734edbaf3f15b9e83dcfc18b50fe91e601fdf446c008c72c3d17799c21a64877e8d3a": "0x000000000000000000000000000000000420f949b07ac91763cef16c15fb78d5370271add31799ab7ea2e940a89af4672b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9afb96de5bd6c558f6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a": "0x00000000000000000000000000000000a41a7938fede32e1275281b3eee5708706d88444a6dc898a4dec463f1eb298463fca2ecbecab066ed29eb6f04bc145a5fe6ee36cc0144f46a722862cf28dba2c6768ef8bec8b0e59e7c456392b9f560a48c0abc26faeb75715b1ec4a804f469f10d618111c1eb2afe48d95bf0501243748e399e23a538bad0db61fe474f4f2b90f14ededef8a62c8642099e5b094ef95519a5e2a1898ec9783c2bac2c71f71cd160cb5554f54c346c7996d2f6ad6c5bedcdc094b6ce0bb9a4afc7db6ae865cd378bc921beb233fc0c3ebb3f98676aad4aea89f81a08f57251e24e2c02f0dc0a901de89b93418a2be5e997eebd4b815754518fc3b7db32b2c31bf97c8297f8ff7528886a23f6aa185a4d262ade722584c6f1e384ce10b269bfb898abf8785cd934a92f63201ab158aa8283fe585a2bf19ceefb00c45eb7b9eb6063b2ee66a108532caa6c46edcc1d2a38bbfc4e200c3851762178268d7a3e565ab99728c18ae037654f79360caefa910ba4bc6e26760fbd44a07a9fd4244c6fc7f58b0ce620fe15c10448cf888bdc13a933c0d1d33653f83d3b34bd775038e0f5900c5363aafee013245a2e5ac185dedd4f63f9899990dc2d467a359dd573a7adf0817e06948451de62bfe4941f647a18c74850008608346ad2c9623378dc3b8856f4d9a17ccb17654ba6fba820d02b4f0def9908ed99ed988d415d9b7c272a1d9394fd670ea8950886a977a6d8063db1b9c58daf3906841f3e2577b07cee9595c5c7e98f7b3aa6612c7ad0576988c680601696eba2ec9b035e6f99fc5579637089d06a24d3ff650a057612349296f2777068dd47c499f36c5caa498c22b48f26c09b9498ade826fa6b7d31c38534c4c6dd648a247e5ed408172cd647084f554747823fe69304f43282272e3e8b07aa02117d8a80fee926dde3a9417a2809b971623dcad89445a3f9ef20ea6b98e87f656d7f23e0b2a310f45d6a6550a211e7df67540cd8b9c4b4aacf39cf23dd3530b4078b43141f0a0ce5c19549909b0ce4bc163984e045d9b652ad8cd53e45f24d5e7c2cacb60dfc3a4dc6260682150104828e62d3a0142c0082e8036bee650826ea445368d4643b0ad2341924bb357c8ee1596fd1235ecf32616bc1a5fbe6783b4c4fa8be371150435d5cace22115338b33a9966b4de2ef82df20bc9dd454ad586a9c7d259068e87412a8ea309a006e06857a04707041227017e437bd1edbcf02649eb8a4103c8668f5903ceffd5b2a4215c0d211affbe5f6cc20f540f6c1dc4dba60d21936788a5bc5628f26333e27b14cd091145d92d8f255055807b7c54a1143ebefe17d711170a5971227a8a8b593c769fdce803812028407201429e0f6beb3a79213b46c4f59f002ff4da66dbb0bfcb66cae1cc1a50749cbecddcf7044de2e7f8aff6dddd8660e28ef5214c59623dd37a62d950da795f70f955feb0ffd847cc972e17e979619e0bc0739673db8604848204bf61af00717afc36665eb89509814350a32bc136f095dc1c9224dac890c0112b5f4b53ac6c086f2422947fdbebd39a68f8708064bd5d9caab70d1d6a51abff895db91f56551244669ebe06bb78a7513e888ab43c70dd2f0c80e90189b02fbf62ecfdfdf66f54572de1db5ea15bc7731401c4fb92ba2ab3f7c387acdbbc2590a673bef4e2488ca5a28e878867689b757883005b39b269cc76cffb757bc672bd9cb1874cd505d2f17cc6203b5746b14c65b94077e29f02d0b1d56a0ba445458c2d7cf9d55a54e8e0a4bce889b5d71d9c9dbcd6687dfda6458cf22bca0a342f5db49d8258ca6a72f67d9caa91e4c5777b9edbb0f7297d7f294627685c9af7eab3563ef66ffc20", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9ba746407882e793d49fca4c127d246783d23e388e34c09446b624d2d5e1f7773c9590823d451019": "0x0000000000000000000000000000000004285f7ae7cc2580d54ec3be6fb7fa3ab6f2c1a32352c793b29163822091839e31", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9be10627200d7958fa65ad25c6a51ba28504fe803d9e3d542135924ba9fc0736cd3f1d9b83901778": "0x00000000000000000000000000000000048278ef29ec5edfc3f2694075448853b34a387e0299bcc326c41e9507a5f0ac2f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9cd04164b151c8211a903015b9ceaaf0f183eb409d3a38c4f0c9a685066ed90b32c834940c689e1c": "0x000000000000000000000000000000000444ed131039b1a6d98896aa12e996d928f7adb00a832fe5c11b719e7d4a4d9b0f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9cd0ac122701f28d7ec5e89c029a05224b2759566042a94c54966d125934a8ff8beb8e0b017cbd67": "0x0000000000000000000000000000000004e85558af1d02241a456725d7ae7370cd1a5299713a970a312c99d9b14d90debc", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9d20d76620b47fa66610405d8ddaba4dcfca1fe4d14f83496de1055fe97efca594f2813a82900e40": "0x000000000000000000000000000000000452acbe4b065282c5b36e7c1b552ccd1bae6039f9e2abc5fa4be566a8f5f10e45", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9d34cfa440b95864d3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a234": "0x0000000000000000000000000000000014d3247cacd091a8f95e795c76e84bc34db75ba76e13a79c1c4671f12f433ee83dd376b1daf289d513fd22426812d5a7c48a58dd121e4c043627e00fd216557873e5c49f7bc76b9e1b91566945e2eb539d960da57ca8e9ccd0e6030e4b11b60099e57259886f2db2014f3bcf26e8baa581816f49c13e010bff9f52d5d9ea3ae68ae573ce3c1ed2c09f46eef869e472f6fc1e1345949d22b585d2dab0198ed34727", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9d41368f1d880a3b3ef88f51188ea054ff03b902d8706c6d9b1ea56c119b34e0b88e915b5d02da5d": "0x0000000000000000000000000000000004f86ca83eaea9aace8ba08ee406a2ca470fb8d274a9fb496cac6e8797721c5977", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9dcc277753735b96e04ca25cf1cbc516ed1c138492a7f2e606f60c5a9ac96cb405eaa3914fd12973": "0x000000000000000000000000000000000884e7a9749fd2b23ce7f7b775dd0f3808d6cdab42ba064fb242afdf0283e60a20d6574db78e7c0315546032b1775930c40d4cca7562e9210cbde93344aad7aa54", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9dcee803646fe05ab0ef511fbed15d88d75933d12bb50b56d1bbed109380b2fe0c7ec72d44119152": "0x0000000000000000000000000000000008ac0c25ae153af1c54bd0eb9c02dbd01e3b462be18089e560a9cd19890dceac6e90255910ad0897e5c6746e33cf138d8f38a6b46b685d06da2802f83917827c04", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9dd0a74dfe9045f7184d701295be7bb38b2c0c58a35bf8edc592671c53d149d206e037dc7c9beb7b": "0x000000000000000000000000000000000c7a43965f93ab8e28323fe1c19ce8156b9d0a941e56661f2b172da1bf74a2de64163c64722e9d2ead4a7d5d88e4a3e565737094f0d4bdca0fc90d6870a8d1271e807a095defd81e409429e0f0036df659f3472f90e3b9376e669b71adb898702c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9e5b705cbdcc776ab4410d33f13c053dca87be657a0ae3cc87655baf43f7efdd454ff74e3a9d8a2f": "0x0000000000000000000000000000000004882b91920f9e4483d2910d72403ecc9522283079ff6770b58be852648e008d44", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9ed6094855a6dc83081c465a655cf27eaa73bdf9554abcb46ca2d56fe7fb0a20835c1a5ddec4a325": "0x0000000000000000000000000000000004051e046a4125b20b4a9df6a8d1d5f81f6155279dfaa2050c7970d4470b890e8b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9ef6562b57d1a60490c7f4e84347dc6e4e176f9156b2347378faa9b538a857b404cee3e341706305": "0x00000000000000000000000000000000082d2a9ef6dff17530bba04671deccf9754c7cdf0b079e0ac825a43c5c0e274620e50c1ab151d60148984c5494bdd23ddd7e5520a8b4873de12ca413a6f37bc3cd", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9f053c2746e722456610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38": "0x000000000000000000000000000000002c0daa7f988ac07541286ffd6ac83affa9d4f0e119c04eba5f1fb74e51719867c983b401968c58e31e421f96e07dd85ce91d985abbccc84bcea5e8f098d97fab563159dccdbf4c37ba277b4becdae7ef002bd7ab17d62fc7419dd68967e41a358b7b9a284d4e600ad4d23bcc2a12a3e52130d96586145ad8246bb3db4a7cb2e0f0e8f0c9814b8cfe6b4a46e4ee7f2b9fd93aa98485c646f07e973e57293a107059661242bc6a8ea761d8668371ad17f9d036982ffbc68af2c28ebcbf2d30ad16e1fdce688a422833948306f4aabf043af4be9fb2be40fc763787f30233b2510573dd2404caa71709d521271bcd64cb771df96abc1454c1bc2db5be8fd84f9f317dfdcd5afc6aaf6c47e499c5c21097386bf5eeda93a13448eb7b9ddc4fcd0e13a413dbe68838d76d77ca594e3e55c937ef7886fe2e8e46de8fe11f20cdf106b29cc09b9c71f2c39942154cf7749268d6978f82a55ab68d6a412c628b2ced7f9d3e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37e9ffd1362c0ca2353c85cebb3f21b5e97737a7bbc14d8376a79dbba9c2849a28edae77c776d1e4a08": "0x0000000000000000000000000000000004ccba4ab664396955d9309b5ddad39f02b7cbbf76743a9e8969949c3e8a2f5ea4", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea062138be3539cdbd8876695e0680719107b9ccb595ad5d8bfdc4ccc8e8e4656091fcfe652c0f155": "0x000000000000000000000000000000000476ad7b338e915c739fa6055381d937bd4541d12ca755533161da8611aceca14f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea078de63f42f4d3d89abf449cfb7d9b862b775abe556bccbe647820fd4d7a50b63872b657c96506f": "0x00000000000000000000000000000000045883a7c739d00f1d125475cda89e7ceff0f406badf56a7c1270c16f850f62cd5", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea0b881b0063a363a02bf32e061073c44300056b416cd66a4fde1e6c120dbc0089bb65134f5693a3b": "0x00000000000000000000000000000000042eab66a1c3116f15f55dd2996db419e367106043a4c5491a5eeab1d33a17460b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea0c7bc8aeaa262f14ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f": "0x0000000000000000000000000000000010c0e9ec31daccb76e9baaa030b5780a85787b3f1e2ef54fa8f4b857c64552a4e0a28d12dd5c12e1bc0f85ba2935bff3b257089ef59869ad310056febaa579395996043b3a00f3e936328165ca3f780b594dc2ff0d9e72659a9e13ad74c3bdad4b8be18f3fe77e8807a0fc3201a7689f4742a12ff44622e1dc241d1a08088ab6ec", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea10e77c34a7d9ba5b8a2a7e1c5807c9b5241a00382d483537eeaac2fc756dfde564af6a368fbc275": "0x0000000000000000000000000000000004af5a44d6d0b15f2cf84afdea4c76b1321f84da230a61b0c73d755d9cf5171a6d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea11a320b9a8feb01f857311106c8d7b0daf6e096db9a0d759b52403e439ab23fd6559780a8b1c803": "0x00000000000000000000000000000000043a337becdfacffca71fe67fec208733754f035958d349d36b30225fd47798f6a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea17e7770b29efc26845498df40e85e2ba9d9e213d1f476e7b147aab6a9098f1bb250e00251ef8f5c": "0x000000000000000000000000000000000c2e05b8c395e198a2efa9bcdf3ac31424d984bb2b9a1cd6635a6e60c9b6a0097b28add2af7269292c685caa58101bae5d78297eff522e3f6b239fd4fff6b5213239083183c6b196c695c642c6e521ecf55a337cc2bd5df2df8fc6d6c0c7d49c7e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea20215acf2cee769a26f9a811e752199217945e52bb96fb08229d7904bc030f6df73b5b4e6bbdb6e": "0x0000000000000000000000000000000008645903e6212a6142af81631297af316fdd60dfe4f02cfefe20d20153e7945720ca66d6f03e32d64a1a0b23baf1da3ee469d7d63c69ca26ccf3b47752d1171d02", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea2aee766ebb6fb7c4edf81ba4fbeb6ea13cd45ba93cc1d689a6e2e5c6dfc35a458a971823a324218": "0x0000000000000000000000000000000004aa580379e5714c790f17e4af93773d158e30eb08f5a4d24abe4f535776b5721e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea35b58e91836d05e60c6e940d5c74596755e6bb1b31ec98958db10d841dfaf66954b5542c95c462b": "0x0000000000000000000000000000000004a46e73069e5a05c232b0487e1523e7a426270e43445d0dbc1744222fd4f6881c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea3833fe87343f3df36b5dcb29928d8a462f493e0250e895158fc4fc54eb5d00a2a6701fe36a4283d": "0x0000000000000000000000000000000008e79c699eb894e1a203b2c6deeaad557fd51fa352841d2d178d3bf78aa0bb1172dab0125fdf270b1af39164693d9bb3251d63b78742a99693632359e0dc6c4882", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea3a4e6df5615cbd134a3f0845fecdf74f7aeb569953da8cf8f8217a9a167a4e7d6b3438d8bb6d828": "0x00000000000000000000000000000000084194458149444dc0e0ae7addb00b669d89f3979309ef9eb635f148c2b879e8784e3d6c92a32e9ec43fd78e7d7b967fa28ed347d96028d73f37113300cfa565e5", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea409a5b38e9a0943eceb07c477bd40d22f83b08cce78f2375bc1e4cf188c0de1ffef592570383e59": "0x0000000000000000000000000000000004ac2fb3fedf57f058e0c786f94c46f57eb68ad57982f0b96f56d5d438119ebf37", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea443701cf93179113acdfb6cd734dd3e624b6512e0903724c1c90a516c03c81a9af756491ea8e15e": "0x000000000000000000000000000000000424102b17c177cf80ebd64796a17ea2c44b68aca3a03fc35be96f6d3ffc60716d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea46019660a76ac1f5889dcc187231dbcba0bc0dad136d1ecb09633bc7cd5e27e04daa0277009ff2f": "0x0000000000000000000000000000000004e6a1e58c3cb43cd4bc65bc251f9c7a1a3de5bc3f815a643d658c8c018158aa01", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea461cd7dfddc684c664b2886e95f12e168b420f06b90c11d8cdfa7ee747bc12e235a6d5efbae6e12": "0x000000000000000000000000000000000416cec430366d2ba6b46f6b084f62ec4f76967ec6fc65101e6de60c92d2751977", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea4ddec1e6dbcf011629c17f4f4a24ec53f85a7beb1c70b13379fb8e4f969560704d2c25133ba8d24": "0x000000000000000000000000000000000c468a99f3bf7d3a5ec5cd3932ffbb436ecd78a9c635286d544661acd5f9f8de15d4fda909c31173d9691cf6c488ffe22b46c795d0bc95aa062bcf08f414c4655a669bfe047c0962dc3ba330b1fb1a83c5cb5262c964fda49b61e9f98a8c759c4f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea59acabf7cc5c2db3a0b67c6e4b35133a18ff9c3b56d6cd28662f9e47f38afbfc508543087966870": "0x0000000000000000000000000000000004cacacf100cec1782c4f9342566de5b4132a012335481dc83fb4d42bcdfcca853", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea5db7a2686e7ec402cbac2d6ac81d2169fa6e455b0497cf0389bd5dd2a11b24a53e6d94053765a77": "0x00000000000000000000000000000000042cbc13e6be77e7af272d495780c1b51130e27e41e95d8d651733b53630b3900e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea60dad8905663a8126acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d623": "0x000000000000000000000000000000000826acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d62326acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d623", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea64992f36040c17f4866f45ae7b07019c03464e3c8c1324e96d3f05a2c5205e889fe597b0af2a70c": "0x00000000000000000000000000000000082add23627ef63d51a47ec9d5f0fa0d06fc3dbfb0e84183b90a13f072cf735300769bde86b6f4610d3b75a775d3cc411da01222b117e84073f9fb18e5a89de715", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea64c3dcbca109f3eac1d2d82c4a69b16c3ce9eb5d0b6f34f948a34efe62488879a514bbc837e0e50": "0x0000000000000000000000000000000004502d8f8870937f44fb43dbda57dea5b07eead72982b0712bd52a5e033be3b031", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea708d9865081ec8abe4bc35b26cdc006c69c1f827d4bfa75e4bfd4ac0094ceaeec8ac70469cac51f": "0x000000000000000000000000000000000462ef7ddde3d6fa33e5b617265ea9af26a64e1248c80b7ac1cf2df7b171889b6e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea88877471b8c0203f6944b2b5f590f132203e5dd4f04c56e594f43b5681a48b210899382c3880b4e": "0x000000000000000000000000000000000482f53c176ea7abea9092ab9b7ccb5506dd3c81de6fe0a5d2b29068f53dd3706c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ea93c6e207f351cebc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d6": "0x000000000000000000000000000000001831918cb9b9c9414a2cd4dd7f720cb98fe98cf852636fc4860845767989127e7d6621dd4e5cdd0ba737c572710c13df35b316d39ecd12c1ae1320bd6db069a07adc0ac1271ef05bf490a482a38512b68548cc3c244285635c32ed242b33d79dd2b18c6f19f15297b4a80fb9f6f29a37e06bc31c723be672d54b45ed42feba74c0ebeb68d26988495f05130309042532d32304be1b171fba3f5f2ac94ef7d33dcd1907bcf63ee4c58723b0457cc8207bbb53841e33ce3d2876f8cef269c5d4d3af", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaa66c809e7c7caee244a202cd6b29e2026b65a07c3fb32422138a122e581a627e35791da331bc905": "0x00000000000000000000000000000000049083308a14f56003ddeeadcf3e12c5f3685f05393380a47adc6be23c88d8b40a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaa92eeacb2f4017c0a409ce1eed912358015a8139383b02292284b392bf23ef9eb89c7f31ed7e10b": "0x00000000000000000000000000000000043c667aac50304fdae4ba9932ebe5628ff1e133986bb2e1ce686f28c6a5d4ac27", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaa96f99f2185e3646069548e7913a106991a40988bd63d25996d6788f9302ef0a86ec40b4e6bd36f": "0x00000000000000000000000000000000044ed4af096401134ae34367a42cf8bb5da1d3c878fe08b512baf5e9a4f7e9bf43", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaaa3cef8c09f417f2a807fc9b3748a0d6b964bff11360e00040fb5fc569a9595532f935286a45f47": "0x00000000000000000000000000000000047cca5de8c58ec8fd1a269c3e51acf6ad45a8b9b32e4a65a4d4c481c5c449d826", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaaff4d5a3b6c0d71aa7880fe9ca2bbf331fc13e40525dcb0da661f143df506fed76d8ada3db8f551": "0x000000000000000000000000000000000c5ad7885e61fefa8373066bbb08ffe85c08ecd11bafb3a9f85af75a4eabffaeae3f25ee912fc878195d9904d4474bf1ffa58d1570bdc39af3f8fdd88829b15655a01f4cca8129d5e282faedcd6547e6676e91c46067489a28711f89da641b1737", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eab7e3e98c718729f7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a": "0x000000000000000000000000000000001c8ff2fd995727bb6c776dce0c1e127955c1f191db6aff56c434a6738fc83d4eb8ae47a2ee72d479b5ae8c2237b156a6c584d82884c37be50958ea32c1aaef7832d8151ecb8e8d11e6c6bd81ae49216b9ef92d2b83b3ae39702a397922f14777680aed675c9de132c2b598f6fe8d256c8057b2d2cd28b2ae3fe6fad5475b407324bcbb3c28aa69648bcb3eb9b493c06256abecc144fca20c90144dc4dc920bff767cf5689832c7f3a596de7cf58e6d764884c33fa5bcadc7038e65e9361108b10fb2f9413214ee983786be59b316ce9fe3848ca7cf5cb20f109b3e31d09f213274", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eac3727c0a32917e62c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d41": "0x00000000000000000000000000000000104662cd48d69f8c1441434bc2c80a825ded8eb41d2c360f6ced694798678af7ab3cdf73c789cb02811fadd2fc2fad69647e6a22e18ff3b20c03cb9ed07ca0e69e3ab6cfff71e91eea05d195a10fc0a03a78667a6ee5a915fcfbb25e90bc258f088bfca4af1ecfc9a8af84f239f3f3198d12a666452d0658069c451723e7d922a8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eac6f1c6373257f1a4284fa7c290fb6052b9437610cfb2e19b3b37081fc72140e444d5b57ca01924d": "0x0000000000000000000000000000000008e6f485794ef2701691b1508c90cb2d3bbf6186bff0716c43915936439e0645a9c0ffc934cf4bfe0fd0cbb0153cc1f8c1f784ae59bc53da0e1833056c63b157a2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ead35c1615f01572956d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e": "0x00000000000000000000000000000000544ad16debf0db0329b8fa6806c88a774c6d4873579225919e24c856728b575d4de62e1df098a40f24df7e2359de24775b28736ded030da69a7ec3c809b10b6e5c66f3189c8351e824c55ea40817590b776431599273c4bd4c853b255e8cfb1b100071d7ea9d85cf0a22365cd41cca3f63121fbef0e1eea72109db9b12af8d4860649bd677aa43958fdeedca2f9159ce5de8d5a278c08e73c4ab9a713a24d0d47f1240c5bddabe0326741d3653bff06d6fcac311846cede93f8aa44a86a971924f42d7c710711e3f6a4d282c46bdc093a1796b6878a45c805827b838756ef78e18ceda44cb74eae64cceb6393fea849c84b6e7c0c00278b6339b14f882fabae15f1cc49a4b3adb82193695b2dc7507d28e72567060373e1e82206a0430005b694af02cd6695698754c7d8a82ef80e87a7c753c95c028557d15c393b9955fe74151048bc4da5e4289eeb52244056c70c535f165d37ad921c08b9d00466a1fbfe442589d797b259ba12d5f74d118a2f63fdd5b519b69003821b9da81614225776a2a9801988b622814386aa36c7aeb697cc35596ede2bcc7e3c7f7c83d99192c611e046511c11fc56b5492bf9fdb92b3ecf551ebb98b73241db611b2a44decbeb85618b8c0db8e0d79d681abc2cde9bcdf73e8b84b9e893952d5528d849a465f9a25c234c72214c38e8cb025a2b0995370d26b4113bec935efcedeca89dd30d21275ce384d806d03a4618c1365850015bacaab7b19a86849f627743dc2b1b6c90573ac5912fc44a3f886271bf2e8f0dd2d5f102f7bc313f1009b771526114fdc2d70007b26343e6ebaed9459ffaae9358c5b2460902c2a0d63d68a748e1d8eb1503364c23bf3c5f9b5c2b83e9bf6722b1a6c15671dd610c63009b0f67d4daa521b4d049590cf81393b2630cb72573fff37feee32bc143021d79faf80abf0356d5450", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eadb4fe3a15170520a6659e4c3f22c2aa97d54a36e31ab57a617af62bd43ec62ed570771492069270": "0x00000000000000000000000000000000048c21fb36ae0d9d838e3e635f7d867a4eb44fcedbfc8f3d03f22f342f2a64b38a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eaeb7ceb911a5fe458c2f8f1570391214b89f82df1e2e0c12f9e2e814cc8e38b3d8baf3692724a311": "0x0000000000000000000000000000000004c2b69f99b0ddfb88c8fa9df62c4865ca4e69515a21c16bde93c726b1e678a156", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eafa63c93073adc978e06bfc989509d6d625c085209adb405867bdbe4f167ded7e61ec126c683165d": "0x000000000000000000000000000000000850d1a6eb9d16f107a16aedb586c8d08259b212a3c54563f183dae7e1964d931e600456bf4a3edc3d8ce8fc483ea6b102c620264661f24c3f33b4b41ca8e54450", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eafab87883b2986dc6ee5ad3ea0da40510f11f42c3281fd543f5a6bfad54ebef7381a7320bb509a0d": "0x0000000000000000000000000000000008524c4404c14e7fbda3e893815a3eca9a05f453ff0f73212319201a2f46d5382a06bd7c7a1535c6be092a798d558a5757ce89567f7cd939fe203163a8c4264e6a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eafdded1663a63773142eba87db082b693b5f35e88d7a70409b0ddb61d430abf218884d4467af1024": "0x000000000000000000000000000000000497d5a706146081fdd5ce77ad4ee232f351c4bbbce94596c12d300efae588ce9e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb0c27f90ac9d10a58adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48": "0x000000000000000000000000000000004840e877da5560adb4bb476e067659f4446675875a5e49cac2d3a4ad207adf450a346c4cf9a3d4e2bbeeb47694406ec7bb64e9c25e695f5a9051cb8119ca8e216d0ede8b484ae583e43b011ee69f561cc3d145aa542269304d76b034ec0df99f3f3e94cee09a8718b5957b697f388b7300815ae76c15d0ca5c0b0cefc84d5a7d4b980e50eb048a8102b537fad10ac389068a37e29e93ed6cdb700ee571eb98811626e1393aaa4e42b5d40f234eeeff068825d5cc50a3802e8e2e488694527b5e7cc0c6960f5ed4ae55f47327fec246d858b57f0d4baafbb54920e0bd47e1dd721e58a72e119fd6922255ddcb1b3f89bab2286d43b9bb3f5b3fd1d3df6a6fb727676cd55c3ecbc354fceb81b0ac3ae860ef4a3794e1aa9e31477de7c2cd36ccf11d9a3bd9c292ba18b98cdfeddc8e45fc0a4eb962baa86c5d839ff3e433de19944ad8900a50ea497ab51afd5227503f91b03a91584b72146c2e485d149cf67f543f8e2ca3235e29d530a16e44fdc3a6ce04c42aaff4ed9b7c275bb9ced877bde9790033f9ee5f550181bf234c12c2e07ef74652d9323c13ab31ea9c2b053eac74580036d9a09a0a63e987a6c67a59b52f9eedf6215852cdb4fd034ec99475a17f1e0208bf1b4851b0e3013141e274ea24d6a498412f2703e598e87b7fbdfbc2a72d1015f23420ba4e90023e3df81d423db7fe2b2691657d45e98f02816e5a832b10a872a2b4f736ef9a7242e0a0d8e64d616ed4c2da9a103707e9ac7807a764292f86434ea1ed238bc9c3106178b9371fda26e3d4333adc04513d188844a789c844", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb0f0b3ac307cd751749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b757": "0x00000000000000000000000000000000187c7c8105064a32c52de4d09d9b9dc358756f37ccae41c1ae71178ce302ff5374b2f0176465f8cf99c213696538dac784ba8c59e4f577c6fa88555bb5f28ecd35f69f5924c239023e8555b80a7323494f03c76357fac283664c131a90d13bf9719a7994a63250d77c7cf6ea9f364f136dfd163cf4ee30d1fbf5de6808e443f25cc8ceb3b9d38e7a25f5016eba5e885ade09042c214623524d78c73f6ce9bcf95fbc97eeb4ec96658e0ec1d15b07524376ed7e1444bd35f3c4fc21526176f4c979", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb0fe6b98334d7d6cc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed8054": "0x0000000000000000000000000000000040668103daef522e6916064ee8e27db33ab950e2d4f065276f7c9d86efbdab3b7d0cbb4adb01af79c560636910430458ac44cf5fb9e24482279191e6ad8aa33148bcc2112d8a9de4645c4ff651aa6efa2f301c9d6a2355f1bf0e6a80826f50016e72f10843313abdcc3fe2ab623e213c561d68539db6f9b47f72a41f2946c7fc45b64bfb076e6685695cbb09316f448529f41964fbbc9520059a0aeed64d63761bfe0dcc8db8a90eed611a4510a8131240174ca310a563a343fdac7fc1060b0b04166a40c58fac1476b58784d0ed59ae59fc516a4b072ba8daeda31d638a53023a5e5167d2749eb21e8d257aca0e738ebdf309e9e0ef503e1184463de7db3d0b28ec194255613dc072122c8330dc7c18e15b12e5eb3093a442224e91e50cba7d3dc68dc89f99b0b46b9e3a10f9b115283e27b7f6fd591a9f6cf53fbaf1b1a4685f90f218ede5ef0e08fcde53a9913c8c01d7cc28d31d21d89071b6a8d9262d8376deaefd68c861d01a4472a1c518bdacd7f99b6c4a0b64ba32d74995a21405797a4caba24b45e5bb6eda6ae45de9e1fd6aa64fb43bd9086694c4935d21872a5502866f40b96e6ca6405ed0c44747726b3972ca4773aac5273dcc25ffbb5003b07536a8ff1b35d2750c1d8482b5f8290d835f5e497bcb9ebf11928d9de622fc30532c21eb7992f79d2d844f3006382236000c2b1eeb4c8985c6ed6db26734ec2e70", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb19b71d671b6baa2aad8e905d4c09ac501fc3f74833019107288077bdaa77291588b5e021330657c": "0x0000000000000000000000000000000004fc2dda4a648f70d73746458b1109134bbda7b43b46ab3546d310823e36966d76", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb2f651117e3fd34c84bda1949a2b78bfc3b12dcc8f2c8e8822912efe0c693a23effaf7f3b54e9a5c": "0x00000000000000000000000000000000049257672efbce6327e97783808a8feb2ef8dfa71bdff401f06700337dae17a253", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb30a0d7012b77142a86620314a174486a9938856e3b939de3bcd73458780f542388be0cd66379e28": "0x00000000000000000000000000000000049fb287e33d2e6433438c3584150a857912afdca0c065f86275b53fe95d3f8192", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb357e4ead78873ac2aa53f55efa82a9820f3c2569d4e52dc467475a1a11cfc9861ce5440316edb7a": "0x000000000000000000000000000000000c3789e73dd3cb036f57dda3ed96e000aa87721b8e19205610d2625e3847f1a06bba7e6ae859516ab7792519d1ccc7781409bc58e534f54f4edd0981118d53405a30ed0348562c1ed74187bf91ab00d4f734ce2505a6d6f5d189ca1f8dc966e665", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb4736827e2622569824651190f1d20237fea2d5953bb53ec59df25d581e54f291d6978c9a8017741": "0x0000000000000000000000000000000004f4ecfa7baadacf1a3aa65baba89f28312db782c43e750e677dc40fca086f7b01", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb48b1b8f79a7433f88b9f3a722747e8f637b2583963ea7f1215adc8c75c3957554fdf92fcbfa5034": "0x00000000000000000000000000000000048c6211892518630b6e583e09dd395211035a508358a80322614f9894bdceb605", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb5421b6506f7f790ac59122f8bc8c527a8efde87156403558ea66ca0ef049cf3fa4f671f98517d61": "0x000000000000000000000000000000000436ea3b4376625f8f5ac0cf7b48b7a186f96bc215f34976f9eb692eadb46ce29a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb5c8f247935e6ce99e0bb283b2d2522a090d71d9c8fb484c7966d3e28b21bc513419ef7f70d6a563": "0x0000000000000000000000000000000004da466dea606e6a603356cbfece746254c6585b90647714222fb59e42ce45c601", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb5cbc9967f19afa3e295650fdd71d7046633b1fafd0881a3207719c573f17725fccddf854a8b5628": "0x000000000000000000000000000000000458b16e3eabd2cb50029bde70c7a7ec0123d1e710bbf45322f50be3f21ebf8747", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb5dece0984444d31a0c077265fa8ebb05329c968fe13efc415460cc5c379fb392a652ac07c9c2f7d": "0x0000000000000000000000000000000004cc710cc1444b51d4cb4d22fc47a446df6d8371a8831a515040a52d7cea1fe70d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb62acaa32f7e218efcc5b90bc1891b7d905423f7a00ffb4e8f3d59aa97491b5a1d45b82548639936": "0x0000000000000000000000000000000004d85148f0fd5fe1eae1bcafc4f9d970f692415245ce7bb7988bbd76b8dffdf02d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb67386b3a2bca62fa6805c6dc7757cea227e11839257d4e24ad39520621e99e6016ee0e1907c3315": "0x0000000000000000000000000000000004663b801c02f2b76565f5b60d817e7dd805babdc276b53d20e19cebd199c88555", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb6cfd687de7a23b4d60cf655685824e9966b0a10c01dc8b17b37e24944fdd760e4dd73ff1dd4ac14": "0x00000000000000000000000000000000089801bdf93fc1d4b0186e1295d517b03a5749b90c94a5468d74331a6ff529a953a830e5f0091c9f1c5da8a2a9a1a7a0de5802c6bdd3d9e23175d8c116ef226251", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb76acca59a92ef07ce072084c159fb3547381b718ac1660d14030e7bcbe9db68eef0f7c0e340f33b": "0x0000000000000000000000000000000004a620a613e0049a85c71fab0328f7449b0a9963195eab763760e1ff50a10d4404", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb82ca38b993a4d8b5a7aaed28c23b0b10d2fc6a0a914c93ce965749d67d7f657facb010255e4852e": "0x0000000000000000000000000000000004009ea4dab5c62d5da4b72e17b5ee5932a3098fa728b996bc7ed07f112702d32f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb8ed6b693822d4a77825b33ec8baf2d437c19856a6ce74f09bbf49c284602a18ecc0683874dd596e": "0x000000000000000000000000000000000876b2a1db526de647dd7aeeebd328bc037be6795e79e7235a23f74198387be12aeabaedff8f91f5afd170b1c8252522e76584565bda69f49ca2e223fdec4b5529", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb9206afde78e38223a154cb2e55ed80b9b671b240ccf20a8e2a47a7097a61f156eaebdc98fe4780a": "0x0000000000000000000000000000000004403c772cc5a0320a23db863c40b5780a9390665df1e3b4255f32df1a0afc396e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eb9f65131235fe195ce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d68": "0x00000000000000000000000000000000f0720436c87f73ebfaadd5ff7748bac986ab74277d57e5b946066d922884a5d80dc88752d6f18f0d5c804929cb727ce8999603dae997b121267ed59d5bb229af3b1ac5cc7855b95a4ea69568546a9e38214f4b6dc5de6cf1351649afd6b0bc800b106b2d295a9a3de6efade304e1efcd123cc66ec27ec92a075964ecac7229f54b26eb2cbbeb40e98cf9d5f39918fe54290600520ccfc9e519efb5779ddf48225f803f3ff57158c1e5483e88d4dd5d04f7f8ca3c5203c6ac29344f314099f96a314ab3e893de103d05f3e6e5f210faf6fb40fddb03be173eb3723cb33a074faf34feb86644e89b8c9daf871b44f7111264cc15bfd8efa38a255124412b9bcc58699e98a7c353052e4ff27d50ee1dea0f7379ccdbdaad823c457b755413243e967fa28ef91b1509ab5a2d494b230780761fb5e5ea00e01f7ce4296907b8b97f4c1e6e5bea81107431deda89d3b05e7e1656354c48d0a5cb767851726ed359371f7d70cfc338f687e55d944e8e6867f90a05085cfb5e15e2f0d5315ca27026d0aa5d6cd8d0f1e2161523b73cdde28b857e8d4c281ee0825d88c3658675561a2bda1d04961a29fdfab26086e085f26198e4839826299adf5158e0de4d266528642b5a22b6c1ab9ef945b7279a730423cf50ca4e25feeefd4953abdc0fc8caa403f70e8219020203f8d92b4c8ae0dc2a5a9c7c5641486ac27a4b591d3560b434650658386d313e669622ba62d89b48b2d4e7be50308ca20ec56fdb89ca5844952b3953a4242b97bcc4600c1de9c6f1a6ddb74b69d9521127a377d2717f6d9fed5ddf4ed47e15ef535a26d9ee0e3199ea99baf7cae9d94a05581316885d0b21549ddd4ecaad545c5c3d4c99b7866e2bcf2483dd7cc7cf578886586663aa25a96bc64205063e0fa2cd4f4b448d507f9d5b2ea8c85e8947a93d92d214be8f4b752807886e02a6ed2142a394d0f42a51281478530276f88d15657aa277b62c54bd1576f322ba91845c6ce9f14ebbb24f008964bd395a2c1f92149810d6f6133a905706000ec282b526ff533bee49db3c9c7ecba02b951f63f8442cc33443a78679d5246829fedd35f51de7e439bf432926351c41500f30fe78941f325c69dbb642f35095479c4151f0860839590586185a1dd97ef4f3fa86a6c0ad4eeb24addd8bca2aa758f60f07a15346b938937e245a9bc5f757c0a516b249d11c40ba8b0742109d573d148152531de95b53fa605b79b786c7f16397d3226ccc2f0beae85e2d7377093726053f965308328e14c097fbfc2b09b6b97256bd6a14ca1459ff9c1e8dec3556f8df53c69120d27f523d11d1704a4dba9448aee78ea4f1481cee14fa15124511a61366bf4c8e9f8fa63bdf70263753a1d34a66a616dca43b48c9f99d2c641c7e20912c81e6895f7b27bb4be5f6cb4750a326d3deeaba95ccce9a6bf6d1b9fd29661712f60a13d05e0c478d73f3a2dea9766c5d4b54a84895ed8b7f6a3f9506146c4d3e81cd1909e980648a1d2b7820cc93eafdf0151002f481c0b874502db473e45d4839be5ec40b585c1f08ac284e656075327d7038aaf795d35789ab10f15a5e26900b9067da461527acdd9856b0934eef5f0c099a2acdce01b51f02be2351c24dc5f34db1ba52471ff7e38158a4dcc3a19b6137b8e6023b72f889cacfe535240246fc1579b9f65b2c83cfa020ea61e54330741399b8acbc8b7215b8dbcf425e0a33a0fede6d4995303cad923ea9cb39de708069630184e76f3c276b76c772bca1d58132476c8e285668c7c1505e248d79821cc2244724f026d438a27d470ffc8d39aafef0cd3cc978a3b1354b65853a12b9f4ee0a55af14311a4de76b7b169061deeb89b61291cb59efc126c4add37ce655a7954f8e2b246fdad18c07d358fa0f5c211f7844143928941e88780961c972b189e6269ca6e0ad98fdae5c994d461021bfbc5b35676c92f37d8cc0205b39ca70fe448ddf0fdcf203e2b4ac4d070c2fb774bdca7e1b4627e9af2a9a66a0b67e7164af0fa26f20781e4b5fa2dc42489553ecd89d7eda44e51d14dd217fcd4e8f183036ebc916ebb32844bffa991574a0fe5948a9e16263adeced4ac5592a4e15ec77d223be684d9229ab3659fc702c34b3c3d2a9e4c126b3e6152b8ceeeb75c43d7530aa56ca6f41de5a5e76a2708e21a74a8d65c99c228e22e79b3e016bab0eb656a5235af8132c2a9a818c7a2cb43e9512a0b56f6e9080b36543163cd843c3816854a331c48cb107c63ee42f210cfd5ba5a03ebfcf979f3bb7d68fd694bfc64d37bf04ca7b2e87d4e38827f94c86b81e36ea46dc1b355c79bf38968367ed63d58e7b61e9aa5c97fb6fd94dcc3a8ccd612df568bb9b459480879224e360d0d8c3caf9365f1fe7d54b458b010b5084c45682961f27cba9bc64fceecf20016338daf42fef5cac7fd229d7727db1685c7c97a0165263b9287982692ec2845cdf8ea293108d3cf51f598b6e98da1f7d2cc63957be519774cb72783eef49a4a1dd53905dbf49a4a6f180a957e05630211ac452bda8e177f52bae23195e506bee27b7007bfbeda4f2010fa6220e029940b89b1a8c5532845c171dcfc78c4bd5c42c634e7d6548d6646c83fdc25bd4737b5a3b1634ed187e0ff740fa52e33f2748d0e88a19cec4e5c185cb00408a89b60578054da56ab2c696de80350f00924db18c896c3b9d66c26750628082750b332c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eba594f7276ff200c4e531ab22f712634089201978511b49aa987322314dcd8f16fa241f0055e3737": "0x00000000000000000000000000000000042c1800d8039258f2722009625f77a8203729e8770d6ea72358f165350233ec25", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eba6839973e6e9ad1e2a0a933d2b1e2dfd0c06baf42557bf4aa2ad84866859e6c869733d6baadf152": "0x00000000000000000000000000000000043eeebded302e53d488d9b063922447cf63e7638e60abdce4259c72dec9126a35", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebadc22310930427ba763de880dfe6c4bbdad18fab60e27002f648c221df5248b7d44a575b4bc7342": "0x0000000000000000000000000000000008b5adad0de4385f3ad6516e39fd6479b85c22886cb0cb9fd91ce52919fec98bbe6d192ca910ffc54858d1b7f553cae619803b55c69af50ee3bb1846f1715e6db6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebbdd44aa00ffeb9790174218ad9d5531fc97c3b347e073d347d157cc40a470ad89b75604b0d9dc33": "0x00000000000000000000000000000000048056875c26b0b99303e102f56af5b7cd6494578bfaf7eebc0f251a93a98c0710", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebca4e93e46a1ee7a83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f589": "0x00000000000000000000000000000000104e8c56b618a0c3750e9f005d58590bbd6b088c326a1fdb075294a8565b4192e8eaa9db4e448cc0b93c4cc1d5059f9bb7e017c51964e21916f2106cf56b702f646d3ffc8efc1d719ddf99d29c8a1b285ff855969c4fff0668f9985a6b41c4b49992b53a95c31152cb0d95a968db4dc8e14cb7f4495f4b3215db38d0fb6b8a8287", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebce3132e4ef55facd425daddf60b2545e07c695d32d6bea2b9343f1528052b4edd1a777e93058565": "0x000000000000000000000000000000000464aa224ccde37501e8661ac74a75eb9c2a6793b13e40828860deae744d806346", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebe092d7e5aeb9a7802948b18cd5001e68a33499343bd8ed974fc8398bbfdc3dfafbc7c478544f67d": "0x00000000000000000000000000000000045c899bdf0bebcb57f0f68da86b80f8840407e7388ee52cbbc1a60f18a7a2eb58", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebe3990dcba28e51a80dea82a6a4704d208bd43d1ea1d5a0bd97a9d20c5237beb348be8c82f37d93c": "0x0000000000000000000000000000000004eea34392724db7a397808df783a7fe52ae6436bd9c2d86af32abe8dd81f43c33", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebe3a70de3dc8981a02098b5f718885f0d6f0f18359a7d16b44c9229857934efe66daf4d9f0eb7a43": "0x0000000000000000000000000000000004ee9862cf3f7401d7c82461127102626135ac670ea079780708e1ad2c537d9c2b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebe6eb4fcd98b5e48225f2459239641fc50300041f8980fa044cb07705db61fefb340804172b1c25d": "0x00000000000000000000000000000000041884855fe5ccb84c814252cb959d599ee9f90de9d3b7c65058b75c39f21b2802", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebe87f9c4b210b250122ff96f07bd9c9b3961c4387d71362315d05addda58f1dcce642888a643f930": "0x0000000000000000000000000000000004bb3daa994e809e4484afce1c63b8737a9adb8a91ccb78d7002386a087b382de7", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebef054a6e8d99eba983c5a0d1f1e697c1a0f9798bc25543603751b41102d41c3b0e23cbc6e3fdc0b": "0x000000000000000000000000000000000c5edf939d9f238bce8f74fdb215d853697a5a515b0f8b3a9a9d64390265f2cad9ec46a834c9d9bad9de24c9d4c6c85d4f942e2c52134f408e7fef2381bcdf2dc2941acddb878c9380546d8e08a2c94431dd6943d8c238428364d4eaf95218075e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebf8e0379b44b6804dcf2917d37c64e3d60416e47b5185b4d6c3965ca531ecbe29e1d2cf759f5f871": "0x00000000000000000000000000000000041adfba8c2b21414451ce19bd06d2e9ab7541214eb3285ae73da678a755432237", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ebfd1adb8160d3d9cec8c97edfab0a07c37625d53be2075b8ea64a00ca71d80cffe94edb44d215e00": "0x0000000000000000000000000000000004f67e4658ee318d7985399480025fa332958346cd623a025948cae8a7db36a81a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec0e968a177335220aa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d": "0x0000000000000000000000000000000014c8c3dee0510e7e05a5ac3e8ab4e13befdeb0366408b0c47c5a41c887d7dfdd58206c097fd6569064a918b1fe42c9a302ee3762daa035b0c44eb771d6c34d1d08b4f54529b00e5295e6efaacfad2de17a22cfe1466f2ef142caf1328b5a701005e2c726e24b6fd7c2bf7bd253448f03cbe350cd0e36bcd621a82fd2732bf9c2069ac3a89771d2fc8c62e9d37bc6548f67306caeeb4ba49e7aef7c09b68a260665", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec11b1c3f82b75014e4d733aa6e16d24e220efa69687f6ff198317062ab5ee12a059d47b732c27624": "0x000000000000000000000000000000000428e3a8ec56f21d20789923fc326898987dbae48643c059d5ba9a8afe843a6f45", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec2531fceab22368da26c51051a9031ebcc5ae2a4eb9a72e444a5bff59b995ce4612ed8cabe8a2a70": "0x000000000000000000000000000000000472020fdf0cdf3cd952082b52fd11ac0df4cb360850efbe0d096126efeefbb6ca", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec3125cbfe931ee052c08cfa5b2dbfcf6850a3b836596d82a9ed7d2d743b42aa5c69798b502b29b57": "0x00000000000000000000000000000000044b514120fe1efd6da4118dab0e2b1fa66ff2eeaab54af205b2ec6c506b52fb76", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec39daa94631294ae14ce4e09b999c54351c75b74d0bafdd17d86d98b6aab5176b9068e1be13e096f": "0x000000000000000000000000000000000c55a7b1fbf19d76a12b4cefc4009405905cbea3fc16452627e6a01ff866e9b6f1bd19630ce7a6e94431c5f771e66232e46a034f3cd18006febacf02baad8311323ac5201c3a4b0b032e701e34988ca6a06831b69aadaf9a388dbd33d85ac85f6d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec3f2c1579fa4e27478baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07": "0x0000000000000000000000000000000020003afd6023b1888ca027ee106726fced92608aa111486ac2b82717744009ea04deea74425ab90f984007c4324ff21437aaacd212a1a5f349d31f03f735cce907d8ccc709448e61b19bc01bbe3be7d7e74c2303883ac6d06c19393f9c1140840f24177bf6f8ef353988a83494a9fd6a8ed1f89ce97daba4d8448c48035b646960a849df65d3f404d80ceae8a840ec60cdfef83ae70df3a6d681870c87d5a78f3110a89404fc6e546945ce58e433c4e88a17167caf4e763793cd3b048e4b0b594010a89401749948f217611353ab25e1789474699fc06ed1dbbcf44b7035f488759a7f00455c8ddda3532450ad2eae9a5405522b11b320e52851ac6fd870b12d12", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec46ba4a0042e414d9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d27755": "0x0000000000000000000000000000000010ca0ed2d57f858e89592c76cad4ac00258041aaccb971171ea43b6fc39a4c4c1ac34542e51274a1c23c1293574ed5da6a1c28d092ae4362cec0eca403c02244d040d1c7929a103e88681731f954862765bb66d96c36e22f82a35fe75cf7a72c205a3116fd94d5f079378c4b1f2066ff567078ae68d97100fa408185a98ee92fb2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec4b6532d1c37b711aa18b3cf52cb27fd19d5b80fe7982ff955e0d5124dae26ac360056f401dad846": "0x000000000000000000000000000000000ca6ef8a1f259f84d8e435d119d7c0b8f4d91c7ef95bef739c81ff66a2cad2cc45cc2797a71c48e7e7f6defcf2dfe8c379a521c8500c9bbfbc13c8513cd5cdfa3bb06e4c7fa18e7887887e5b7424e8e2131e2a244163d4a70829f311a571d57c2e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec560adb2f53e7fdbba0518b2408a0883ce26ff4ea90f8639ac05332bf82260fc45033d7b5baa0a20": "0x0000000000000000000000000000000004d2ec0a695435c6324bfc9b27dff217e5092e2972b0123529514006e278914c7c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec56c778db308e44b8e32641448f9a5ec78ad04a33b7874a2942ca7ad4c7e8ee2e45409cee1883e06": "0x0000000000000000000000000000000004681559f05e3544030950899e305d923d8e11e244943c1520c35e801253d28008", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec59c65c996cb7128c8d887817cd801c256ae0adad712737a18a89e23eb061b7002839d16530fa0d8": "0x0000000000000000000000000000000008e2612e76480388dcc8dfc46219130946f276496403ecbdd37a6d1a14c35701aad7a7116db2d1bd9dd4c7b37c204dc775888f9310a1a18877ee913901bc95281d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec5a064463897ec28ba98d1704adcb69b1d50aebfab39709c03713555e3d49e75690492b0a02f547c": "0x0000000000000000000000000000000004c1c0081353c756023d47df0da1d4c1b9eee95b9bb90058215e6b42ec5b00d525", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec62d71f1d9e80b5e284eb76f4116f4b75a718fd1a374cc5b6e02fc18f37e02deb3054e57539c5328": "0x0000000000000000000000000000000004284e0442b44363d362b1194b107f46ec28e76932170fdbbf8077dbe87aa26001", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec637b13dd6b9ed4474c76b2bb6e2e4b16fec1849aefadeae913aed26e72e2101a4dc34abb3e40776": "0x000000000000000000000000000000000846911250513cf4880a89dd8ee3e32cd8363d0f3a064767a4fd19635f2605475eb06c021615bf00ced6ccd77c0bc8c820a71e819bfc48dff36ffb12d7ba044338", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec67401b1f25d1590b45b073f1e692d18c2dcebae861b2f166a4dbfd95d9780ffef603c9e61d00935": "0x00000000000000000000000000000000082dc4deb5830a5e765042800fdbf03927e72ad3d40644360b07cf9ac241638701d76236f0c5d432f6e6b99845a7eada1491dfa6288c36dbafe21b45a0d90488d0", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec6bbf3f9dd9143a5fe6c31fcff28694469c3d4c1681270bdacf6edf7ec39bda6c68cf25738268b79": "0x0000000000000000000000000000000008a2fa6c11ee56da6d5e51439a0d0ee776c8b4f0f6a914cf6bd9ed8af27db80252164f70bb86b671d46c1748f38329f50db8fc5461a4ba4dbbfaca7a47bd063962", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec6c6796a808b7f32a8a99a7f49f1d3d72656674fea67bc18454325f00c9a5921ec6010c43409d43e": "0x00000000000000000000000000000000045263f205d321ac0063c4275a7daec9c6b5a34b3f0cb835ca2f4fb22bd9e55e5d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec7e9bc04cc0841dad6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c25": "0x0000000000000000000000000000000010e6ba74e93df6c3e3cd1615c99708e867e1f3160e324fdcce53be8e3b733e663a4462badaa1c9c6bf3e368c5de7a206c0e8c1ec70ff0c8c5d2a51545e0514ae309810e91f40b4c50ff66c7d228a9e4109e677c406cd6d2417bfb11f0899345e00c44a96f5d752d040b443a98592bb0d42719b2cf3ebe538fc10f76637bc054e7a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ec9c02a3bfc8b9747e2b3d30136a5bf1ad99ed78efc1c0cfdc6a2c65d3e30d86b3303f3533e155032": "0x0000000000000000000000000000000004894b90350435a6f04536b6a1c0f50e83344ac230902f07fd5e69953e8824d63f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eca8ae099693f9dabd8004911e882a05affdcf81aea45f611077f07a29dacf6b754bb69ab118ae067": "0x00000000000000000000000000000000042d3568072e73e8e73a9a8cab58e10779bcca9cc9d3da70ee41af6b5682fa1170", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecaa21989ef628ddcbc63ced3f8fec642128f2aa9c37e989a9313a67e9635dd85e8bd689ae8d0ce1d": "0x000000000000000000000000000000000c486e705093cbe54e60dbb3e63ecf3ffbc84bbfa2a1efd0a3a9282585e2f50772a82cd9ba02bdf8241a35d6a434c019a6078547e238df7a55c6dde5c4deb2f12c8011fa4c76d86408e873beeae9385075b1f735e05b59dca7fee6147c14952770", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecb3200a490ec72062033f1e89095d22a9c51162dbcce5e28a6b12957fdcb4c3cf11ea8def5ea1e22": "0x00000000000000000000000000000000049862f63cee080f43d1d4de935b51b615cd7a15682e28e41f0bdf6565deaadc06", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecbc819e175aad208ac2709eb9569c861e63940eefaec1f51ccb76eaa84544e56331adfcdec859911": "0x0000000000000000000000000000000004460fbb15abc6a11bacac5accdd7a64ac63bf649e22c4efb879ff0cb0446b7e8f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecc718a6b9e9964318ef5289702f6b8c7d22b3562ffda7d5593a5f6414226925e72097efbf9b25720": "0x0000000000000000000000000000000004e35a5bb9f11f2d71940593c4ff87fba89a7ab269825da6282025c43bf0b4c07c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecc9822c9da4c837c86b7409a11700afb027924cb40fa43889d98709ea35319d48fea85dd35004e64": "0x000000000000000000000000000000000cf826721deb8c5d5f99d57fab56da2e28286fb7ad92f148b05d1aa353fea2b26ace10c51e89ab2907983cc8b846d9d1afa2f9700db18e176c7fcfe709d0406339de4a3a5ffb49ce7652bd6a9f98cb78bc68c2360c6e55fcbd6d6d5aa6b0f2347e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eccf50f8320382ca644da8d011a0f821b2e39d6151f8e17c417c0e09b664587dfe2021a194ee95d74": "0x000000000000000000000000000000000441593cf289a037eaf22bfa42c5f10c5325340bd4f488cb37fc72f65cb83f51cf", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecd07125b43213e171c82102e4554587f23cbd4bfdb0f43c9d2879d18feb6102bbed977930f695f22": "0x0000000000000000000000000000000008f6f9a8d8e0eb8f9113107b5f2bc4c3bf64a31c6ce51913433873e4357bd35524e64a8c8a0cd5301afb20483923ad8427c597ba471a6fa868947270768bdd2713", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecd367e518a4206c79653ea6fa2a3e4072178c4de671464a69d9c72c7ff7170bc76697b46b3947b0f": "0x0000000000000000000000000000000004f204ee949a256b7e81637b358f1d8519458e9b79cec9f1e345ff9d2ad4516370", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecd4a30ce889e7a55c04f1633da0ab6cb71f71ece4d1a5c32926d3f707d250f66ab712d65eb374b2d": "0x0000000000000000000000000000000004407ffe0ae098321e72b2b6fe6ba331285a2967a27430f04375910007010589c2", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecda070697bb44382d2cfdfb80cb90a4a5826c98846a367489fd25d3a2561838fa372f39f3f7fb138": "0x000000000000000000000000000000000897a78ac6bd50295c46bc350d252714c70dffccdaa6c1740dce1da940acbec1d19b1e47be56602b6fd57d873573f8e1cf67e97ee448fabff165be2cd9b7b6a777", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecde110fa4c51bbb438a48b1b98077c557c474ad091c854286fdf929b0e710299b16daae9e0ae4a77": "0x0000000000000000000000000000000004f2e0c893582b2b34b415274bf95b65f52ab82079a097a9ed28349eb9a7bae745", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ece0fc9b4caf7f03d56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b115": "0x0000000000000000000000000000000014506014a02fa72b89b1b4ce899d40e369b2ab4d06fc1ead4663c856bae3d9db60d05bd77a93988e8d68d67733df1c5c149fcaf773e6a74e70428b2aaedb018ac93c0579545b855f0070c2ca5c79342e333fe698081f709b7da3c9117b0b6b3e66ad37814b38fe39243c36ec13d832f06e178267058a03d5011f4e06ab78f67e0d9a73a50c79a8b6552ac4628486f70e2efdc87020ce5460f6c7c5153429a61f58", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ece591cccc3c347d0fc90e922a45ef6a5dc3c8abed38bb0aae5b9aa7efcd388fab60e329fe9c2d945": "0x00000000000000000000000000000000049a48686506ea99e3f79e0643854fd07392d8e59f7249b61557e1662de58ee059", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecea9b7b0be6d4be2f0e5ac8e356d7a3867e9919b8cb1984ee5a070b1659b6195deb85039a3b69928": "0x00000000000000000000000000000000041ccc2a2abfdd492dc72fddeaae0b32888f3397860a31b3fcc88430f7c5338c40", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ecf1172ac1fb91b86c07040b1be7aedb10ffc0f136b7e147e4a1ad56944c1c76d6c2f6ca089cf316b": "0x0000000000000000000000000000000004faeef086f38d55942fa48bacc018724b488f46ecfc2828d879c7b780c8f57b0e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed0524a63ed8afdc650df6ec6f3dbb1134df6fd1d572d4dfdbe1058fca0e7197ef8d0f3d05a720f5e": "0x000000000000000000000000000000000422dd0bd944bf21712d577daa894b5d2def3b907ed1ce8cb334dff3c8216e1a59", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed0fb318e6895ef127add073714bbf9da81fe49db63778e918217e56c55e4f81f68e7d2e7d0e59d0e": "0x0000000000000000000000000000000004820f781b839533ebb3f3606d6bdb794136b3da9a8eab8ddb2f4b2c29cefb515a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed13778bef3c90858128b1857f835ab1569c06a71e4de49df3154a9d5a5fabfa2a4f1ab1c458bc140": "0x00000000000000000000000000000000044445d3cb2872e596cdcab7e8ac9815a369a6d4277f831287523ad9da7e60a53e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed164f9f8d9b541902e69ac91dc2b3e54afd2d74736e7dfd95faa1e738dab066c80328980c7c9076e": "0x000000000000000000000000000000000c0ad8b4f94dc8e6229e2c448d995094cdc1bd356dc14c6155467ac07ede18b8720f6987ec94f7c186a7c76fd7792be048d9e73494daaf0f86245f2f68cef20b2a6e63e1f89c023383484d1f16ea1d9fd66d46387f929dcdada62f8e5dcfcc9221", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed21b6f71d23b15bb1ea86f3c82538c486a25d8abca26760e57e76a01212419c7f1c8b510121fca73": "0x000000000000000000000000000000000815a946a44e88eac4fe2568b67d675983e9617e83d70d3ad6d9ec28707203be7eff07f170fb1e51a81ed96a4ca36d82decd18c5aefabae24a03d36ec5f8ffb257", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed25b2b83caf5ac06d857fcac7bd9bb03551d70b9743895a98b74b06e54bdc34f1b27ab240356857d": "0x0000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed2f1f3681fa9bb4720112dff656489548b0a7815a06d3a59f93880ea46ee2662a6439bb431bab046": "0x0000000000000000000000000000000004367c5a125977696926fd9820f8282c73f7a2cc8fa0dff0f0153cd7519d6ff316", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed3b4bb9b7ce70c8d4e3711ff0fdcfc953c9ff93355ed42146e442c256b6010ddd5b5fe0ee8b8ac1c": "0x00000000000000000000000000000000083012b3f9f22dfe0f9f29a97eb2fbcd227e5bd4f9c27df3a24816f9fd3a4b17130d3fb75084e9d91405dffa8b3f1396968dd935308d4dddc0e119fbd6be444482", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed3ede878555e1dcebebf5aa73bf19935376f19460dacf00bf0dcd021ca37d6a2284cc6347dfbb13b": "0x00000000000000000000000000000000089a3e193ef4ff85f45060902986dd3ba10afd3e4a0749b6718119298be183bfde7cc30da54f59bf041de60af0a1eeaea965edff0ba95e43be290b08ff15f91716", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed4351e7307bc37c8d82318297ca7af51ac2546ea6bd24acca272e1627db952e2ca35df527a3cf257": "0x00000000000000000000000000000000048c6d54d22c18c9072a83594d805c1a6c4a06940528eac4c3cd44359dcf9aee4a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed435a9777e7ecc393c5862ed65c524b7bb3564776a81904218f44f3d7c35162a608e39dbadbcda05": "0x00000000000000000000000000000000043c5862ed65c524b7bb3564776a81904218f44f3d7c35162a608e39dbadbcda05", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed4ed4dd340a2cebbbc486ed2f394da6e6b58b130687b48d3d19f756ba6d0655d37bf58ff0f59f974": "0x000000000000000000000000000000000c64563004d7fde7f69c99e461d43e799f2b8bc69c9c6941a265f5fe1e7e50c4646268664daaa26e11b1691bbada389dcefe14898f05214f50027c797d8004f777513b35b8d169fb8f713504d252be09827c6e9fa2197df14bbe563efe67af51d6", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed509c5c59195b1ec5c3739d60301126756a7510e34f9d656d4435cd4fe64bbd001f1f3473bc9c333": "0x0000000000000000000000000000000004a08c23158a93a3aa7de94d3ced1c9e1b4ed1efbb1e29dab0363b1c8ca4904e06", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed5ce1fd9020fbeba60b791f8467410a5ce2e880cc222933ad50705664917bc9d190a52596b987121": "0x0000000000000000000000000000000004982f4a55b705be63aaa88e069f4f93a955cc2e1c7dab295388d4a739ef6cb34b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed87333d9765befa4e643e4515fa656d6d830c088ec251ab76ba6cebd85be7e7d6362eafff654e222": "0x00000000000000000000000000000000045c9d4bed4df1d87e33b03c63aef108b00b23253cc0cda93b528ea9f95c33f522", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed87f50ab0b5f9643ec5909db1fe8581fbe80eaf39b4577c12a99d5abc87131bc3d4363f623412f42": "0x00000000000000000000000000000000042e0c76ebaeb0ca61c682a80271d95abff7bd6249acb3f90cd702df6f23368b16", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed8c344e11655410c54fda5a0e241e5497283afebd81b53f6a0235abf62a9bd39594be3f42d291e7f": "0x0000000000000000000000000000000004867c63888fb81ef44bb0d5b761d8b536abaaaf5dae3b5d23891554e924049a4a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed97b21772959b4b83870abfd18505f673c1808b61dd0d7067a810a9719c2ddee18f9b879752f4c50": "0x0000000000000000000000000000000004ca4acfb773d3f44cb7ddeef0caf203eb82d3366bef8d775a0533ef152431b633", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ed994ff06d05e1d5898989f74514aeaf57d4f41069770242a83d619c9ae5d46cc05b85136edd53776": "0x000000000000000000000000000000000424edcf58959173bb907319517828c0e5949a178917099537bfa4895695e5d00f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eda1658728cb5fb3c82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e745": "0x000000000000000000000000000000001438f0ee79e61dd2bd100c13719c468038ec4d722104b0a95fc38af7057c28fa502ab862c753d2f6331a4403f28cdd60a942d5611882e934c079a55145f49f9659b8296804203c1734a4dd445fde8f702f106965c6a6b33e44896af15ad093c0697618f7a742a744daaea9f6761f81fc54933a584cc5b4870a47e9525f42cb176096413aaaa130817e645a00e8f380264161aa37a6ef35c2328f4c79565ae9e408", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eda569c826c2fd86b76739ac0320c03658b64366855bd6ab037488fb23fa0d183f53b989106e25a2d": "0x0000000000000000000000000000000004203fade9dcd70e45da97d67ec48f8c5d8176be2e27cf3a612b6d6d7473c05577", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edaf69a211b7a8ea508a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f": "0x000000000000000000000000000000001c1bb5e480e154b39b0e8e272ba015da6daf3f9f634fd357cd5f8611b29b7d4e51e2e0c7c189cf04f3600624f5fed3a2107ab6ccf9625663babd571b492bb27cf942091485cb911996df13bf18b2ced631569a74c5e43790f285fa4ec64142d5030d32b36853f65bf42ac0bdd182edd4601c8503e927fcbbd1f34f1f74048cee6ac2b0f22e091372190ee2f4f79357f9084e1a9d3bc9af30e41db16a3fb31fd3d192def6fae3d1c6c1598aaaa7dfbd7038c3e047da285f993929e25bfea8d04b40a618dac7de8bd9fe8561c672d303c542f356e8f27be541bb6e54e80141d8187e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edb564ac3abd62540844152eccf08725bea8ce898d6fc5362ff2d0bc9dfc21ed15fd138438d160622": "0x0000000000000000000000000000000008c419b5e959b021c52f9afc64d96ab1130da2a03f08f820789a20faa24a206163e4f861ee16e48158f3a84e6e04f1959495fa8b39f13b39c2d3a9a464151f595e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edb70f2601c34332880a135db57d4d35273d9a4f661d3dad8f153a1b5bad478f9b0e5223657aabc0b": "0x0000000000000000000000000000000004d6c6649ddfbc12a755845a05072148efc0d82ff7cf4491ba4e63cc97495b3735", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edbc1bb2de0590492cca2a0719fad006090aad6536ca8b7d8c527589be01b0012564dbdd36d9a4923": "0x00000000000000000000000000000000083f9bd8000dedbde0a47dbd7bf089dee1fa558ac28796942a5883af07ea59fce1c0266f91841edb77e30346c6da3975b5c3ffce4a2b1ddeb696527bcc0279f3ce", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edcacdfdedda85ff952e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818": "0x000000000000000000000000000000002c4a4ad21f7448e3183c18b8314ffecf0b382098635efdd056e0af7c53228ba4262a5a25fb22ae60a8a24177845715bb880e16ad84344e91d1269ea6940e929f5b920799b25e259ab600be83eedfa7807ac27a842f005dea4a2bd49799840f4b3a449e6184747b236ba5577c3560b7739e35718c65039b8997b7e723722512b310fc53b8a54a21149380351cadce380bcd0028cec8145c34fbb67db6176dbcd31c6c8bfefb8ac4b47696a47ba939ccc48415c02fe947afd32437190cf5a36440024e9807808e2487f1a38ae21d64de700342dd7feac9c23a7293da4687e668e71d109507526c7136932a5129122ab622dd17ca59db69ebb7ab94ede6f7992fe854ee67b25f8646b574d06dda6da0b74ececa842c48cdc5bd8fabb48276f28a6043f444730a05ea7fe71e53277384e8e78bc1c8b8c6858d2b177e16d6d1b05c12654e8b6fcf0dee98dcb0d710fab325fdc6b158964c7011e9a43be877bae760717f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edda1f8e340e37b261c39ef78e57f239200072aa865312f87edfcb4d4133c6ccc0a7e33f5c799e201": "0x0000000000000000000000000000000004d45b3d8d71f6ca469454a375a951d272db9426e3712e172272f951d8b289d300", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ede17584cd268e75b0277ce02b2ac78ceeb9ae4fa0a595005489bf3f5f77898415e32a3e9504a5314": "0x000000000000000000000000000000000c544e2e588c90a2e53e051d2f87d40e222e1f034913a30f95a9a2f39114e5be3810230b53a6fbe58eb3eacc65cd3ef675e0456529cfb02a97eb43ff93bb6f8064cadcba686c8bd7b8579cacb9e1233fee5eba81db5e7c25328b724198bc499b2b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edea8918004244b5bae0ce04d8021516cbf0a10c00c4e721319c1e91c729402b232942f9e2c152320": "0x0000000000000000000000000000000004c4ceb4225a9a168528d1264733d5b6bb5176c0eb31bb4ca3c962be4cdcbacf71", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edecae94c7ca0c861584d715bcb7a2d3b6a3120891dba91b19b12df42cd50f1c76103e2581d5b4274": "0x0000000000000000000000000000000008c2bf131a9bc49208383fce6b0ebd78517ff563ff812f146c441d917dbe726c4dc2bf131a9bc49208383fce6b0ebd78517ff563ff812f146c441d917dbe726c4d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edfda9759c850e63fcad4349f82754f223d99182a3f9de949c41ff94e672f7f548e7f4e66c04b5c1b": "0x000000000000000000000000000000000486cb4a7d71b52b87a0ba07d245f92cc52dd40259d14190cd15f36b509f7ff511", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37edff9d344c62cc1a2a89a9920a98f3591ccc0a1a4bc827a0adfba37b75fcc108ae3c7191bb9a32750": "0x0000000000000000000000000000000004cefcdee5940f8e74338264c625fd7fe4c671ce205773f69e8bf4cf1b372f8e26", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee0e206491404b059c229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a65": "0x0000000000000000000000000000000040b046bbfb0ab2a461c916bd646f879787adaed72992ff0182233cc798fc9a2c314c9f8b6c9bbd518b19a4fe57cb38df839f9d893c577a9106579de22ab1ebbb36de670277a4ec31a0664f1d47eb01a7fc351952d63980ac1246ae1e6751f615041883cb0c880e437370dbe0ab6747e1d6fc6decf1e0ef4f423b815f14e3ffc00956c33c3e6261199d162ed7e756297752416cc7f7dc0eec30460a12a0a7e0c577c08ef34fd7c513a00cc447d3a01368dfb0df9d3c84ee52182b8749e18573e14d80de9a994f4ebfe1053baf13182362e06fe78b159c319be596fbbd8d027db5768a51fcf7cd53d24e15d85b8180f31d5f9b295af7841f9448f80b7264f381875222caae65e7ded01a955d36299f613aa1636767c9944621bf5eb149290339b97bd047791087bdd0caca708a478371eb8dfc056a36028504ea64f4cc43713fa9180069c3ebd00f7ee39c7f8affd0d14205768535bf95633e60e26f8c8006c27f5366e499f4ab6510c9b071eb403111b1d51b97195af9cc2aa65db79f3b84f0976298735853f4d1ce4c0e545e53dbbd8c65fe5f89385fecbb646a26fe00cad7795952e2931449f8d897dd10fe7f753414821fc90698d940050169a863db5093bc3bfaf6136c1b5c48e96fa266bedbb262f30748b53d9da7a435423272e1e67ede7968ae914b1cddf602f7e775099eb62db646dcdabf6c32fc0bb1b951e94130503d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee26aa6ab4f40124e083f39607241c8ebb62919ab2ed816cb6b20c7d0abad78a92570030d2f96c63c": "0x00000000000000000000000000000000040119766bce9e7ccb7adf4b74870a29b352995478848ad500f46166c797f1c326", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee31e32af7d282fd42cf0838b05fb182718de859525fa1e6d53d557e5fcf631ee9ff44c619810d43b": "0x0000000000000000000000000000000008426cf52dc5549d7f8fee37c20ba68afd3443973a05bf692185cb913fac80887320430a70d2db1bf57c424e5e81de47ade7f1f0ceae2b568b9182ecf9b025aa35", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee3e9a46b476478204c4769cc1bf4774f19c7433e31a5b8cb686944cdd758e193d264410d4918b120": "0x0000000000000000000000000000000008742e6def792a15d4b2518cd2a957f9bb7f75525308355f9217a2df17a701128a4729298bb2a53d0e5974d34d14932af4d4905334d5f9a57d7931ed1eb04eae67", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee424960c1224933864e05e73625f3f0991e3062733ad8480c5589a710a24beacbaa555f1c4a7f064": "0x00000000000000000000000000000000040ac2e966527ec0e3076ac6ae05402fe763d6cae60a8c01e108dfbb6e92d0863e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee4a7b18b604b590ebe4b9973a7f6a5586a38fa295ec8e64d4026aa878c840630a7ccfa7f3914d162": "0x000000000000000000000000000000000428e219b7c6307a185ea3d7d203fcbf5b78176fc0601cd62b1a3ab95e81e06116", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee4b5facde9bf411dee16a0a68c6bb00ee88ee56a12ad67e778bbee540f868ead35fb6851fc522c0e": "0x00000000000000000000000000000000048e74741b4eab0c60f4b1621f8d244da79dc84785622e52ac8e4e5d3da9f9e512", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee4cea58d581e6c8f707c9246c1c227f1495885cb2f4c59297248ec5abeff2d0f68495075a16bc17a": "0x0000000000000000000000000000000008289fad9cb619fa9f9b77fd385d003476fdacaaac6ba7191bf5486aa09e1d83298224620901db3a08a236f1417e7f865c079b41c0b2e6cb0084109e4be3fb1d0f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee5ec7a33cbbb8d9e04f3da939fa351c562c7e06e1e3716976b5e14230e83a45995cbad9086f49e17": "0x00000000000000000000000000000000046d6f646c70792f6e6f706c730012000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee6c2c15d71b57c80a8cc040d5d391967b6c50b54d81dbc18acf06fd13a704decc7df6f464679051b": "0x00000000000000000000000000000000042a646f536fec9eeb72210c0a5ae166e0b0853846f4d052ffaf438696921bd725", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee806de170873b7f5bc955504a40c50ded178a8082516a78a68f503348c16b106fb2a1aa2c594743e": "0x00000000000000000000000000000000045ff5a4655138350a17e2dbb4ed130642abbe12b52ed03867883f0af9a1ef0cc8", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee86ac2d54fd84df0f4914e62f037cdb798c40ea01fd56e555b77635e0e9b7175b98bc9514021756c": "0x0000000000000000000000000000000004d228fd275f3f92e8b6ccc56a9437582dc59db70153ab33cdd77562661adda60f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee94531e277a1ad52dcb38c186bf97625f108b4832981d966ebed50d939349d4437a6f538d40d5676": "0x0000000000000000000000000000000008473d3b1ef58c6170dd0d8e4f61cdd1d594cd17280988b52a7333b3a98fed4269eccb809fabe7f585098c7e61345f71c2e651c9fb61f16ea74a5ed6279a644d74", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee9521ce485bf220366a4d150e1799ed9ffa721e7e95397c4484db801fb7f26fbc4f27e1d158ef839": "0x00000000000000000000000000000000043650aa13fb0f5a4c3a5ae264eb820463be11b8fdbe5fd09cb34df93c19430a22", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee991a1b779e8a17838ae9a751c06cfc8b4bfb06f4d0b8d88df80fc88317415ad6f1b9bb6ca114941": "0x0000000000000000000000000000000004f16a6e2b7183e7a10f701d357d224e9ca87bfbc49a663fbfa27426a8f5e9b1d7", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee9a6cafc1c447d4fc2a82d0740d343bbcf853665019f2afe81ddeb884f76dbb5c74533610f72a732": "0x00000000000000000000000000000000085eb5606f625995f4a16ab77fab23443b28b5ae51964638b6c6d1020f5cdf5d04568538b172c522826347235dd841d08c6512bbddf1fcf91a10c9bb9542b75ca3", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee9a938ca9a4abd3102b2b0de562a79b5ad9c666c3f9e7752955f3b2c2b4a17c71125b2668ea9ce5a": "0x000000000000000000000000000000000420188a2097650af57e7cba4be37d595ec1884b69aafc65961210f295467a5313", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ee9a948cc19db68dda45d1343d565c182e0e1cd3da2d6c0b1ab5b17a77ca165457d9620db19439a64": "0x000000000000000000000000000000000443dde39c254993375b5d7905319e7700ebdbf57acd84e44b3025d869ba7d8e6b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eea41c7234ed3632dc50f089e43c19f3f4ce606cd994bbecc50bf8dc53e970c0c1c592304f651966f": "0x00000000000000000000000000000000049654bbc25d7891d49151110003c37da87fce6eb551768c02e47eae754b61b466", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eea99648ce61b6d52d86dba437fa4388bc312e57328e808cb1d37cd49143b90c338714703867edd7a": "0x0000000000000000000000000000000004fca784faea5287b50efffea3b8ec2995d80648fcf5292f38deeb5bcec2d15e2b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eebb9d8077a7da3fe98672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b6316": "0x000000000000000000000000000000000898672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b6316d8c5a6bb60ac4bf7517a02c2612d122e389ef4684a34b5f7be058113e9e74c75", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eebcbc6c0c66547df8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa": "0x00000000000000000000000000000000103c53243e05c79ffbbc910d8df74e4d1ae0197db16b7f00662e2aac74c8ceb3021f81e872efaf12f97f5a40b31afbf874bde9c0225e89511734f749b4b1d680ae29c22701c5675f9a1d0c99c86c5bd43a5c781b5029d080077926cd3d3d17a81f15ece2a3d6a57419d76a4a66bfb72185e128e3abdd1e13345052f43f21548a9c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eec9971789d54b940607b422f959ab305856c1621be625a1776d2ffddfac9a03446da3052d7cd3a58": "0x0000000000000000000000000000000004607b422f959ab305856c1621be625a1776d2ffddfac9a03446da3052d7cd3a58", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eed170e36fed4d7829c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627": "0x000000000000000000000000000000008d0144ab70adf9b1a6402cf14b3c61f98acf5bccabaf0030d537510166a21ee44d1676c26a1fb9acbdd56be00d4c44901856929b9d2a879caad6119ad0417e9949495ac7f6af5aeb5364188840d02f0e74e813e6d9cc0398d6994b66727658a4fb306cf4b9ce8d60ca73a35f036cd58afbc52ecea4d691484586967ae1ed45a1c4235627b276d86cb8de65eb9b261907a0134f1eeca33e423eb357ed4cc339e68d1d2c61f078a240b295eb8d19db50e5b27b39225ede1cf718c0872c441cb7ac8d54aec16460ec51be05e01406f39af4e8adc9d400e511cac7aebc10c31d42540f46c0c86652faff45a0e4a86f5749bf813d9d40aac848b8c672123d7ee2503a6d5302c1151878ea5c35d75c7d4f879fb48ea7a4199e2d3ac9ed79d686a157384d2fc6a8eba5ee9f02ca31a31bf5de2dd406adc9c55df94001f6efa28370b154544d72c76dd7083bfe6b601d39dca6288bb8adaa0673c914f3b0c40ed812fa4b5429c2b18a21865fc3da2283153ebd44a5da61f33753f6f20eee1d8e41fcbaa0dc67c0d0a4ad7841c483d4cb7813af9550c9d7c1b182613bf27a900e5211d9b64d6898ab313fb0a6faf344c680e6afda715f41179d993ab86f25e481a6259c97634380ec6fb1ab57be7d791fa9bb7e711b2736c6422e0b66932b54f3e95f614b4b2de852fc4a048379bc123ee21bdeb4c6a4d94ee131b0920ad219d6cc280b0a09651e25c43583448b07d9e3ff3a2c67c1674ebc968258e42ac4ac000204f6298774063dfccb3cf16ab95e3af6fa877724d2ec90697596897ea59069aefe5c223f58e293a27231ba1550c3767df641d03102ad153acf8b4bdb7db7f180fa9d544d65faf6bf2c43d534d180a04d58c2838ebe73f3c98e0c3699f224ef0ac156c65e23322e857c9fc42bcd84f6f4e2d1f7f892baef31f1da5731d22796cfc40e4fdd5dd4c6173852da2969c43006a3806502c5f6bc23e1f3e8d5507baff2b5e2f1774ee040d1b984526d7e5222ffbec6cbe8bdaa73f9190a9e3d7244a54fc99cf37a6574b215d61cfbd296a81d6ead301607072d2bbf9dd308c3606eb1b795a62bcf2f68851551f073cdbb09116a1e5b1500042b1376b440f967b0ff961df638fae8675ef2424315d83ff1d4199b1151f91ad9c0e89306512b02f846f7acf17f00da67081c3d2269ab0253aa2d2c40fd37ab6e7304b0daf0bd6068d0d689fb51f1c40f3a365c988f1b8bf6c4574656c803938a4e0250e25837f74fa6046f0ccf225123345e9fdb6c477d50a5c7be50ff581405ec6c151ed4ca2c25cf21a510e6bc7e6b603d8b10a42a8be5f7e755820b0c4241732614384e039536c8e43d3b414430566cbed2071a6b6848b4d170409de00af2da5ce2245166c9a5c32ae79fcf44876f7e91f2c936482460b397eea5923867efeb2635679ca776cdfdc62bcea000250de6897f5eba9ec46ed569cb3c532d193f04bccc3971b065df4239a18a1e5e527cdc89c6865c029c1088fb27b41c1a715b0bb611b94e1d625fa0bb8a1294187454623ad4601b91806226421ebcc2af8a4e60b4292b52e9fa8bc1c57131da50480048636a9fc435413c12d7c7524f6c12110ff15938dff2da4dd92cbc87696c721a6c6ed8531e6c0b882af0a42f2f23ef0a102b5d49cb5f5a24ede72d53ffce83174c08de8a66557f63521d871087a9290cf8032705cab1ece83bc4e5a230f13020f29100ef06c7724dc32404caf185c03adcfe64e92a3a4885e08cdafab2594d2de635bb7c13379f6b759e79aa78b8852d750afe7da16ec7f01139fef08849147b645c0ded9084b8186ef4aa2d83ee1c5ab326757267c41c05444e15c657438424f4642a032339376577e3ff7f6d55a53fb6519c5a20633e30bea2bd4d2eac3a0540ad8a6c92b5be3305a78ec0ec67cc600e791fb2769b9cae21cad79c40f7c92c04f231f52cd2a234dd3a72a7c920ea6e10a7f85abede1a9b4062428bc303ad7d5a43b9d3a39997151c4d745c1513b73ea440fcd50aec480eb4ddbe65fe692477a4b5a3630311d5cf8919e20be535ded925f210724ef5c78f8e3754a32ed43841d21f6f288702a2646b5cec6d0cb5f77d48638af67cf77d6dee823e2959ccb967be03f2946dd310eb0212bd2c44122eb48cf77c834699f6bffa88e2697e7fe04f545513938fda2f111c89660c78998fe45547148b9c2c0891f28ccadc27313a4516c4a4dfdd6c04572aa9c3fbbce888451c65cb1a1c96f611aa638e609cb6f609007cf8c189e43ad7cc1eaabd0aeb82ae7d62e5ca915f6bb87c4a0d85bb8c3772ee75ab2836d2ddd324049b86b224542d6cf8a12b601045ec14c454fea4e9cd470e2515bd2e4ff6a32fed6306b3fc37095cf875c65f987c19c2b2691d8545fe51463b64f13f694e789b1c89d219210b4aaef27fcaf8621ce8103f88e3951d054ea00b6ded2d4d0101146c5f76452f6900532c39cfb36b911e38776c782cfcef5940e488d3a17720b2cc51ddc6cc6c4afb23ed4fcde97698aa2cf374fa7fadb37db0820d7db40e2a9fe96c7ef2e810cc51a7da195bc995f329ffde72fae04e7b3e2c85e23060a9c8b4598f2927a796f8062aa3843dab76f9eadd8b2f36179c263e1a765697eb319802107fc3eb312b686bc335cf4456be1c46d6482bba3e1eb038dc7a8f82a2faa5ec9326f6970edcd577f8ed603104845ad07ce5c5d8f4a49d551233533732bfa8bcf7a95e0dfca71309e49a1fdd70d43fd5c405505a6826ef725ae96556bd15eed67a54fe5f9191835994d94c18a764ea4280bd03faaba617740cb8ca7ceac36a246a8295a56068d2b532fa2c61affbb34bc5a80777d91f1805702ffebbe8d46bc7b2d33457e61ee616e16c56d726244a6ee549a2572345987348ff655461db0e896365cea6351beafb80b40f19a3c453fc27e6609f872e4238a42184be9cd7657a019c2624c045f4ef80df884576b0f2e1eece434410537a3708c74cb0df1d73c69a078a6dd56d80ea94e08a2f72cba07ce6c5b471fcca8976c89604d1a2388771784ef80c5577fad1e75bb2362d5d578a94e8dfb3d982e938b8774ed1e7c90fd0dbe40fe7c6a8d810484ec59624b59374a38a8bbf9d91ee1b54bcf53ff5d97b41b38a3a5ccda86b3a3b1d7090a20747e2bdfb2cc46a38d514eaa00abd5e6449dd46d8882c6024f26cb5247d26becbfbb4f57314d342b96a653a620493bb740849dc2f946560976cc5f8fc004b038cd61859f5be0b2ae3643f545e8064f8898a29d4811e09b207cf3302e5cefef16615f8580fcd8fa63a624e90549dacdddd5bba278515f623f95197c97a6a7793e1e350c7492a9436e4a90db0b7458638e3862d435924db213a27b64b5029bb2f06f68bd337b1c3de43fe44e816b1ea4928a0d642ee4b4fa99aecfb717bcd47086edb11316254c2e5844d2950bf01d23906f2dd19d8cd71dcbd3033af5fa1dd042dc4dc1f3f5f86c2e9ad5b50c63f86e505700906b9303be612c11427a137eee64475e048ca585562f79c50e8ce09ecba19cbfda0c26fd052cc50a5365b22ced871d32fb6a2eb1853d2bb7eaa672cf29483bc35d2991a17f143213bba4fdf81050113c483cd205f689032368aae19fba03bdb71cf735646aba2d56fa5b4b83aad3d96804d70e9559ed8071efc036538dd0a7335685f0b7f62f6745658ff16bc2d61a8830e70dad3e1749355129129bd5eb2ac144f5d28695aa11f2f14153863409d08656f7e34c2963dc1128866bf5337468c1c81b265c4d9f352ad6b0e50b7fe77c4a660fa9ce31e45154abec1f258092973881a9591a5f751a5ca2b305c6bac9f4500c0e56ba02dd8581d42e37b2268e7e97d6345f7611dba1f4f58baa27382b87cf536ebdaa23c3b811ffc0b298393d72240ea0a06586ea1227e8c84f786c7fa05879e1ff28422017370b65d8d7707042e22fbf2213c687b330cafa3a792598536cb5fef7aef40cdf07c1aa9d3c51f17264aea16d04dd1b899fd311853b2bb2944487ac2c43f1e3040482ab01782078bd1515a3027895439f31237792568ad0eded4af3d31cbf30d951756a88434d91c219575e30f91afe0ef870901772375a33f006fa82b7c743b49176804069db501a5d23ad862cb312892bdb603740707c1948b797d4d30dcd76d1bc83bf4af534e16af8aefbc56dcf58d3488c77601bb1abdebafc2fee50534af7facd6b218c883c8ecc7a71a6b22a74261f1c2394399818ad3f3939ef31e463e23687a846146ca3cae0d51993c0e186d6026b2134ca05e213562c0141a85b4ef5ce85a54ca5474be7ec4f0e149232199a19f1f962331e1ebd5be36cbb77d8b0c3e4c6a12b41192cb3355642a4de4fa55ae61387c23673f0e8c8637dd864eb0c443983a3e49a6aef7637adde845d561274ddf1d66ce267c81b3b0bac979ff79106f2c0f99b106126a14a19ed92af1bd9055ca4c39fd9ed5ed2305d18f6730ac5470", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eee577071e47d1ba7b8a40f17f9fc62194fe1b12c10e8a2bfb5efc7057b119f4ca3b05ba96eb7da6b": "0x0000000000000000000000000000000004b08c0a54f1f153adae9df1b746cab08c40e3b949cf2458f80ac43ff256f2c17a", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eee9be5f0b44a2889287e6f010e50f642775dab59f39ee4de313fe6325181ca603824399cf4d42c08": "0x0000000000000000000000000000000004787f2dc3f07598f255932ee1fd3cdfea934389c61a31473a87d270655f70811d", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eeec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x000000000000000000000000000000001480c546b7e44391d7f7832d8cd5456f7ca1a76a73e73807544a4184bb59ce60481a2b2effb22453209445e66e170f7beeffb3b66c900fa8fd49cbe9efe9eb49423e4f57a212fd4403b083d956909c66b8e492e24c48095c3681a5a282088037445009e192ec169788c9c1f0202fe7c2bc79405ff8b6e1d1ac78fd6152006e606dd091cf86d04141b1c17c70826c08d074cae1b00d6f82de1b8a5406ea10ce723b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eeec1d763f95c70cb16eaf9666bd95a04bc6ed619c30a4809a43fd7265e414284c11b27b8c666fd23": "0x000000000000000000000000000000000894ee7175041f3293479d3abab6dd9fd5e5d463f539bf6eb18a2bfc85e6c5bc54c63d0c9d2b2f1b51dee3c65bb2714871c2913cf646efe3c775d5cfefd4e1bd89", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef035a0d786dbcf44868cd54faea1a0e45836635b2bf658733436ec69c5567d651be592392cbb69dc": "0x000000000000000000000000000000000c60857d3958e4e8809b36403726468f6b336e952d7cdee4a16c32126719dac4113472a370eb332c43576f14f315b219aac6f86795a580d50cf5454b4c293b811f300685aa838106c3737c9e6c6086481f3daedc1b1650b84cba9405389ade856c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef04fc71c9051dc296467fd4e7038b925c2422357380d8cc0c5f17d272f639af8fcfd1f1156de7040": "0x0000000000000000000000000000000008bed497470a04ca4c13caccd69c7827e3ddc64473fd2d7c5d496c71061f452b05f6be65cc16c65708bb6a0e4b9958ffe23d1c56ee5683670a69dbbbb70c10d507", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef1352327dc3be8a0948223bb2e7bcc8a55be248add34b625c1c0826c58fe037fa5c8e4591440dc59": "0x0000000000000000000000000000000004587fc2461b55e47619ef522b4bd986f71f7adfd207166e6dd2ba381117a2dd08", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef1697a69799d08e44211b834beac4f35ff92e0dcbb0167f6ae7a0c43b186727d581d3f69f10fea34": "0x0000000000000000000000000000000008e68e209129894d176228151c41e67d96f9d8ed4da38338fab5c964f2cd2c61562860f5267cc37b8ac5cce7fc5e1e00aeff5c951ca71a7075e75e5be1136e8e3c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef1fd5669b551e9dca43b2797bd4dd454d7fb0870a2a4edd62b39eea0801f6baaf09b05c8634b5a25": "0x000000000000000000000000000000000c384e257ac2372c996a4180f6d9a9a0e16631cc76929c600468583e8d798c17603e586d68dad3baa2426853204a502f7476c280a7cc3bcc4f25bc4bfa3e1216015c3e489388961303bbe308673f7faba33bae973af37d6ca444e1772a750c9775", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef2148a94f5867abb148a35cad2b2fe9cf6ffe0baf5f4f2f4ef894263baefead0e797a1e3e6d0a07f": "0x00000000000000000000000000000000042aa7daf7650583460d76859d7f4fea90eaf792ad9cc03e9bcc2667f165f00b36", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef24d4d1adb36534d96f7daa1a00790f8b168d3db7f0175e5f8dfd3430dc7edb4c5b807bce2b9d93a": "0x000000000000000000000000000000000493bd14a518853f72f3deb5357ee12fdd6e77151580b082bd468bca1358250d2e", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef25ef82af77881fe240cc50e90684f175ebef583b904fbc0b9aef4b38aaafd53e6436ad3e70ba366": "0x0000000000000000000000000000000004d2c2f040d9b3546eee26f30efecb97e72fdaddea5d4999845b37742841e95f57", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef2852cbaf60c5e38269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39": "0x000000000000000000000000000000000c269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b3944a8bb3fcbbd5b54617b782667c7f8c5a89ca53c1f878cdc9dc1766f447ea30f922988e0c062661a2af3df12782ee38f6df030390d1874d113bb8a53c165f147", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef2b06e2ea680db3c12d9c0035dd422388e6d346f61df3d9f3667f8ab761c8c57120dd61917976e10": "0x0000000000000000000000000000000008b466b09ad7c824d88e8548f5587ba158415f7514a0d0dd7c18144f6503507f473c1cdb7f10555d9e080e83ac20acbb4880b32d3d30319f055e37652c7ef3d36f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef32bbb6fec42f4b03e89cc7fecc4ad46cd7ba606522a8d1679863da498718cf9acdafbde8cfe4b78": "0x00000000000000000000000000000000049e7fb05bdd2dc88013e77f26a37dc19e1c1717fde8a27bfd1f2fa8231ddf8538", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef3e3959f84b063bcd6c29a7c39cee45b0e045a94081bc188ef73be2be086d66aefd850fc7eeacc45": "0x00000000000000000000000000000000083ee307326a809fbca23841d62753a3aaa5d3ef29e45a4f810ea1011c178f302d4e1f1d2881471357ea697093e5e68d46712d2b0e5b650945c4ecb571ea43757b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef3f9a9fea1c2bb71688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045": "0x0000000000000000000000000000000008688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045cc2db6639c1895e08c384f618c9f215e32e0fd23f2ca0ff3b013d1c658287a75", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef5695ae6155ce7ab243612f0fc6c935d9ee0cbe21c453a83f58a9427054ccdc74966890ca57ca719": "0x0000000000000000000000000000000004eef86cb3454d5d2d17aceed4598209af5d3ec6a09cacc00bc88d86bba7f34645", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef59d68b847bcb2beacab23f327e732756f5d76a43cd32830d5d8a9a489cd9c5c6a8554a3374da056": "0x00000000000000000000000000000000042c527cb7d17e0fe6df0e0da303a71f3eb46ea5bd309858389666ce6dad8efe15", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef71158c0f51bb8fd5247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61": "0x00000000000000000000000000000000085247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61deb5320179cd1dab5b17c203384b7ec2fa9e73577a82954f9c526ad535552422", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef71b1777c4c6a13546b4eca928ede3e8075d86e25581d46adf3eff915646eab110d13e2fbd947b5e": "0x0000000000000000000000000000000004b4adbb4e711987eb53c39b12dfd79435736f1317a869db5f50d5a913e4045550", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef891e0d61d95d2f9ecc96f0e735d4677e64728f5300b27c97c3413ba01e7a60dd29cb89123990a66": "0x0000000000000000000000000000000004c0020cde3bd8293eb5d5b61b072a9f6b19cdce1624a8ee4a27ca8c57e3ffa628", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef8ef4c38a66ac4223cf3f47f611c9dd952bd9007a85b0d84383f91e2f25edd0f13d6be20b5805110": "0x0000000000000000000000000000000004be0bc39e129f4ecfac3d20c50d78472dca69f693150064093df5edb3a0caf14b", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37ef94e92ce97ad9912aeffde5a4dc7117e4cdde2d3fb3d2afc7b2f710d5d66c55c5d1d7c5873598706": "0x00000000000000000000000000000000044415d4ced8c9de7ba415022d5b356f25eeb4d9dcd522732b2c87520e29e66044", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efa4f3e525e10f673faeffbbb88ab949b51abcacd45d7f9addf608a6e6ddc3d4b39147454e1a23a16": "0x00000000000000000000000000000000045f58951d682a66090492f70ce968af8b8d39a6308aebb3cabeafd44bb0213d91", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efb1e196ecaf7c6ef54ec6a7bfcee3ac00ab63b98e084f1a1c4d0e82ff63c31387aee91c9a721a81e": "0x0000000000000000000000000000000004f063c0ba3d0dfdd209dc5b98dee86531ad264283fce758952e49f8e6b7f85c7c", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efb5bc1ff496d8054008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a": "0x00000000000000000000000000000000201560de907974c342ad34bd99ba8b530cbf89b39a10be019f9abfed3649470718a00505eb2a4607f27837f57232f0c456602e39540582685b4f58cde293f1a116bb4e1d9efbe50d88f02dc608509ba4ef589646abb8dde69c9398738becc8cd48d34e07fff5d2c51bf316d91599d98e2e1ecc8bab38f57caa40a4206967dc8ac013ea937fa9da7a04ab5ae026b321323ffbc3f6ffd24898500ef3eaa6b2353613deb536d9d2138242abbfb7d0f1b7b2905d8316566edd28c2d029996a89e51e09b53bdc896b61a0c3facca04307105b99e44841190d41b655c127dce9447ce2d4e848eff972706bdacaf38bc657028f303d44bacde7b359b8595fe7a4268e7418", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efc6a73dec7fa79b18c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c49277": "0x00000000000000000000000000000000d84248d8caebe59dd27fb0606a3640daab22456c80bf8449bc0f9ca721ad2e2074c6150d4b20644caff90e355c0740cf211f04ec624a65acac57608e7390488f0a2cb40effcc1bd1e91c49205a599b87e3a49dfae2ce9644f3a431e974c721c54fb22f3abb5bafd42556aaae871a79acac48e9b874703cedb7f8f5ce219860ae08dec5377d25559444879fa2dbfc018dc9bc4b574c73e7cc4ff17301e6f0404b0ca6359df267482f0eb4004f12f3189cc44d1e70441ecfcbc1a2d5c6c32066003b7291c36a6b23990b023acb5bddedf227b9688372d4ae99b442b031cadf13f66ee26714e05311dfb5e182d27b7f0e2c399c96ccdd81c25cf47e9c61315274631fd6d65677fb307c3ac6c6c0405a1ecd9a47d0ade13ebd9fd340038fc78d9d883672b86a19da9f10eab2fffdb74143afea62356c6896c265dd18207867f25751109a9868ff02ab61c9603e98eaf9560a864870596f58a7144203636bef6d04e269927f1c23cdd2161cb6bf0da7abb4dd94ce6a98ff07e9fbdedfe96acd3d7dbf5abee52eddafc82ea6226864dcf0583e034f6510d2b390ed60129b6855fc020c06868615ece4f03d149458a8a54f26f7b3992f687e066d7c50e6713f72dcd6285adc19a1fb8d9519f281e155457a5ae5e30ee6cbe81b70db34a18c3bd72c67244b0600cf06f1c8e912c9d968f1de9fe6ed32d033b8e87bfac698602c25604e2b4ea6e5748915493258986746cb3e58f9e76c69bd65bab4fc620dc649c102baf716280774e8e4e6118ffded6250a1b6b1a50285b5a61cf184e19a2bc8e8de8808583ea2629ce3574dc7dda1f20721f7d7a1109dea19ee434885d768c5c9f671271d10002bfd652b0ab50a36adb9bc74163a4385c6b4ad8d3cbef794c07716ee0d6cb04789c005102f21fd271c09568a78047f581710323b5f91b7c2d5743011e1286ec238210f082cca5552aa2ce9a0d1c4be9c7bf44c04f4524ded21f8cbcc611dccc10f47daf388814d58209cad72e4c07dd9131ffb7b2b909d39746577a971784a18d3235c574d9f25aa3371f0190be83bdc423f5b77fc310390e753b229a952644f5b938a2bca8d0b0d5b0f08bfa3faa67acf54f9d45449777022fc23cdbc0fd8c68f5ee90ef5d4f3a2b0d3e827b6b52d6d42c66f0789546e7672128891df61227d3663b23d3565e9f07343f2218b47f60b3221f8bc32692ac60a22c7fb936e021ac11f4e66c8e210deb3f90609d0be4335e8c434912a92fbb1f67d3800452f260707c021782450fc2707ad65e0ffebf1f9e4025b69b8e192378e4835b05f74ba5a53f10121888c3b765d7a0e4ad64209bb08abed45cf9b6f72eafb3af9782a1a7df77359ce352ba50059ec6e2635d7964a50cae9012e4a737f5e82c353aa0d2c13d8c2c4b4445943ffce2d55a39cd4c982e5bd4181d30f712ccfd8347ca45d74e6950dc3144fc86b2f190216b04dd5f75c5ee52d7d3d0a949bb697d48430072c35a5568d679cc0a70e5b714a16a87450270f8ed184d35e961629aa7c364f726e32e6b0a35b369455c50fcaf7153945fd6d92b850a593ea33b5c3b51d7e5a2acc9732afe3d57624b8bdd1afdaca3f940d0010ec54c6eeef52b15ee1da15b06924c295ae61b1b902e08f1b4939f83aefca9d3cf3c6048f1bee7ca71dc5c20a2e58599575b1d7994d5f588624fa628018dc6357f6a90f488a2d880525e582a914565e801907aa5ceae0511572155aaaed09c8ecc03b7dca4790609ffe26bdba0ccab8f3ac8a49d03d47e037a2f63bcb5f38a180115c70db29ee4f379e2e04c3354e346e6bb879c076c4b6290aaeec0a06ebc5cb198245f31343ac1160e16e942b5e4a7f6fd9a8525d277f96f3e758e51fb673c6c28a7203b1a57f6e90c9f81349e81628fe7cf9e8c5e313f1d418b48778051a756de0f652496423cfb3f1be28363c982ec4375d3b3e9c950f540316fe84dc53191424fd073613cf4dea51cd156eb00533dede137ae3424e18ed36871d41e440bdf62952275f43c899e1837e31612482fd4f47789ed517ae4bf2672eba2895d1b6a85e5d963e82cc77c48e57f17614a4ee7a1c85e78b96211b9af1d020030203a9d13c0eac03f4106dbe42d683140ed01c71965026d33ac38506cc0590b2ceceaf2a3cd648e16e0a1d4c105426719c2df8fb28c6749d31d1716854ef3548aff85aafef3175c5e49030715c00fc2506b7a79b3d933c72bb9ae21b97fcb67d5dc1811af6d5d9c412545e6ce7eb9a0362832dca982c4883b26bc9eb5f5af530535e7d216400578738ef04ef0871de73a26c112ec96a277c48e91f46d5385fbdfee248c6ee7c3a66a9f8e640b31922a840d9bfa0963116a9e97d84f9888882bdcb6faa12332997b7f5b83c7c75532216b6d4569e33bc6763785b94b98ec57d07573650e35e682492dd515e0a064d8958", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efc7f2ed947ce60905842026fdfe358c9320e35012deeedc83c1e19d2b677eba10a1fad0d93c82b66": "0x00000000000000000000000000000000085c0db244fc6960005482b5e6c2896bf2064efd1e5be17e851dc8139f839cf062d237627616a57f2897c778f501c919d17ea969251d6b46cae60ba3f01dc0c72f", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efdb56e406bbd33003c1db08dfc6786bee3b0e1b4aaf51e80b6f2ec9badbe3da87d30ad7605a2bd16": "0x0000000000000000000000000000000008e34c880765bf4cdda6ab2045979a9039544bbae925cfba4d6421286296cd9bdcbacafb0ea22a692dea279a648b8cb44649ca71629f9fce6d69e03a4869cd9383", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efdbb17eb6b8c97966c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc128577898676": "0x000000000000000000000000000000001c38aa672a41872f698aa995f14f0bd9e54cfa4efd97350e742d68a0c44da377d9e1cbdb5c7c39209793cf71d71ccd0a5eec8ee530069837073032da3ec4a5a714ae3aba9a0f0d03d9fab3ad97a367fe66aba07ac0f7fc58d8dc18eed82f8c62f0a6f39c26ca691bd958706b03619b5579a313404e93089bafe5760b2a9db4b5518a989898ac32a8333eea5bebe65671f63fbae7c43756c21f8507be73a53941d1d6ea41749ba9fa1ea5fb094593de0726ce6c1ae997e000b3bbd66ef09298f92d5611f54264f980f8d850f4fd87ab8eb7e6c86b99b396f50d1aed3c5cafcdfd88", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efe0e61bb6b0e225d68170716ab7c6735dd0a1012045d9ea33891b5f6596cf97eb217d0962d86a518": "0x0000000000000000000000000000000008ccbb21d7b5bf0b08630681c37ebda5b98b5454c8916463a9c2b50262466deb76d44824ac8d1edecca67639ca74d208bd2044a10e67c9677e288080191e3fec13", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efeb09bd923dd400cca437639da37528d8edc0bb6b31966fdc0263218f4bd60c6f2cc37e963090371": "0x0000000000000000000000000000000004dc64ebe91ae1dd904651525eb5fd91eb0abf458cb0f5986158803e0075604153", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37efec4b60935b1627f3ecdb909643a31da23e3dec041ef8920632ec16fc5157297084eda7515badf68": "0x00000000000000000000000000000000043481012d5c43235dd891fea6f46c4745b4c6f9ae37e756f7da67f6af35831a23", + "0x2aeddc77fe58c98d50bd37f1b90840f96ee5a0b09e7e9a96219dd66f0f74c37eff27f362e41c7ee9487d7703ee644d9a9b59ad29aa7f27405851496306f69678965f1d18d1478740": "0x0000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471400216b615048534c12bf9efdc9e4e25b4dd72c560029152b6546ba2fb62eca400d7edee7e5f36b5a": "0x040400000002000000000000000000000000000000000a447265616d62697a7a00000016636172697361676c61647940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714002e08e91d4d456f22f6f9f7bff5f160c25d09f3dda01266aa372084f68e73a49a6f75ffc0aad46a": "0x00000000000000000000000000000000001053756e7368696e654175746f732d5200001f4073756e7368696e656175746f736e6f6465733a6d61747269782e6f72671c73756e7368696e656175746f73696e666f40676d61696c2e636f6d0000114053756e7368696e655f4175746f735f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714002f96199afbb10962dc0af0a0af60196831c33ef674915a18dcb54ed293ac3733b128d0faa0a66c": "0x00000000000000000000000000000000000a72756274736f7631370000001472756274736f76313740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140044864097418a79480e2e9b103634bf32ba2c955634796a44cd1c6924e87b2596dc252a28383959": "0x0000000000000000000000000000000000096e616b757279736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714004b6e7aeec73523a6d28a83827355f149db71b1ffffafab9ecce641629c6aea5dfbbb9f4917b346": "0x00000000000000000000000000000000000862696e616e636500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714007dd9a9e7c493d87e8b716984392ac7a4282ae6ac5b35317dd2cf838cd9d388bad322bc11d3ed31": "0x0000000000000000000000000000000000076b7573616d610c72616d7a7920626164657200001672616d7a7973616d69636f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140085d1df7366a986ae8f7726520ba56f9153c9e7820015d462a71c6ea0035ce0fef5dfae0a98b228": "0x00000000000000000000000000000000000454656b010101010000094054656b69697575000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140093ec78bb21bfb2680407d00db6705819710e2f6dad5a89cad6a28b24c184126fd8d05476bd6202": "0x0000000000000000000000000000000000097368796f6f6e373100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471400ba2794d92fc826e4269547e0e9a8c162de9215bd45921be44dfb58ec95d2f627990d5189001440": "0x0400000000020000000000000000000000000000000010436f696e20636f6c6c6563746f72730000001a636f6c6c6563746f726274636574684070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471400cf4acd8af41f16fcdf10bdd1d597869ff3089a69395c153847bbe208b6b42c71edad958fa7442e": "0x00000000000000000000000000000000000541413248001e68747470733a2f2f7777772e7065746573706967656f6e732e636f6d2f000000000e405065746573506967656f6e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471400e0417f161433ac2658c2083dcab9b118b5e828fb81344c4245deb8eed43fa890c8c0ae9cae526d": "0x08000000000201000000020000000000000000000000000000000004576569095765692054616e671968747470733a2f2f746861742e776f726c642f7e7765692f10407765693a746861742e776f726c640f77656940746861742e776f726c64000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471400e44be06404dd23f621dca649d16a5b33c9955e6a09a5cf3a881b4185a1930a02c7fc3245ac3333": "0x040100000001002ca07d51000000000000000000000000000000000000000000000000000000085069636173736f00000018696e666f40636f6d706f7361626c652e66696e616e636500000e40436f6d706f7361626c654669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714014380e30ffcb2a672d2666b9ecf591f655d98e1800a37d63f454fc915cca7c6412cf55d98f43d67": "0x00000000000000000000000000000000000b476176696e20576f6f640101011c467265656b7962696c6c696f6e6169726540676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140148d7da0c4eece04cef024c8124fea94800b3d508aad0c474045b69144cfb3c24012bb915fedc10": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140167335afc9508e06aa2d675d46b5eeb0d922f4188b525daacb0091f6f31ce7d9409d45614eda803": "0x0404000000020000000000000000000000000000000020f09fa6854561676c65f09fa685207c2044757463682056616c696461746f72001868747470733a2f2f6561676c652d6e6f64652e636f6d2f0017636f6e74616374406561676c652d6e6f64652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714018d717cb9219f862cb783d5c0ddcccd2608c83d43ee6fc19320408c24764c2f8ac164b27beaee37": "0x04000000000200000000000000000000000000000000056b6174611041647269616e20436174616e67697500124061647269616e3a7061726974792e696f1a61647269616e2e636174616e67697540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714019d8773aba33ec5c48cbd210165097e4955ba0b35553db067e959752d454331835be646b470d15b": "0x000000000000000000000000000000000004426f4100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401b8e16c4ef5704b081bfb25dd99aed0b3d899820c722788535f82eb14cac2ed0adc9daa5a4fd72f": "0x00000000000000000000000000000000000678524d524b000000000000074078524d524b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401bcc09d733aeb61505e685f12b11fff499400211f38ea5a8cd9f1e72e9883b58fddcb66c563e84c": "0x0000000000000000000000000000000000055775766e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401c62b08e0f1d3292eb9ad501926b86b6c074a5a48bc16503dfc910b13e1ce2a8bc4440cca43ab2f": "0x00000000000000000000000000000000000e4365646f75782057616c6c65740e4f5549534c5920434544524943000013632e6f7569736c7940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401d4c9b3a23a716c824388cb8ad264b43a93320076e3f6690d707c3d1d53dd022a645c0127a78267": "0x0000000000000000000000000000000000095865726f6e696d6f0c4a65726f6d652048657272157777772e6a65726f6d65686572722e7370616365001867616e77656176696e6740666173746d61696c2e636f6d00000c4047616e57656176696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401dba54cb1c92c2856aa4370ee3d21b98ec19f0cbf2106a036215937a15bbe517b24ae5fef4d3870": "0x040400000002000000000000000000000000000000000a4441524b4c4947485400000016616c657373696f646f633740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401e3012609b6e0fe77b377299bb54afbbab70894a10e4ba1370f6a60914c8ed37f9b2484da37a335": "0x00000000000000000000000000000000000a4e4654204775696c6400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471401e66931ebe7cc802a82fb6c3dd0269f6977b022fc3abfa2f1ed9783de2d7f26672b7eebf4fa783e": "0x0000000000000000000000000000000000057072657300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140205d71cb9b4787812eeb34296344896ba0be07383211f262b76cffae3d00aa91d0c3d10e7abd37b": "0x00000000000000000000000000000000000769676f72656b0000001569676f7279616e62756c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140214f0b5b1672e56729f8acbb64cb60b5edb62beadc9ac05430ede0086e29800ee32d106befc7825": "0x0400000000020000000000000000000000000000000008416c436861696e0000001a6b65697468616c616d6272756b6f7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714022078fbf54f7d762fa1b6d109d1876820d529c1a53f5e59ca5a05f01d8833439428e811aada3923": "0x000000000000000000000000000000000000000000000000114053717561644c65616465724d61726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140223d09f1c0c1ef00ce0bbe155c5f116187af43bae0bd493872f436a139e23d9b26289d0721a310e": "0x04010000000200000000000000000000000000000000094c6974656e74727900000012696e666f406c6974656e7472792e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140224acf1d46b915ca048e9318fe2e6a8b6f9174800c44caad3e44d22f92453d1de685afb39089e2d": "0x00000000000000000000000000000000000b54484520425552524f570b54484520425552524f5700000000000e404348414f535241424249545f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140224be9facd8c216c2ce97485afd4c6f5cc11da558f0b28b62a277fdb50d7bd0cf3d88dfed968217": "0x0000000000000000000000000000000000076175726f72610000000000000d40417065734e4175726f7261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471402273ab7613e5661d033ca16a330cf722e09b908a545818f8e2880a221d16d902923ada564b4b646": "0x040000000002000000000000000000000000000000000c416c4d6974726f7669636800000012616d40756e697175652e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714022895ddfaa9819ec423a2dd622f907c00dbf99e423c4e3c9e937684b6ac14fa49180637c6eed61b": "0x0000000000000000000000000000000000023d000000000000034071000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140233abfcd4caebc1fc8f0be99f1dc3c1bc20b122eb888761ffa281abc9783f910df8b57ffcf8b572": "0x0000000000000000000000000000000000095052494e434550530000000000000e405072696e63657073526d726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471402492b2d8deb67a91862b74508884386ca63e94959b33773bf0f1ba6e3aaba793e8975760ba19a21": "0x00000000000000000000000000000000000948454e43484d454e0000000000000d4068656e63686d656e5f3531000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714025081289a767e3f04b72fd6c91c2799dd0f0c74accd0e5d6dce0f665b5a175ba3fd80a122416078": "0x000000000000000000000000000000000009616c7068616261650000000000000d40616c706861626165313030000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714026bed6843025f8466357ad0e7451c02f6d53fa777f394c31cc2680c4a7cf448c48a91d78ecbc565": "0x00000000000000000000000000000000001150616e74686572732043756c7475726500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714026cd546f7bcbf83ecfa264fd1da282eeb7b06b8c7fd5634e9f5da8eb1163c79b789d943c310ed25": "0x040400000002000000000000000000000000000000000c53555045524455504f4e54001968747470733a2f2f74686f6d6173722d666f746f2e636f6d001774686f6d617340626966726f73742e66696e616e63650000104054686f6d6173525f537570447570000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714027f0a2e5771d1390ea95a5a9a64e338318cc9e38b07fb0dcf75e164f4b968d3b206296c2663e059": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471402a74f185bfd81d73ae9f951aef3bab402292d205c9ea5f850e5b80b563a9b5837ac40ad97c22469": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471402af845724d240cefea7e94482e6aae6ba684414c251845b33b1dbd8cfdc035959f4ff948089dc17": "0x0401000000060000000000000000000000000000000007636865657365156b6f6e7374616e74696e6f7320446176617269730000126279726f6e7333407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471402bc718576057bd5c0914fdaf5815ff54b30fe11a656cf17539b090c36d5f5650260b12a7b94a945": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f33390f62696e616e63655f6b736d5f3339000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714030bf2a06d3af7df887b2f85c74b58160bb1659de7f63e0dffb480a46f99afc1d1e4002a44aafa1a": "0x00000000000000000000000000000000000d4d6172696f506172736f726100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714031326492a87a9c14631954522a90e4361e6b9bb3876cf6213bac251f99d456ed4703b47f289b95e": "0x0400000000020000000000000000000000000000000008446f746361737400000019646f7473616d61706f646361737440676d61696c2e636f6d00000a40646f74636173745f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140318c1db47739db4d030ca0b2a60a30e7d1a0fec231f6f36c3b608036d25ff6b2b9ab9576d59c252": "0x040000000002000000000000000000000000000000000c5374616b652d517565656e00001840717565656e706572736f743a6d61747269782e6f726716717565656e706572736f74407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403195376b973a33e30b25a315eb8ea1ff57e39183ddb0a922cd08e2443e6fdf4cf28bbe34b103800": "0x000000000000000000000000000000000009736d6a756e696f720753616d65657201011473616d62757433363940676d61696c2e636f6d00000e404d61736b617261436869636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140323373f05a102e67e99b3bfa6f2df6433c885bb45dcdcaa0cb01dd07079d5e9b1f687714322672c": "0x00000000000000000000000000000000000c7374727967756e656e6b6f074d616b73796d000000000009404861636b733732000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140328eb74cc6d2a41402cc6cb8ec16b5648fbc7be76657e17291d855b4d2dfc98511586789bf6c01f": "0x04000000000200000000000000000000000000000000174b696e656d6174696b73204c61627320e29a97efb88f000000136b736d406b696e656d6174696b732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140351153466a702772a326eec0bd3f6db6e6a17ecc5ba726460ff351045fe63ccde53c971944aa84a": "0x0000000000000000000000000000000000056d75736801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714035c8158e47e1177ceb5a9283e6ff1b5ae17a18181220657597cb476fbc726e2ca302d1e7a9f6d2c": "0x0000000000000000000000000000000000124b7250726f642053747265657420417274000000156b617274656c726f636540676d61696c2e636f6d00000c404b617274656c526f6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714037dbcdc8f46729a2cba024614ea8ccd1ebf7a634f30b38d65c082be6aaa92551b9c3b4d1f15ae6e": "0x040000000002000000000000000000000000000000000b5370696379205461636f0000001a73706963797461636f70657070657240676d61696c2e636f6d0000114053706963795461636f506570706572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140398dfc6cfa0cad07e7699082933c3da2328188e77d3ed6f0d6044e5b0e1a3cef907339b823fca62": "0x0800000000020400000002000000000000000000000000000000000e4d697463682d576172696e657200001a406d697463682d776172696e65723a6d61747269782e6f72671d646f742e6d696e6572732e736369656e636540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714039ea54cb812a324847194325a12bc4f4faacb6aef973eda31658195c26b934318b960aa69050819": "0x00000000000000000000000000000000000a73796e636c75622d330a53796e636c75622d33000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403ac99c30a0f9cefc87323333f6c7ed668bddfc05f00d058646f87df33589d4b3f3b2d159ce3e831": "0x0000000000000000000000000000000000074169204172740943727970746f204a00001561692e6e66742e61727440676d61696c2e636f6d00000c4043727970746f5f4a5f44000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403ba33ceedadcce5605ab29b9b1110fc5aecc4d1604862282fd58887d45e7b47a875901780a3103d": "0x00000000000000000000000000000000000f53686964656e204e6574776f726b135374616b6520546563686e6f6c6f676965731e68747470733a2f2f73686964656e2e61737461722e6e6574776f726b2f00156465766f70734061737461722e6e6574776f726b00000f4053686964656e4e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403bdc0558aef9e267eba793f6c8b72db5ccbba0972846a41dec11d3e62da13d9c09a868863f50848": "0x04020000000200000000000000000000000000000000085765623320564315576562332056656e74757265204361706974616c1068747470733a2f2f776562332e76631440776562332e76633a6d61747269782e6f72670b686940776562332e766300000d4056656e7475726557656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403bfd6fd4ef57fa5a0ad3e520332a754892d7a16de9de871b9f20e982d62a498b5d9c7e5f93d433e": "0x040000000002000000000000000000000000000000000653696f33340000124073696f33343a6d61747269782e6f72670f696e666f4073696f33342e6f72670000084053696f333437000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403ce064f38ae56473816e99372dd086042bb6bbe15f082d70849a371070675e3819980b50fbbfa6a": "0x00000000000000000000000000000000000f614861796c65796672616374616c074861796c6579187777772e63686173696e676672616374616c732e617274001b4861796c6579617274776f726b73406f75746c6f6f6b2e636f6d00001040616861796c65796672616374616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403daf1ed6a71ceeb484a68f3a30ab11bfdedb06f43f5bb9aae28c3caf66a67fe408efee66e7df46d": "0x00000000000000000000000000000000001d446973634c6f736572202850656e736976652052686f6d626f696429002168747470733a2f2f6170702e737562736f6369616c2e6e6574776f726b2f3633000000000d40696c6c756d616e61743333000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403e65d4ca28086078c2625b0e10c7bf65f283c576878cf00f67478d3dbb6bf39ee62b3ca19ce893d": "0x04000000000200000000000000000000000000000000117061756c6f5f5f7a61676f20f0938582002068747470733a2f2f796f75747562652e636f6d2f5061756c6f5a61676f595417407061756c6f5f7a61676f3a6d61747269782e6f72671c7061756c6f6372657374616e697a61676f40676d61696c2e636f6d00000d407061756c6f5f5f7a61676f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403e9f523ac424d6258c88b6777d3a1d2f2dd03cfd6f3bc37634380b273fa9e3fe2cf0927a39a0411": "0x0000000000000000000000000000000000074b6f6f6b694300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403fc9979d20d8f4376e282d7a7eef593fe7a9a8c5d08a21f134e8858e1b1753bf347057c4db9b234": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471403fed7fe7c184ba490bd3d091b8837f2f41c38b6e3bebd28a31ee280f82d15e687f95d798ef41c17": "0x0400000000020000000000000000000000000000000008457a696f52656400000015657a696f2e726f6a617340676d61696c2e636f6d00000940457a696f526564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714042590a80582f1a138a93e60974816d78c774a853979d3327de0e119fe2606d11d8de3d13bbd0d17": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714044f0e81770d2fe4d42eb2efe47dd6c0d5587693d706b6ff988e1fb289c21afb1099c3eede2ea543": "0x00000000000000000000000000000000000e484f5420434150554343494e4f0000000000000d40484f544b50554343494e4f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140454cd0bd8fd07803ec587860fea3a47649fef7bdd6be7786fbcbffed789f454b52613b22358850f": "0x00000000000000000000000000000000000e42617261636b204b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714045dc4c6b832bb9cba718c7f73c24fc4bb006f6aee231c6764560a69f5a8c2d6bcebeaf59b886836": "0x04000000000200000000000000000000000000000000097468656775696c64000000197468656775696c64736f7572636540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714046409e5f145bc2af4f95e82d3eeecfde0058a399005262a9709101ddf3f2a564ab34040678ece15": "0x040000000002000000000000000000000000000000000b574542332d535041434500001740776562332d73706163653a6d61747269782e6f726714696e666f40776562332d73706163652e636f6d00000e40776562337370616365636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714047021104d1ffe0a329c95d5190b434b204b6ed49f23129aeea1cb38f70aefa1af621b4c01d48311": "0x000000000000000000000000000000000010427269736b426c61636b4d616d6261000e636861696e677572752e61707000127061787375726640676d61696c2e636f6d000011406c6f6e67626f61726466616d617261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471404bafd1de148721f84bebc905613c15b1464d94e00068be0a67edfb4b274b180fa00573e4a41656e": "0x00000000000000000000000000000000000478666c0878466c5f446d700000000000094078466c5f446d70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471404c7c5013bc5e632ecfe133cb8a7eb6248a79ec2838c5982a3996db0c69c8427dc1e4ca3fdb0732a": "0x000000000000000000000000000000000014f09f90b2204b7573616d6120447261676f6e73002068747470733a2f2f6c696e6b74722e65652f4b7573616d61647261676f6e7300186b7573616d61647261676f6e7340676d61696c2e636f6d00000f404b7573616d61447261676f6e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471404cc90b988a75711683e24f78a248b20b2c8805cae1d228c1140da7d15f2d92c91dee43da6df3642": "0x040100000002000000000000000000000000000000000e54656c6f436861696e5f4144561e4d617263656c6f2050c3a972657a20646520417263652047c3b36d657a1768747470733a2f2f6269742e6c792f334d6863375573001d6d617263656c6f40636164656e61626c6f636b636861696e2e636f6d000011404d617263656c6f506572657a446532000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714050595b2a27bff0328bc337a98b458dece2c080a545fe7eb38ab06f7a26b9dc576357443285b4c79": "0x00000000000000000000000000000000000a326e64736861646f770f457667656e792042616275726f760c73756273717569642e696f0014652e62616275726f7640676d61696c2e636f6d00000f40657667656e7962616275726f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140505df941b88d8a60a725e79b9b6933c684a19923c69eb95ed2bf60a37f418e276a4ecd9d80d8961": "0x00000000000000000000000000000000000a50796d2050726f6f6e0000000d6c656d40726d726b2e61707000000d40416c706841697264726f70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714050b93a25349a94f32694dc2fe7ff7637b26f93f51636ce8beaf128eb4bcab5297d13dbe555d2830": "0x000000000000000000000000000000000008414c207c2053490101010100000a40616c617a616b7279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714051fe135342851ed0ef762dfeb3c0cc556212597df740eb320ad5b10e526a93e1aa32df8dc3d8c44": "0x00000000000000000000000000000000000f43727970746f42726f436c61726b000000000000104043727970746f42726f436c61726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140524d45908638528248a8784f67eaab3daede6b3367277040f38ad93339171253c1698daccfb4f6d": "0x00000000000000000000000000000000000b4e4f42554c4c534849540b4e4f42554c4c53484954000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714053f986ef1b208a2629a4497433e01dc77b48378a2c9f90059f5a6386c4d0042fe1c9751cd29bf21": "0x00000000000000000000000000000000000847696e6f4172740547696e6f1d7777772e696e7374616772616d2e636f6d2f67696e6f6172745f372f001467696e6f617274303740676d61696c2e636f6d00000b4047696e6f6172745f37000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405536af493f9e4a9c29f38d97fc79f3c60343d96cf6cd3e334fdf03987c50a7fd788ffed2a5ec928": "0x00000000000000000000000000000000000a43727970746f4a616e10616c656a616e64726f20757269612000001f75726961616c766172657a616c656a616e64726f40676d61696c2e636f6d00001140416c656a616e643437383530323535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140556a86b11fa77913c7f40746d04d77628d886dfd469c9bf606232dedaa248f5c219d32da93f4054": "0x0405000000020000000000000000000000000000000014f09f8fb5efb88f20464c4f5745525354414b450c466c6f7765725374616b6500001b666c6f7765727374616b654070726f746f6e6d61696c2e636f6d00000f404265466c6f7765725374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140557741ad8ff629b30ada415c8cc022b6ae05febe4df84af44b09b542490887b11ab3df04714bf2c": "0x00000000000000000000000000000000000864697374616e6b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714055ca836acf0447774422321a842adfae9419ecd3983c4fa2da6e879ccc1db031e54c742bbb9bc03": "0x0800000000020400000002000000000000000000000000000000000b56414c49444154484f520000001576616c69646174686f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405600578c1e1169728b2f7bef7da67014627c1f7e36683afc5a9b1a9e071570065dbee9eac414b03": "0x00000000000000000000000000000000000a6b7573747261646572000000146b757374726164657240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140573bb60d22fa77e98bdd9395e86f4d48a442f70fe2513fd3fe0cdc7e95105ced193ba2666c8fb41": "0x04040000000100902f50090000000000000000000000000000000000000000000000000000001c536f7665726569676e204e617475726520496e6974696174697665001c68747470733a2f2f736f7665726569676e6e61747572652e636f6d00197061756c40736f7665726569676e6e61747572652e636f6d00001140736f7665726569676e6e6174757265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714057502993decae27be3d23293857895d14cd4b30e1823365792d89c77776b238e4d883e8d2261338": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140587e6d391ccaa424c44f3e63cd28ea42371fea311f977e701ca31749ec7d0262461bc41591d3607": "0x00000000000000000000000000000000000e44565f4d6f6f6e686f6c6465720444616e00000000000a4064616e6d636b3138000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714059bc9cf5ceb19d4b2801b3240cd70a56baa1aab6d2b26252bc804c254f8e2942d365e3207b46a6a": "0x040400000002000000000000000000000000000000000748554e5445520e48756e746572204569736c657200194068756e7465726569736c65723a6d61747269782e6f7267156b736d4068756e7465726569736c65722e636f6d00000f4068756e7465725f6569736c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405a60c9d4c41f598de9d02d7d5447ea749e3c33f38033ecbdec8f4ad6abb3f0a17d6023db1988b1a": "0x0000000000000000000000000000000000064a6f65205100000000000009404a6f6571753135000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405b079eb94353bd94adf51a47b72795366d52285e329229c836ea7bbfe139dbe8fa0700c4f86fc56": "0x040000000002000000000000000000000000000000000e536861776e2054616272697a690e536861776e2054616272697a6911736861776e74616272697a692e636f6d1f40736861776e74616272697a693a6d61747269782e7061726974792e696f17736861776e74616272697a6940676d61696c2e636f6d00000e40736861776e74616272697a69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405b5d46c57dc301d8c99cd908a45bb7973537ce461ff349904f6b3176ca9f594a2e83d720e09cf72": "0x000000000000000000000000000000000002520252000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405d31d1ec885004a5a6e6d7f1f5af2300c1b721cde7f08238ffef321bcb45cce819b00557fdedb00": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000000f507265737362757267204c616273001a68747470733a2f2f7072657373627572676c6162732e636f6d1a407072657373627572676c6162733a6d61747269782e6f72671d7072657373627572676c6162734070726f746f6e6d61696c2e636f6d00000f405072657373627572674c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405e3f970c23ff63cb85d101c656fa86dc284f34f7583b5f178d9e9b619df6031fe2c04b4c5f07e26": "0x040000000002000000000000000000000000000000000c414e47454c20535441534800001640646c697365656e6b6f3a6d61747269782e6f726714646c697365656e6b6f40676d61696c2e636f6d00000b4044796d797472696934000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405e501157aa27fcd22240cd28aac3cb675651ddee8045f1fdd5d532c2b149e3e68b0b8f606b6e075": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405e51ec513573d8d8eb71ee062ea6e33ef20d8ece22607a4ddce26104535141b562a84f31124256d": "0x040000000002000000000000000000000000000000000c4d41582d524557415244530000001364757a6972796e6140676d61696c2e636f6d00000f406972796e613235313432303332000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405eb675fee1282900e6bd67d5dfccc6180a5ad07870653d1a8a57ab09efcff251a49c234b649f423": "0x00000000000000000000000000000000000641694172740000001861692e6172742e3432302e363940676d61696c2e636f6d00000e4041495f4172745f3639343230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471405f8e083dda4d67b66e0b6ed9ffcce16a6e8a77fad73f6029f289139229a359380384929ba8d093a": "0x00000000000000000000000000000000000a524554524f57415645104461767964204b686f726973686b6f00001a64617669642e6b686f726973686b6f40676d61696c2e636f6d00000a40646176615f6b3230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714061c4dd514901839c0cca7d600db0542f7d46a623c53383cb24ee7ef9122c5b42a5f63551c054438": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140635da251fe445574e449bcf3a54b723c9897abf182e125d472242d1ef0676052fbacfb900b9a044": "0x0000000000000000000000000000000000165370756e6b42697420537570657220536861726573000000000000104074686567616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714063f98a01f914d5d7634ddf79f2e749774d401cf31cc4565da1627f6857e2bb5c29a219121512068": "0x0000000000000000000000000000000000066368696c6506456c656e610000146c656e6172696f343740676d61696c2e636f6d00000c406368696c6c655f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406464a684f7b7a0d1c6681030fd4860fcfc1dfad9ae55fc0181229b007b6365dc4c8f5fbe162554c": "0x040000000002000000000000000000000000000000000d45786f746963205374616b65001968747470733a2f2f65786f7469637374616b652e636f6d2f184065786f7469637374616b653a6d61747269782e6f726718636f6e746163744065786f7469637374616b652e636f6d00000d4045786f7469635374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140655181280220c8b6280b912d54001e1ac0bbc1023ba9a16974a6c23d22e817e97d418ea94d29642": "0x040000000002000000000000000000000000000000000946726f67f09f90b8001968747470733a2f2f66726f677374616b696e672e636f6d2f184066726f677374616b696e673a6d61747269782e6f726715696e666f4066726f677374616b696e672e636f6d00000d4046726f675374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406885e6b6b0cc106068c252ec614ba3bc04e729d590bf21ce3b82ebd4285b8319fc56536027d1460": "0x040000000002000000000000000000000000000000000d3036312e6f6666696369616c000000173036312e6f6666696369616c40676d61696c2e636f6d00000d403036314f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714068a83f6750959f2b4af44560bd1a1aedded0deca4f3a57548b4b70d63f69c7fd16b41f6599b7f75": "0x040000000002000000000000000000000000000000000f54656e7462616b657273f09f8db0001768747470733a2f2f74656e7462616b6572732e636f6d0017636f6e746163744074656e7462616b6572732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406962b7186669a025e5f430170298c557cedc08e8f2b688e59bc2a7e081a6467eb7a0b7b5ba4c90e": "0x000000000000000000000000000000000004766c6405566c6164010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406982ce1b07dde21ce8ce1358c0f5ab2618e38a9c853948c51bcf3ad550f7d65af1cd03f959f2843": "0x00000000000000000000000000000000000b6a68656c657a6e6f6666114d616b73696d205a68656c657a6e6f760000176d2e6a68656c657a6e6f666640676d61696c2e636f6d00000c406a68656c657a6e6f6666000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714069b111e5a0fe7089a8260623bc5831d8c2b343584a77007782cf231f8063e2caa2abb4ff686c466": "0x0000000000000000000000000000000000195361696e742773204469676974616c2056656e747572657309437361696e743032000014637361696e746e303240676d61696c2e636f6d00000a40637361696e743032000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406a51bab8ef99a0b50d987e17e9e6d29755219eaaf922c92870657adbba3a3d0208e30b0e9651c38": "0x00000000000000000000000000000000000f412047686f756c20456469746f720000001c6167686f756c656469746f724070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406ae29fcb31f2504fcea4f4585d2d271139edb4c75a70445cf84063d0b7a05955af4620daf56e238": "0x04010000000200000000000000000000000000000000075855414e5f32000013407875616e39333a6d61747269782e6f72671b79616e676a696e677875616e6d61696c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406bc1957793c67e8d2f05ac62ec209254a2796a6e45f599195b90fb78de0c915e2b49d557332d56f": "0x00000000000000000000000000000000000d4e696b73696b66696b73696b124e696b6974612047656c79756e656e6b6f217777772e696e7374616772616d2e636f6d2f73696d62616c696f6e735f6e6674001667656c79756e656e6b6f6140676d61696c2e636f6d00000c4067656c79756e656e6b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471406fef9da176fe6b5504f8379d55a37d9b91937eea092e2d74d85bd1894cab557bd791b92f47dd566": "0x00000000000000000000000000000000000e4c554343494f5f4b5553414d4100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140703fa0ba498f4c1d6aa353e69dd58d0298d9d5cc2000b0b279f90e3d6a8e80de5932e3f1e300b06": "0x040000000002000000000000000000000000000000000c456c204c65c3b161646f72000000166d6676617267617339363640676d61696c2e636f6d00000c40656c6c656e61646f725f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714071aba1c4fbe2c7afea2b3bd4635b227539d7b4894ea4b09eccc01acd424d4e811b2dbff5670f726": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407215386cd0fce6716c95a9cdec3df8ff80ca21d4c9f8fec3f4c7c9fb940e0ac2d1f8bf486acd35c": "0x0401000000020000000000000000000000000000000008677265656b647810496f616e6e697320536f75726469731e2068747470733a2f2f7777772e616d706c696679676c6f62616c2e696f0119696f616e6e697340616d706c696679676c6f62616c2e696f00000940677265656b6478000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140737c7a9c60b7040b26699df67dfb10499cad602d1eb7680109097abc955427dac056d4ff0915757": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140760d903221d52a2d6260d36b4f57d17c0d1214f67f51ad72b44ca6a5b28b267a057df44a4ffc75b": "0x00000000000000000000000000000000000a7468655f766f6964790000000000000b407468655f766f696479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407628049f99bf7d7a46c0a25bedc15be8fc45d5d9bf710247c4cd6b7478ac3d71f71e67937522e15": "0x0401000000020000000000000000000000000000000009417661204c6f636b001468747470733a2f2f6176616c6f636b2e636f6d00146176616c6f636b406176616c6f636b2e636f6d00000d40617661756e6c6f636b6564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714076a68a64b11f79daeeaeddfdd71854dd03402c966ccc5daa5c3afa196f2591dfc22ccf263f77503": "0x00000000000000000000000000000000001154686520496e7641726368204d696e74001968747470733a2f2f696e76617263682e6e6574776f726b2f000000001040496e76417263684e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407715dc9ad8895a8e898988dda904df740a306d0c786ed5668d1344720b102be91a3956bd480f35b": "0x00000000000000000000000000000000000a4368696e674c696e6b0101010100000b406368696e676c696e6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140798b555f15705031ed39a4aa544b98ebd1243abe6264730ea0921edd5e279e2c7c5f136bfda7e4d": "0x0000000000000000000000000000000000096c65696265727479000000167261792e6368693731373140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407ad6e0f21f25f78887ddc26a5efdc1bbd8bdf8e1051dc07279de6abf830bad4998e44d848812458": "0x00000000000000000000000000000000000b4b7573616d612043585500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407adcfcd16f835d4b2bac0ce6ae2d74d54b020ec4f2ced833d9d9367ce9b44fd03c47b2955449e03": "0x0000000000000000000000000000000000076d61747379730f416e64726577204b75646c657373127777772e6d61747379732e64657369676e0015616e64726577406d61747379732e64657369676e00000e406d617473797364657369676e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407c7d38f8167b3b8ea868dc748fec06ebc5409c01d3a3445b49ff65f9df353a5f6a45582eb001522": "0x000000000000000000000000000000000006646574306e0000000000000e40416c656b7365693032303231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471407e3699c0690de378835373096d1ba3d43eab5289f28507faf3f5b7c7905cc2cace9903bea43154d": "0x040100000002000000000000000000000000000000000e5354414b494e4744585f434f4d0e5354414b494e4744585f434f4d1668747470733a2f2f7374616b696e6764782e636f6d16407374616b696e6764783a6d61747269782e6f726713696e666f407374616b696e6764782e636f6d00000b405374616b696e674478000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140823dc59ec2f7a204eed7cf3f4f6560d58db4eb78bd24b655bbd1d7a5c6b454e77c8dc5e2721a54d": "0x04000000000200000000000000000000000000000000164d4f4f4e204c414d424f5320f09f8c9520f09f8f8e001768747470733a2f2f6d6f6f6e6c616d626f732e6f726717406d6f6f6e6c616d626f733a6d61747269782e6f72671976616c696461746f72406d6f6f6e6c616d626f732e6f726700000f404d6f6f6e4c616d626f734f7267000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140832e37ad433bf330093c7603ddb81760e5c90ba6c0fde51812e18e6cc14121c081f5a573a868142": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140842535831df92d1f47c8e560ea22d951dc1d11f507e03cf84d24b763ac809f65b0cc96a38f0152f": "0x0000000000000000000000000000000000066f7a7a7a6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714084526527aebc960f46d9672ffd7ed18f87db293545cf8443b938604cdc750370efa50af4d74e603": "0x0000000000000000000000000000000000074a2d54686f72124a6f6e617468616e2054686f726573656e01011c4a6f6e617468616e6a74686f726573656e40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714085391a2cae90f2cb0ad422a668631d7e1deca3ff382cdba5899815abaa63f1d3a5c41ea5be4b930": "0x0000000000000000000000000000000000075a414942554e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140857cb9df490db87c8e9e95dcbc6b16730ff59ea5883c581d9a8468c6c9a8491282d765dc79e8b07": "0x00000000000000000000000000000000000f527873747564656e746c6f616e730000000000001040727873747564656e746c6f616e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714085aa13b537671b97ced45565a0da076fdffafc5b516479c72f4ad5c4a932ca1656b029bb79f8b61": "0x0000000000000000000000000000000000204d697373696f6e20436f6e74726f6c207c20436f6d6d756e6974794e46203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714085fdbb7e912dd07e2447f4fc17d2e0346ff5033dcfb1125d965384a3f2dc1ef86ced9346f8bb942": "0x00000000000000000000000000000000000f53757065726865726f2048656164000000000000104053747564696f536b657463686572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140867cd2096d96b96ea6a0804e0024beaa87fc072eb250446162310017e52147d18fada54a8ddb57b": "0x0000000000000000000000000000000000094e6f6465706c7573094e6f6465706c75731468747470733a2f2f6e6f6465706c75732e696f001268656c6c6f406e6f6465706c75732e696f00000e404e6f6465706c75735465616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714089158aaccdbbbcd36061b78bcd9eac1f33933dae70291680fa0718170cf24431cced2274e8e2916": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714089745272fb1fb5054bbd380dcf112ebfe5500ce634b45349943063e90651ab0ccd0eaa53baaa27b": "0x0000000000000000000000000000000000164576726c6f6f74204f6666696369616c204d696e74001868747470733a2f2f7777772e6576726c6f6f742e636f6d00116c757575406576726c6f6f742e636f6d000009404556524c303054000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408a50dd1623e5808bc8299cd873cbc489fb2b4f86c0220fb82bcbe6f87c419d4f82e258fbb11f11a": "0x00000000000000000000000000000000000f4b5553414d41204b494c4c414820000000186c6567696f6e2e6d616e79313140676d61696c2e636f6d0000084037333631304e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408afdf9f47614de486c987ce4f2f3af1bbe573bc5062e0d9369142d2f941758af4f5069e93ddaf42": "0x000000000000000000000000000000000008656c6d6965646f115061626c6f2056616c646f76696e6f731e687474703a2f2f696e7374616772616d2e636f6d2f656c6d6965646f310017656c6d6965646f776f726b7340676d61696c2e636f6d00001040656c6d6965646f6f66696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408b12c769aece86816433ddf1a483df91e588d4f5c677d25e99ee2144a6dc2e8bf38df8ce0970156": "0x0000000000000000000000000000000000054c6f707000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408b34e7e2acff7a2e2fd73bf97986a65ab0771df0eb3bc9fce592a2579562834f3e58ab28c760422": "0x0000000000000000000000000000000000084d696368616c5a0f4d696368616c205a61647562616e0000137a61647562616e6d40676d61696c2e636f6d00000f404d696368616c5a61647562616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408cc79e8d56c8beb7c88cb63517049b0569ba773b2cd7be3dea4c7c88340ba5f31c7bfa2e847f65f": "0x040000000002000000000000000000000000000000000b57617465726d656c6f6e00001b4077617465726d656c6f6e6e6f64653a6d61747269782e6f72671a77617465726d656c6f6e2e6e6f646540676d61696c2e636f6d0000104057617465726d656c6f6e4e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408d021ac78f6fc34ee1605fe949a127bc198df93f5fc6e420168e5656d28770d0e9e9402ac842c51": "0x000000000000000000000000000000000010486f706566756c204f66204e46547314486f706520446f726f746879204d75727068790000177468657275676761626c657340676d61696c2e636f6d000011406b6576696e6d753736333333363831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471408fadc8547f2d84d901564894dc37fb1719defd3063b29e6496544b7362fddece74fe06c88baad18": "0x0000000000000000000000000000000000134d6f726f6363616e20747261646974696f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140911084e9a4894bcac99f396388330ea1200432287395014e1bfb65195705130193212c656481e2e": "0x000000000000000000000000000000000008746173685f327300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714092d9c51c43937f55ecd23f062fc8fb0405c798c00b5759f52bdda38ebf10bbc464c757686125236": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140932ed16a6ce31dbd08450b51426556a9e61b8e928b97c6075d95cda58b433fdfca36a2b69d9766b": "0x00000000000000000000000000000000000d43687269732043727970746f1243687269737469616e204361726d6f6e611d68747470733a2f2f63687269737469616e6361726d6f6e612e636f6d000000000d404348524953435259505430000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714093c88d361b492968e76c9299f5a2046beaa5266ac0ef8b7b310c929704f15d8e6657b371302202d": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714094ca67c6fbadcea0ca2923ab15eaad6a04c929078d754253249227ad18927018f0a2c3be0fa5621": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409621844aea6b395108a708f579783ecb399a6e3f7a67b997440e4925737e9bcecbc49558d505d5b": "0x000000000000000000000000000000000005646f7431000000186661726d323032324070726f746f6e6d61696c2e636f6d00000840305f6f705f71000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714096c13bcbcb0791226104ba050f385c19450c62d2adb3e9deabed8783eee0059d582ff8918c03b10": "0x040100000002000000000000000000000000000000000d456c64726f6e20636861696e1d416c626572746f204761627269656c20546f727265732050696e746f00001f616c626572746f313640636164656e61626c6f636b636861696e2e636f6d00000a40416c746f625f3372000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714097cc1943b09bfaafc155a7f9fa6dec3ed3ce1edce6adabc9c0d1f3a9268ed34d499958d72dd6e22": "0x00000000000000000000000000000000000f4b7573616d612053686179616e3100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140997afed24646842ce9d61eca43a43e6bfec323df5c1e7084c1281161b82edb584027649766ef73c": "0x0000000000000000000000000000000000054e696b6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409a23974df7b0430c6038c7457c93db81c307499774a52b6e0a6915c040f1496c9baa6efe15b9704": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409b0fa30b4583caec82fcff0545821a3261f43a4956d1bec8f73ff13cec3c5e6d2788b27b7403547": "0x00000000000000000000000000000000000969736162656c6c6c0969736162656c6c6c00001945647a7a6131323334353637383940676d61696c2e636f6d00000c406c6c6c69736979616161000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409c590716ba75942788dc4de3ced2049b97d486b9fa84c1b4b442bc85ec2cf6dd67629f689a1cd72": "0x00000000000000000000000000000000000e50535943484f4e41555449434100001840707379786e6175746963613a6d61747269782e6f726716707379786e61757469636140676d61696c2e636f6d00000d40707379786e617574696361000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409c71da7f0f4f7aa98edcae85e6eef98ba192a51fa0efd89aac0541fa264d46adc9d8f29d3e21047": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409cedc84fed5609d6c1c40574832dee06228c10e43537fe6b3bc4cc78cdb7d34d1586d8904d8fa7b": "0x040000000002000000000000000000000000000000000447696f1147696f76616e6e7920476f6e676f726100124067696f79696b3a7061726974792e696f0e67696f407061726974792e696f0000084067696f79696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409d05f5fb1d062ad503551a752e49ebef1b6988ee561cbbfe0f442a56fe624a58ae80ff3b3b9cd7d": "0x040100000002000000000000000000000000000000001f45617420507261792056616c696461746520f09f8db4f09f998ff09f96a5000013407978313178793a6d61747269782e6f72670c4f5456406570762e6c6f6c000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471409e2ab1c6ac2e7039041c96d3710d0a1abe9f550306f252e363a81d717eddae45201284dd8538842": "0x00000000000000000000000000000000000e526f636b585f4b7573616d613306526f636b581268747470733a2f2f726f636b782e636f6d0012737570706f727440726f636b782e636f6d00001040726f636b785f6f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140a4afe501add7d8e2a9ab96177cbb3a9002cc0f132d4226537b14469ef685792839f47f15971d047": "0x040100000002000000000000000000000000000000000b5052494d455354414b4500000017737570706f7274407072696d657374616b652e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140a5ed2dc88d315840e534d4d97bb282068c705fa51611698a6c6680ded8ef9ad9e3ec644a4a1691e": "0x00000000000000000000000000000000000a57656233204368656600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140a7a36431e6bf788600e047c97181ac8d0b9d5a6372f6018f556d68b2b4cdb529d87da365f718d40": "0x040000000002000000000000000000000000000000000b554c5452414e4f44455300001740756c7472616e6f6465733a6d61747269782e6f72671976616c696461746f7240756c7472616e6f6465732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140a847e530cdb1c2e56217b7de1cc11317965e5fbbcd5befc40472e060042a6f69bf1aab0d2f08632": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32320f42696e616e63655f6b736d5f3232000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140a875f4d26e2532608676ec0e77c681fb1f96768ff752f535fce573b540abd2415087938e1c44456": "0x00000000000000000000000000000000000d4d61746861642040524d524b00126861647279736d61746575737a2e636f6d001b6861647279732e6d61746575737a383640676d61696c2e636f6d00000f404861647279734d61746575737a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140abb2bf22ebf7bae9efc577205550c1b254ff059895120f132de3e3b5fe0b9d22370e116257c0659": "0x00000000000000000000000000000000000f4b7573616d614d696b6520322e300000000000000c404b7573616d614d696b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ac3c356396cc02a160a6f4320d23a7715715fce96136dfa55616525f135a9868bcf1ba6f11acb25": "0x0000000000000000000000000000000000096e6674787469666600000017746966666465717569726f7340676d61696c2e636f6d00000a406e66747874696666000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ac7b83a778623410cfc58e61cb62c25fc3f45a56005f7b6cec22fe84eed6ac7c8992ce3209ab024": "0x00000000000000000000000000000000000a42756c62617361757200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140adcc02215ec15f4def30af11d3d4068f7418b757cd81b67176367423f5ea96868fe398290ae2669": "0x0000000000000000000000000000000000094b534d5f4d4152530c4d6172696f2052657965730000166d6172735f39323036406f75746c6f6f6b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140adfdac33d62d66a58e7e4aec9b2e494e77ea7aa2ba910d82923c91adf3c4a85cd912a16fa7da527": "0x0000000000000000000000000000000000105061727454696d654c6f766572585000000000000011407061727474696d656c6f7665727870000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140aeb5541d86b4845cc2f2f205d3d20d5a1f879ca5c20dc701fc9ca9aac3a17cfb7cf9527e2dcdf49": "0x040100000002000000000000000000000000000000000966726573686665720f4665726e616e6461204f7274697a010118656c656374726f2e6665727a6140676d61696c2e636f6d00000a406672657368666572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140afdef9f452d50b7c210bd52d3613aaeb1a76e1927e26284338d1ebab34b6b6f1208c7de97099b2c": "0x00000000000000000000000000000000000f4a6150616e646173205371756164094a6150616e646173134a6150616e6461732d53717561642e636f6d00186a6170616e646173737175616440676d61696c2e636f6d000010404a6150616e6461735f5371756164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b168c54499a2304bc97fbd07eff9c15a64279ab2c35c3c9aaa0e2c6ac35e2447dce59a7d528cb62": "0x0000000000000000000000000000000000044e454700000013646e65677265613940676d61696c2e636f6d00000a40646e656772656139000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b1bb76cb1a645af0ae6793d3b38c6903b70523d5a93579a7800fa29644ee67224b1b42792178c0c": "0x00000000000000000000000000000000000b737566696479616e6f760000000000000c40737566696479616e6f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b28cb00eb8fb1c6366e5d037b1dfbaea9aca8c05fa5e5d36147fad2a2ae114e33379a6b06bdbd54": "0x00000000000000000000000000000000000f676d616a6f722d656e63727970740f676d616a6f722d656e63727970742168747470733a2f2f6769746875622e636f6d2f676d616a6f722d656e637279700018676d616a6f72656e637279707440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b2d46548eb3753ccc96f77c66f0b96cfa65755b8d15bf9de55e014725c696d4f8e385701633b415": "0x0000000000000000000000000000000000064b6177696e064b6177696e000000000009404b6177696e4d50000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b3a777104037709f221049df41595b4296f7cdf47a38b5b7c3187f9cad55c48ad60277ec92ce869": "0x00000000000000000000000000000000000a73796e636c75622d340a53796e636c75622d34000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b490dd7c2add7ac567e17eb14c080fb53b263d9e08ed4259b3da6bfeacb088f3476752540b8f909": "0x00000000000000000000000000000000000d4172746963204b7573616d61001968747470733a2f2f61727469636b7573616d612e636f6d2f000000000d4041727469634b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b4bb8bd516529ad1cb12b2bfc64acd31cdd6d603e4d2752f952ce53346f87155acfdfd3f5d32304": "0x00000000000000000000000000000000000c4465782d53747564696f7300000015696e666f404465782d53747564696f732e636f6d000011404465785f4172745f53747564696f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b5975a00e39357f7e6df0b6f8d257074021c3bf045f9a74c020908f462edae423b2af34ddcaae10": "0x00000000000000000000000000000000000b43617374656e72696b6100000016707269636875646b61303340676d61696c2e636f6d00000c4063617374656e72696b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b78efadc03e987f66241b171bd08521a33dc807061373a092faea04252f58b70792e7c7ecfd500e": "0x00000000000000000000000000000000000e4b7520436f6c6c656374696f6e0000000000000f40636f6c6c656374696f6e5f6b75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b83cb57ee6e53be78277862099de58a7be0c6472923086fc92cd75c12beb02fe9fdbe0c8411b409": "0x04010000000200000000000000000000000000000000054d616b73000019406e6f6465732e6272616e63683a6d61747269782e6f72671b4d79726f73686e696368656e6b6f2e6d40676d61696c2e636f6d000010404d616b73796d3630343130343331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140b932747c4dc16804e89698cf8e1e4062df1e6994e7491d1b05c22908a4131a57bb753bebd99d82b": "0x00000000000000000000000000000000000b576562332047726f7570001868747470733a2f2f7777772e776562332d672e636f6d2f00116a6573757340776562332d672e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ba79531536753bb707c94e3ad62ed919cf1eebeffe3381161c4daef849a306d698539931a08ce14": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000e576f6c6645646765204c61627316576f6c6645646765204c61627320507465204c74640000176d6f68616b40776f6c66656467656c6162732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140bb2cf3340206487cc03adeb1111b9cfc802ef169d0629ec766a2588ab7609ed7363ce19e584ee5a": "0x00000000000000000000000000000000000552616d7a0552616d7a00000000000840307852616d7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140bb6f52935e1627fb8293604e2a0be96865b68a39d42cd4f5d53fcac3ac44ef060158ff7702aa419": "0x000000000000000000000000000000000009536c756d646f6745011d68747470733a2f2f70617472656f6e2e636f6d2f736c756d646f67650101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140bc06185ac12eb70fece00a202f0832dbb17324ef664cfbd18ce6b0625fca47f0931f0d7785c7445": "0x0000000000000000000000000000000000135275746765722076616e20646572205461731052757467657276616e646572746173187777772e72757467657276616e6465727461732e636f6d00000000114072757467657276616e646572746173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140bcf942d23af458454aa43748f98be9e3704f9a2a95cae73b3b03724b19cd79ec06f383b2daffa2f": "0x00000000000000000000000000000000000c6d6f726964696e2e657468000000166d6f726964696e2e65746840676d61696c2e636f6d00000d406d6f726964696e5f657468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140bf3579ecdcacde0362f7ac49028175d12576f48a1cef9e71c533ecd9221237c772132cbf5168342": "0x00000000000000000000000000000000000f526963682056616c656e74696e6f0000001a776869746576616c656e74696e6f6f40676d61696c2e636f6d00001140526963685f56616c656e74696e6f6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c100cc5eae89342e659339aaaf44f9871d9a42595bece9cc446cc4dc321dcb30c798332a5780846": "0x040000000002000000000000000000000000000000000454555a0000164074757a2e70657465723a6d61747269782e6f726716613935323435313430383940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c2040d8da8b2f132053de39c4b63304c65a0cc0d93d1b81537a4ea78be0e09404dc74f3ee8e276a": "0x000000000000000000000000000000000019506f6775657a636c61702d506f6c6b6461646f747b4a537d0000001f4d724b69747479536179734d656f774070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c230db7b4eecaf8c4d023d2b04cd11112b689517d5e8bd20a66aa5c62f9bb7830e227ff88617f2c": "0x0000000000000000000000000000000000045a4841055a61696e00000000000c407a68615f747765657473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c32af425ecf7636aceff65e3bc5a9cc1ee6dc90a3acc03f65cd6a66c7c23104d7d21a3f4d266a3b": "0x00000000000000000000000000000000000e33394b7573616d696e61746f7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c388e1358813ebd801e4481679d2522f3f9cf41a66df264210fe9780528c04280a33003e2022618": "0x0400000000020000000000000000000000000000000016416c78566f79204b7573616d612d3120737461736800000015616c6578657940766f796e6974736b69792e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c3a9dcfc81a3cfe046677c468409001b6cb1e3a1043cee8fa919aca71e27a8f65ebb965c6ae717a": "0x040000000002000000000000000000000000000000001170692d76616c696461746f722e636f6d000000157461754070692d76616c696461746f722e636f6d00000d70695f76616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c41e5ffb19e12ae30a11a36a48739b8fa4bee6844af919e22aa50f114f9e395a1caec59cc157102": "0x0000000000000000000000000000000000055365756e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c46249d82bfb0b0d074e77a0de68e6cf05f748acb4958d062f29eb223b87be225918f23d9bf6866": "0x000000000000000000000000000000000009756469626162613100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c50403091a3fe08acbaf2c1d45ca4529a36ed37d0197fce11c1848cb62c607457c5629688ca0554": "0x00000000000000000000000000000000000846334a6f756c650d566c616479736c617620502e1b68747470733a2f2f6769746875622e636f6d2f66336a6f756c65144066336a6f756c653a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c6834f1c2c76bf29aeff1e8a9d96bcdea1837651f64dd248d8c2bf13b76759fae5c60f6237e641b": "0x040100000002000000000000000000000000000000000f313132304e465447414c4c4552590f313132306e667467616c6c657279001840316e667467616c6c6572793a6d61747269782e6f7267163131323067616c6c65727940676d61696c2e636f6d00000d40314e667467616c6c657279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c6c6f483598e787deb2bef705dcf0792c4027cdf5fe3cc6f064446f80d5281c11fc0883a95a6761": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000055a45524f0d5a45524f205245414c4954591068747470733a2f2f7a65726f2e696f000e6d6172636f407a65726f2e696f00000b407a65726f646f74696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140c8734e9ceeea871e69ade711fa80a229815e5847e1041104fd08fb5a4e77e2a5f0d912b16aaaf03": "0x04000000000200000000000000000000000000000000094d696c6572756e6f00000019696b61617274696b61776174693740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140cac97255720a64876323344da3952acb9f0a654bb3402f6a95eeee8abc97c3b13c2848ce9bea600": "0x000000000000000000000000000000000010417274456e3639736567756e646f73144172746520656e20363920536567756e646f7300001a617274656e3639736567756e646f7340676d61696c2e636f6d00001140617274456e3639736567756e646f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140cc8f64bbd2e71ea820050e114404eec82932c59bedbfb6c1b58981e8f85af37e5d4f26a34226960": "0x0000000000000000000000000000000000104d6173746572537061726b793430320d44616e69656c20426f6f7264000014442e6a2e626f6f726440676d61696c2e636f6d00000940646a626f6f7264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ce0f91c97c65aae744be50accad162e5162a2499a897f5cfd792e0ebf9ca6ed7d13b5e404b36007": "0x040000000002000000000000000000000000000000000b536e6f7762726964676500001d40776861747265676473666f64726a6b673a6d61747269782e6f726713616964616e40736e6f77666f726b2e636f6d00000e40736e6f77666f726b5f696e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140cea71908e309bff28cf33cbe014592a6f11c9133006203591ac206fce44a0d3ac5519667aed0706": "0x00000000000000000000000000000000001167c3b66b68616e207461c59f7465706500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140cf71787521e6de28a04ab3a66328e01112d81c15314c12bd4b6411baf8e05225e47a13daa78dd18": "0x000000000000000000000000000000000010446f7473616d612e4578707265737300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140cff0134bde4ac18abb9286b2b288f2af6eb392d95b12a64768174de723047b9ae0f86283dd5e34c": "0x04010000000200000000000000000000000000000000115374616b696e6734416c6c20f09fa5a9001d68747470733a2f2f7777772e7374616b696e6734616c6c2e6f72672f18407374616b696e6734616c6c3a6d61747269782e6f7267167374616b696e6734616c6c40676d61696c2e636f6d00000d407374616b696e6734616c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d0340c34236dbdc923059e1888ad3f7c623b3f84c113bc75975e5dd8957590104b9c0613433b67a": "0x00000000000000000000000000000000000a4d696b686173686f7611536572676579204d696b686173686f76000016732e6d696b686173686f7640676d61696c2e636f6d00000b406d696b686173686f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d081f1081222619c8937715d6516a1081fc4e2757dcdb7a687f9f3a4021e0671f1ff7576a88d55c": "0x00000000000000000000000000000000000d42726f734f6643727970746f0101010100000f4042726f736f6643727970746f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d09678fc53ebff9b6ab520cbb6fe9b6bc5433fa4193074bd1aae212f0dc969d6af584e140a08a5d": "0x00000000000000000000000000000000000d52616d70204e6574776f726b1852616d70204e6574776f726b2073702e207a206f2e6f2e1668747470733a2f2f72616d702e6e6574776f726b2f15406a7061756c696e613a6d61747269782e6f726715636f6e746163744072616d702e6e6574776f726b00000d4052616d704e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d227a0c675a37dee0a1c40e9a37cd51d6b644a33e8e4952d576accdbb13c967bf8ea3474a583031": "0x0000000000000000000000000000000000105375676172436c7562205363657468105375676172436c75622053636574681f68747470733a2f2f747769747465722e636f6d2f5375676172436c75625f010100000c407375676172636c75625f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d39c09be41728d25271937d9336b12c2801a62938d27878729a7987c705770d5f19c0e42ffcc64c": "0x040000000002000000000000000000000000000000000a455645525354414b4500001a407669745f657665727374616b653a6d61747269782e6f726714696e626f7840657665727374616b652e6f6e6500001040657665727374616b655f706f6f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d39d429edc8d0712254479a21f40fd96f3ed15a8f08f6d289e7c9d1701ebf89ad6ff6d5755b824f": "0x00000000000000000000000000000000000f4449202d20537562736f6369616c0000164064656e6368696b33373a6d61747269782e6f72671564656e69732e6967696e40676d61696c2e636f6d00000b4064656e69736967696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d3c3a7016e8df8e500908d663623ee3c05935758e1f056d70c0a8ea33fc0c00384845dd7f3dfb56": "0x000000000000000000000000000000000008444546496b736d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d4ca3ddcf99187b260a01d4ea712ce6bf0fa166b6aebe2ddfc86bf523307005f6c87c2ca654916b": "0x00000000000000000000000000000000000a626c6f6e646961646100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d533a9fec9db13002b47d21483aa953be67636583cb184f55d575e0f71ec75f45383a786324a64b": "0x0400000000020000000000000000000000000000000015f09f8d8120486967682f5374616b6520f09fa5a9184e6578757320496e666f726d6174696b204475727265721768747470733a2f2f686967687374616b652e746563681640686967687374616b653a6d61747269782e6f72671e686967687374616b65406e657875732d696e666f726d6174696b2e6368000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d5ce2f7af07c1b88afeae9a945866e010eb1bef5082c9f0670e484984b6873e7f0eb297cd4d8e54": "0x00000000000000000000000000000000000d307847686f737452696465720000001e6b696e6767686f73747269646572303037363940676d61696c2e636f6d00000e40307867686f73747269646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d65a8f206f0572aa67b45909ab82a670809e0eb1dff23c0d4f296974b62d8d823cf45471044c516": "0x00000000000000000000000000000000000b45736554654c6f70657a0000000000000c4045736554654c6f70657a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d7e595debaf7057166a8e85fb2ae8e4bb6815407ab2e17573050a080e1babc5022264fef9e96f5e": "0x00000000000000000000000000000000000768616e6e657300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d8bedb75031185630734713c5ab53cf7cffbb321ced799fc7d49b43f385234b15c2ca720a222573": "0x000000000000000000000000000000000006706f6c6b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d905eb3b2787c26d495b0e302e1a577cd8ac5bd2681568e809e706bc32ca18d0a3921680530fd19": "0x00000000000000000000000000000000000b4e6f6f646c6544756465000e6e6f6f646c65647564652e696f0000000010406e6f6f646c6564756465706d7673000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140d98f82850d6b275f2e9d52d264f1d78a2f3379ac661de73255cf80b6b54a4b80de6d9c31f748a0b": "0x00000000000000000000000000000000001b5375706572636f6c6f6e7920446566656e646572732046756e640d5375706572636f6c6f6e79201868747470733a2f2f7375706572636f6c6f6e792e6e65740000000011407375706572636f6c6f6e795f6e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140db5079f95a9bf8dfa7c3aa61ad8c8ddee5e79e5cf0f0094d4ec0a1c5ce1b74064a3001d0ea2b64a": "0x0000000000000000000000000000000000084d722e484f444c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140db9aeb749b73803bea5add43dcec81b15267ff88d61106f1640f5a8c84bfe8555fcfddc64bf3405": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140db9d7828adfae319e7c6c92b95381eda2995d8b4b6f3926b694c74c3643dddf3e4d182c316a3a13": "0x00000000000000000000000000000000000c4444204d7974686963616c0d44696e6f2056756b656c69632168747470733a2f2f7777772e6c696e6b6564696e2e636f6d2f696e2f64696e6f001964696e6f2e76756b656c696340686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140deed80c472e7c7c686a3a22aef015c34517659f4f96c5f1768aecc308f1467dc621e85c709d1809": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30320e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140df42bc818c9fd1ef89bedd1de864245baefc341997957f57eaf77620e26ef1aceee9bb50bce4220": "0x00000000000000000000000000000000000b617065586368696d707a001d68747470733a2f2f6c696e6b74722e65652f617065586368696d707a0015746f75636840617065786368696d707a2e636f6d00000c40617065586368696d707a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e032f02dea784887ec0c61a682519e78e65026c51ceea52273870636814605a33518f02ad543317": "0x040000000002000000000000000000000000000000000d737765617479627265657a650000000000000e40737765617479627265657a65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e08280eb46d228ef69de233dbbad30fd78a5a88bc8fb4d38bb9c0caa6f0e73a4a4f8955ac5ec253": "0x00000000000000000000000000000000000941534148204e46540000000000000a40415341485f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e0b3aa196d8924da44db018b0966000a7601da48063c535ab23ef856aaec13fa1555260c244143c": "0x0000000000000000000000000000000000010c4672756974792d426f797301010100000a4030786c756b656f69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e211dc5b0982117b47a017c3ebaff5fc5e7b686fb511d9d8b7065322339274695f8fe1d38200172": "0x000000000000000000000000000000000006666861696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e21b1928b52b99a9adf3209ba3436e0c3e7b87ed6aa40fa1a88fe68ed3a00ad0e922a147494324a": "0x040100000002000000000000000000000000000000001847454e534849524f20425920455155494c49425249554d0000001d616c65782e6d656c696b686f7640657175696c69627269756d2e696f00000e4047656e736869726f44654669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e28c8c63d0620b0c84c7013e7639f5ce15c6b51d9a33ab040dedf1851c71d697f3fad5f14594549": "0x040000000002000000000000000000000000000000000f506f6c6b61646f7462616c6561720000001b706f6c6b61646f7462616c656172657340676d61696c2e636f6d00001040506f6c6b61646f7442616c656172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e2df285221b11002639d5a44f52ebb752039a5def9e776c12b8ed3ba1a12e60299cfc00fe546c2f": "0x000000000000000000000000000000000015504f525455475545534520434f4d4d554e49545915504f525455475545534520434f4d4d554e495459010119706f6c6b61646f7462726173696c40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e60e74a5190baf65ae72c7ce8ab9b183909c1cb1eaf21f02850c872130f391af72c4380efa3e738": "0x04000000000200000000000000000000000000000000084e6f76614e6578000015406e6f76615f6e65783a6d61747269782e6f72671669726e64656e69736b6f6d40676d61696c2e636f6d00000e404164696e64614b6172696b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e73707fed983955ae1ba2069c434aa22b860314674b862a23eb53ae9603316439d3cab44e6c7e20": "0x00000000000000000000000000000000002047616f20746865204879706548656c6c207c20326f6636204d797468696373000000000000084047616f417065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e77a555b20dfd069642d0db9f3b301b44df74b63b0b930011e3f52154c5ca24b4dc67b3c7322f15": "0x040100000002000000000000000000000000000000000a536f72616d6974737516536f72616d697473752048656c76657469612041471868747470733a2f2f736f72616d697473752e636f2e6a701d406d616b6f746f2d736f72616d697473753a6d61747269782e6f7267127440736f72616d697473752e636f2e6a7000000e40736f72616d697473755f636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e7ebd7950f6e71f663017d73b55d4f4a7fd5adcc62006ff49b12f6056f2f30fefd21b4a0ee35610": "0x00000000000000000000000000000000000c5a68696c696e5374796c6509566c6164696d69720000136d722e7a68696c696e40696e626f782e72750000084058616c6c4861000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e8cb1099f1092089cb4a8212f1c823c25693c15467047378f846454bad62d6c947a2ade36563851": "0x00000000000000000000000000000000001f4d6f6465726174696f6e205465616d20426f756e74792043757261746f7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140e9910201efc63d224eb144dc285fd665819aa61ee6765b27039ec6d4c6c9993a7c163f063cdab07": "0x0000000000000000000000000000000000034d52034d52000000000009404d525f30303431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ec06ed16827147be2c0f5532d658a0c0d9e12c26bc062e30d309adf8e39b4a0c29e489f382bfc49": "0x040000000002000000000000000000000000000000000a63727970746f6c61621243727970746f4c61622e4e6574776f726b00144079616f6873696e3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140ecb33ed71b3de7b708eeff6aba393c24d89dbd6bc74e46cef9ccb7be321647b624781b76d9ba304": "0x00000000000000000000000000000000001054686520506978656c205661756c74000000000000104054686547616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140eedf7d25e7a7bc88063c56f76c1dec83d0cc13abbd248d438d512f5510a62dcd6e98d2fa9e38e41": "0x00000000000000000000000000000000000a74616d614a6f73686901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140eef1e0dd5e940a8d8e704ee02d595b8622d1d1901dbae3dc049118e36e85317e2cb7f9166b7c93d": "0x04000000000200000000000000000000000000000000095072617368616e74000000157072617368793230313040676d61696c2e636f6d00000f4050726173685f4167617277616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140f177f5acba9e6e070661c356f24a2cddc859fbae974cdff149661f165f5e622df3060bcb8e7b373": "0x040000000002000000000000000000000000000000000e53796e6572576f726b20496e63000000167374616b696e674073796e6572776f726b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140f75f7e0ac3e676454273ca13308c2a9f40b322ab6c192da5ab9f8cc8be07326dfdca1c59689bf08": "0x00000000000000000000000000000000000c432e204b616d696e736b69001b68747470733a2f2f7777772e632d6b616d696e736b692e6172740012636b40632d6b616d696e736b692e61727400000d40434b616d696e736b693137000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140f7722ef9e3f0c3bb0d8ce5256f0b5a51a38ccaadc6d21fe930d8ff3da1dca198ebe1807802da753": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140f7f00ad7cb619c008769738ff8d53c17d6e0f0344e52c50a5ef6b61a33389f4dc4adbb7aa2f384d": "0x04000000000300000000000000000000000000000000105765623320466f756e646174696f6e1d5765623320546563686e6f6c6f6769657320466f756e646174696f6e10776562332e666f756e646174696f6e0016707265737340776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140fc514eab423f9a784434de779e5fcbe6da08b123b0d1556c5ded43cccd6a9b1f6efdc9ea4942032": "0x040000000002000000000000000000000000000000000f4b75732056616c69646174696f6e00000016686579407468656b7573616d617269616e2e78797a00000f405468654b7573616d617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140fcc6386bb41988e76d82b70c69c1fbb8c15260720357f8964dde4621520267051b69a86d46be767": "0x00000000000000000000000000000000001050726f666573736f724875676865730000000000001140726f63686573746572736e69746368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047140fce6746c0fcbe63c2fb8933d2f269bfc83970bcf019e9b9204fe40666ca00494eb9c6560a53b01b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714100660e0aeb247211c2a9af7bdca199cf341b9fc1315c3fa625849d6e9bff3e7361f40f4889ab57c": "0x000000000000000000000000000000000009446f746576656e7409446f746576656e741568747470733a2f2f646f746576656e742e636f2f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714100ad1333a8758d9d8cca15fca39d01fde7d1eff1cc8529dfca033c40777994e23150e81c72a1640": "0x00000000000000000000000000000000000841564c204b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141015fbd7c4e0657c321b74ce57dab7e81fd0a29d2d5eb705ec3f0950df8d9673d2f0e9188fecd867": "0x00000000000000000000000000000000000e4c6567616379204c65617665720000001b6c65676163796c6561766572736c6c6340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714101dc364cacca331289d0e953caa48c4e7e416022169d1a71ca9ef7726571d551b3fcff2bdc59a73": "0x0000000000000000000000000000000000094879706548656c6c094879706548656c6c1e68747470733a2f2f646973636f72642e67672f664d63386862506d354d000000000b40687970655f68656c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714102148a1017f00501a393b336f8230565ac033b4e83c4a1711f87eff586d2acfb351a1254c41235d": "0x0000000000000000000000000000000000097869657765697a63077869657765691d68747470733a2f2f747769747465722e636f6d2f7869657765697a63000c787763764071712e636f6d00000a407869657765697a63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410285ff7a2dfaaed30dd6b5e5177c32a64cdb0f0e601d77902c2833062b3cb7f5800e7a2c497640a": "0x000000000000000000000000000000000009f09f8c88f09f8d8000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410373f12dc9ab897a4a045fee5632d07206b047972efbf41de0351885f7d0c8d7bd2f272dd98c053": "0x00000000000000000000000000000000000e4d6172696f2056756b656c69630e4d6172696f2056756b656c69630014406d6161722d696f3a6d61747269782e6f7267176d6172696f76756b656c6963407961686f6f2e636f6d00000a404d616172725f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714103e847acd44a834c8c0c1fb9bb3902b9e4790461bec2c33afa31c9a3b72a4e4ab6c050b4a284507": "0x040400000002000000000000000000000000000000000b436f6e6e6563746966790000001c78696f6d6172616268756c6c617235323740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714104c4a90570bc5fcb01a8d3e27c8f4a2f1ed53bad7d240999ec076bb23155fdc020b70e2680efa1e": "0x00000000000000000000000000000000000943727970746f44560000000000000a4063727970746f6476000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410547c88eb5e1280f889d7a8087639059b95b1b3de84c8f80361fb2309a7497388b6ded2e815d766": "0x000000000000000000000000000000000015484154454d207c20444f5442454c33415241425900001940686174656d656c73617965643a6d61747269782e6f72670000000f40686174656d656c736179656464000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714108d9a2d402cd7cd82e813a68fe066b55cfbfb48fb99484e96f813e3f2b98ae3dedda80f5b069243": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714109f2a19e0b0e38a20d4b086bb5326ac9896b0a3ab4f37fdb680a09706c4460c98110b1a7aae4f12": "0x0000000000000000000000000000000000000000000000000f406672697a7a6c657a6c7a7a6c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410af15fa81ea76ada81e54507ca4f6fa30932b96d35e8f073556c99f4e3119e5f679893450192109": "0x00000000000000000000000000000000000853435954414c4500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410afe0be04153ccb6e7a5ea5f4113720dab9d89c4b7f949ea67731df7421ea069516115777b2ba6d": "0x00000000000000000000000000000000000d4265747479202620426c6f6f00000016626574747978626c6f6f7340676d61696c2e636f6d00000e406265747479626c6f6f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410ce5b49d79045fda2b8bfb3c0c1f04346134e7b27cb5b63de8a7af0d57c502d09c05ba7b3dd1e28": "0x0000000000000000000000000000000000054475636b010115406475636b77696e673a6d61747269782e6f72670100000b407468656d6475636b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410d658671f80bdd8baf077e92aca3921fc948042653b85d2c7cf1dae44eafdd35270943ded113425": "0x040400000002000000000000000000000000000000000c50726f647563745f4c49540000001d6665692e6c69752b70726f64756374406c6974656e7472792e636f6d0000094066657977756465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471410fcb033412d7d4970882eac544428a1332197cdf4e46f0ec005b083f30c9e00beed9f0c0f48817f": "0x000000000000000000000000000000000007576176696e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141109d1b0b3898be6446130ed95427fedb36702f4ab2eae7612e5f2f5033cf0f8b51ea97e13f1d219": "0x040000000002000000000000000000000000000000001e494e20535042202d20f09f8dbef09fa582f09f8db7f09f8db9f09f8db8000015407370626472696e6b3a6d61747269782e6f7267185350424472696e6b4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714110c6956c14d8038f81fefa90f5199ca0d60d147602cf2f9001266e557483d41ce8c671d51605313": "0x0000000000000000000000000000000000104968617665427574745468727573680000001744616d704372616240686f746d61696c2e636f2e756b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714111aa70eba23115bfec58ced993f959b9e3f61848eb10caa2a1376941d30c06be2425b1e31f50e23": "0x00000000000000000000000000000000000c4469676974616c205a6f6f002168747470733a2f2f6269742e6c792f4469676974616c5a6f6f47616c6c65727900186469676974616c7a6f6f61727440676d61696c2e636f6d00000f406469676974616c7a6f6f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714112601944f90bca480e7d9cef14591225c0e2a135224b576efd10b38cde56f71ef231dac8973b524": "0x00000000000000000000000000000000000d236d616b6f746f7069616e73106f6666696369616c2026206f6e6c7900001362726f6f6e79636f40676d61696c2e636f6d00000d406d616b6f746f7069616e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714115e48078425c5c92aa70df8bfb5ebf58cd2bfcdabad29392ed53b1d2f2ab81e519e6bc4f490c13b": "0x080000000002010000000100f0373a00020000000000000000000000000000000000000000000000000000046e6a690000001a6d696368656c6c652e6e6a692e313240676d61696c2e636f6d00000000096e6a69233536323800", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714116a7dbbc41fa50e64b011ce64137258e47a08cab6b492788e03e74f44c7c3a22c567217af20645a": "0x0000000000000000000000000000000000026a0000000000000b406a656e5f646567656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141181e386a86037f2d269f40cdc569d0855c22874f24a81b572d76d8d08469c33d1cf70db2d5b206a": "0x00000000000000000000000000000000000970617374614d616e164d6f6368616d6d6164204875736e692052697a616c1968747470733a2f2f6963616c31302e6769746875622e696f19406875736e6972697a616c31303a6d61747269782e6f7267156d6f63686875736e697240676d61696c2e636f6d00000d406d6875736e6972697a616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714119a0f76e4d92fd98c68b0748032acd289880d004ed59fd72856fcd75133faf360f0e1652a23276b": "0x0000000000000000000000000000000000064c4f474f53064c4f474f531e68747470733a2f2f747769747465722e636f6d2f6e66745f6c6f676f73010100000b406e66745f6c6f676f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411b8ff944fec6dc1d09a1884c8ca6641e644447f160be702de9c6748da6b51c553d6ff35cd8e4e08": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411ba561e194c5f74d897ab7ef91822fe787ae9e4ec865e6aed2aa20e59e6ca0df2fb67d266497d4b": "0x0000000000000000000000000000000000174b6f6461446f745f4672657175656e745265616465720c4b6f6461446f742e78797a0c4b6f6461446f742e78797a0000000009404b6f6461446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411c43684ff6dd5c2426d4caa9a620d37f530756d282dd41b1105cfb4e4e3bcefc18609d1ee199d1c": "0x000000000000000000000000000000000006536b61646500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411e075ceba8e3f4524112dbb17e6f83bb832ee26149c8b00cefac96a1a668ccf0645898c3c271d04": "0x00000000000000000000000000000000000c54696d204a616e7373656e0454696d19687474703a2f2f74696d6a616e7373656e2e63727970746f00177468776a616e7373656e383940676d61696c2e636f6d00000e407468776a616e7373656e3839000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411e755e0b2a267d8a8a2e5461f346cf0c23d1ca613437432a160525b6487dbb718afa51439d48d04": "0x040000000002000000000000000000000000000000001a4b7573616d6120537465616b2d4b696e67f09fa5a9f09fa4b400001740737465616b2d6b696e673a6d61747269782e6f72671a737465616b2d6b696e674070726f746f6e6d61696c2e636f6d00000c40737465616b6b696e6733000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411eab7306fa8072a201551760e53240d8229b7c99fcbce0ade237854dff91796dd67c5a00cb43672": "0x0401000000020000000000000000000000000000000005636c696f000000156f746f67656f6e69636540676d61696c2e636f6d00000c4065617269617332383238000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411edb4162e9b96b85ecc1b0043fe1fc18950cef3726fa74151bc41f77438ce924c11a9b43823ff43": "0x0400000000020000000000000000000000000000000018f09fa78a2049636562657267204e6f64657320f09fa78a00001940696365626572676e6f6465733a6d61747269782e6f726716696e666f40696365626572676e6f6465732e636f6d00000e40496365626572674e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411fbcd54abb1de419ce84f6cd845ac3fb2a009aae8e99b1a2fb64aa3e7ce1c7867f3ab2db0c9bc00": "0x040000000002000000000000000000000000000000000d6c696465727461626f72657300000018736f63696e796970657273696b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471411fcae71b9124914ea2cf269fd21f2df6e71e5df234b1d1e5e05c145e02d40ddff3b6f0a7691c64b": "0x0000000000000000000000000000000000065768616c790000000000000a40796f756365617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412060f617a53b90efa99c57636163b80492e7748882c27e82074cc76ae723804e0c8f222aa1c9879": "0x04000000000200000000000000000000000000000000144b726f6d626f70756c6f73204d69636861656c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412340500c577b01cfefac151cf58a64b79b329b7ecf23bf592066f4af0cf1a17c61ab61f4d71cd63": "0x00000000000000000000000000000000000c5a657573204d6f6e6b6579000000186976616e2e7370616e6963333240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714123e32f295726d2f301075ea9032e7e039d63b38ea075a276cd2f0f7087ffbeb1eb4320213048955": "0x00000000000000000000000000000000000e50756e6b205661756c7420233100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714126b274fcd441f701054d5e79d6343876329914f0e7264c1f7abb9ab83c6944a08d1e1c594b4541a": "0x000000000000000000000000000000000007486179746368010101156861737372697a6b393340676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141281300a3acf4a3efea6e9d55bb4b00962d6ffa48d1305b1e7c90f6cd08858ad5a7a2b86e6394470": "0x000000000000000000000000000000000011416c6578207c20444b2053747564696f0101010100000e40444b73747564696f416c6578000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141281736c37e85f535829756f059fc06840d26ad9c75518aadfbf125314f9af67f67b7f5f66eeb97e": "0x00000000000000000000000000000000000b536f6265722048616e7a0000000000000b40736f62657268616e7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141283d5fd7b76f3b26ee23b9c2e8092cfaf9a22eb3f6167f099fa3a0413cc379b666684e5e944f242": "0x00000000000000000000000000000000000a4c696c204d616e676f144e677579e1bb856e2043616f204e68e1baad7400001a6e677579656e63616f2e6e6861743340676d61696c2e636f6d00000f406e677579656e63616f5f63616f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141299152c90d9cc99f27087b92d180452a367b385c93e4ff2f9206ad87b172471a8d54b721d282910": "0x00000000000000000000000000000000000a6b756d61676f726f770b6b756d6120476f726f7700001b6b756d61676f726f752e6d756e61676540676d61696c2e636f6d00000f406b756d6135365f6d756e616765000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412a2b27991e12dc3f4e082da663ec16019fc9db34386a4b0c4571ea758f19f75b5ed496817816c79": "0x0000000000000000000000000000000000044c784d11416c656a616e64726f204d696c6c657201010100000c404d696c6c6572416c656a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412a67a04b3ff6d1cb8e3827ef7f013ffe0684f2a2463cdb6d81a74dd0f34b0b7e0761105f0dedc45": "0x0000000000000000000000000000000000074a6f795a6574115365726869695f566f726f746e69616b0000166d696e697374723134303840676d61696c2e636f6d000009407a65745f6a6f79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412acf616659be35f9866ec0c1204773a4b95a1b374d838b5820f704a65deeaafb97f4ab96c351158": "0x0000000000000000000000000000000000164b6f6461446f745f4775696c645f52657761726473164b6f6461446f74204775696c6420526577617264731b68747470733a2f2f6769746875622e636f6d2f6b6f6461646f740000000009406b6f6461646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412b1ab7fbedaeb3e100c99beb21e35628a5e0d811d0e6637b1e43b5deba5b3e555ca78e071f4b803": "0x0000000000000000000000000000000000095761674d656469610000000000000e40746861744d65646961576167000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412cc628ce2af21b01837232566f19190ccb14bf5a1e60a805398032d38e87eab9ee18f90aa0e721f": "0x0000000000000000000000000000000000096377696e656464730643687269730000136377696e65646473407961686f6f2e636f6d00000f4043687269733737323630343530000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412dffed5472b77a54a9086ffb666eec156b216247f7daf9f5eb73806ee501ba87f7ec8f83a19d86b": "0x000000000000000000000000000000000005c2b06f2e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471412edd5e808c61a4696eac06549b02180ec91154820531dd78640a234d3f1f6efd9728f0416851f41": "0x00000000000000000000000000000000000f4275794869676853656c6c4c6f7700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141307eb650f06f8f7721cd1fe88d1d2df420564396ad478c84d9bd66447c55bb330a4e7d8d454057c": "0x0400000000020000000000000000000000000000000008477265616e63680000001667657274696b657274313240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413102e0d3c1339e244135eb8cdc82a9fba31b0c628faa21e6a6cfc80396883a553a2766339b03078": "0x00000000000000000000000000000000000b4954417374616b6572730b4954415354414b455253137777772e6974617374616b6572732e636f6d17406974617374616b6572733a6d61747269782e6f7267156974617374616b65727340676d61696c2e636f6d00000b6974617374616b657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413266de9c03a53de50b9bf10b8cffa9a694570ef350b8191d567cb46a04a361bcfa618716b78d715": "0x00000000000000000000000000000000000f4d6574617665727365204d616c6c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714132693d807f6c23df804dcab1236fb910768d4da27194a2e66172165d41f8b26d95a23e051d86c42": "0x000000000000000000000000000000000006526176656e1154696772616e2053686167696e79616e2168747470733a2f2f7777772e66616365626f6f6b2e636f6d2f74696772616e2e1440726176656e33653a6d61747269782e6f726713736865676930303740676d61696c2e636f6d0000094074696772303037000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714132a190b2bc6eb70a4f12c896b5de927b41124a79d0808d61c32f5c3105f58e80369321888d2a351": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714133d012d7d60381ec218093851955159d042164ec55bf7aec8e4bb8754b34938dd58603322bed771": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f343500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413464ebee1a9be7b46c9c30fca4d06ed3cde1cd6ca25392fec9e27d6ef86f786118a53416401767c": "0x04000000000200000000000000000000000000000000124b7573616d617374617274657220526561000013407265615f63683a6d61747269782e6f72671472656173636865676740676d61696c2e636f6d000008407265615f6368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413470468a7a63147c214e403c5a7b459b86bcab68e6d21241c1bd20b91aee546c787e71b877bf460": "0x0000000000000000000000000000000000134d616365205468652050656e6e696c65737305416c6563010101000011405475636b6572746f7468656d6f6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714136bb08c596dddb97ce2421f6b3c80a00c8fa9476eddad55f7bb9cc2f54ad916b4969c103b5fd438": "0x040000000002000000000000000000000000000000000a48204120562049204b001168747470733a2f2f686176696b2e696f1240686176696b3a6d61747269782e6f72670f68656c6c6f40686176696b2e696f00000a40686176696b5f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714136cca57f11634c0d29f3ce17cedb01b50312d7318ef8e9653d15682dd2511984fc963623bbdc272": "0x0000000000000000000000000000000000094f6a72614f6a726109416c6578616e64720000166f6a72616f6a72612e717140676d61696c2e636f6d00000d404f6a72614f6a72615f7171000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141386b80bb27232f3b8060d01712e6c73c63d799537517c6eaa4cc91aaff645802c824ad857dd8e28": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f353200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714138ed61d7d4e581400725cbb3eb7e1fda5b19c7ab123a08c1a28b16d17fb4d6d09f679012ba38c04": "0x0000000000000000000000000000000000055441592001010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714139cbe44f2633cf6d6793dc7dde7b0d936b3e1748e322422c6f61b0a88d009af3556118b28729143": "0x000000000000000000000000000000000005446f7473000a646f74732e70696e6b000000000e40706f6c6b61646f74734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413a4e7699eebbe52e6ff88586d3166ca2400929db69f53a8c80f5aad9dcd88e2c2634596baeb4a0a": "0x00000000000000000000000000000000000b676261636920524d524b001f68747470733a2f2f6c696e6b74722e65652f706f6c6b61646f74626f6f6b124067626163693a6d61747269782e6f72671767696c6c69616e626163636940676d61696c2e636f6d00000840676261636958000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413b3f7e5a93f07231888d8cd7f28c49bef8d47726228213023b7b83604937b9149df15278dad014c": "0x04040000000200000000000000000000000000000000194c6974656e7472792d5265676973747261722d50726f78790000001f7265676973747261722d737570706f7274406c6974656e7472792e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413cfcb660666c8624ce1f78bf64a21a6e2eeb43328484cb4be5f4e16487ea889ec097601ba8adc13": "0x0000000000000000000000000000000000056261687506737572796100001b737572796176616d73692e7065726c6140676d61696c2e636f6d00001040737572796176616d736930393132000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413dd0435c4b8c522b4666c60cc9d87c3915b4baeca2d36c35099e9ca0ddf514d46af551fb0548b68": "0x000000000000000000000000000000000004617a6501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413ddb460718d6739042f0f21da287ed2ed87cff8265c769b29dcfbdb31ac0139f932e7995953d53d": "0x0000000000000000000000000000000000084e696e6a61203200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413e1cfc174c1683df6888bc9300f5ea591906c10ad794b79074905bff2bc972efd81a56a5223366e": "0x00000000000000000000000000000000000c7375627363616e6e6575720000000000000d407375627363616e6e657572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413e46ed7773b00617e2de5c0a266241928cf60949b2ed8069cc0485d93e4a1dd17ccfa3a28de8e32": "0x0000000000000000000000000000000000064d696e7a7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413f09528ec25d9e786f5d655731e62ff3b27a5ded3e2615c01821d00362624fcde163a2d5d62de71": "0x00000000000000000000000000000000000b4d616368696e65456c6601010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413f69efb52055873ec5b49a3746d88c99e3f3598bbc2ea84dd98ad0249dabfed2cd685b1ce636d5a": "0x000000000000000000000000000000000006475250564e0a477261706576696e65000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413fb96176f3e8aa424c8acf190cbc2c5b2d9bc0df22d2cf0472ab02baa7ce7cb958c90e8a5b6e04b": "0x0000000000000000000000000000000000094f736b6172766c72000000186a6172616d696c6c6f2e766c7240676d61696c2e636f6d00000f404a6172616d696c6c6f5f766c72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471413fba91067ee782aaefd2727ec65732fec6ebfc4a824345adb093436abfd5f53e0fe421c6f5cdb0b": "0x0400000000020000000000000000000000000000000006445053544b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141404625c59d62180187c76f60b8e91032091aacb1ec79764af51e796a0c962bd2f2e766e9e5ade45": "0x040000000002000000000000000000000000000000000550494d450000184070696d6574617261646f783a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714140d4d149491fcc516789770d4f032a7a6a43d03493704e8750ffd67090f8d763874d1934dc65b66": "0x000000000000000000000000000000000008446f746369747900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141440cbe3e601dca1749e34ce23a7934f79736024a100897a95873e4234e9fb64da3526a3c1cfd60f": "0x000000000000000000000000000000000004545132010d74713262656174732e636f6d01147461717561696e747140676d61696c2e636f6d00000c405461717561696e545132000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714144ce51a8d1e9d772004a0ca9db782903ecf235bda84dc084ee57ace3183dd9c52ecb1f4384a2108": "0x000000000000000000000000000000000009506f6c6b61646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714148446d6e27ad179566511e3d396022cf986a5a86d09bf77db45af3ddbae12a8bd78948072505f4a": "0x000000000000000000000000000000000009546172656b6b4d4100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714148fb0f115ad9c603c36970e4f759294ab646c7f67b040039321069951f955e3e9daae8c0df00e7b": "0x000000000000000000000000000000000006474d41373000000014676d616f71756940686f746d61696c2e636f6d00000e40476572736f6e5f416f717569000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714149ddb66d3286a35ec7afe6fbfc9947fd177ed118016e403dbc14803a0432bfaf0337e3bbc3c820b": "0x00000000000000000000000000000000000853435954414c4500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414a3752d9508a99f06ea5e92916cd4db2e18257272c868997978f28b079366197242626da7e86837": "0x0000000000000000000000000000000000134c6564676572776f6f642053747564696f7300000018667574796f756e676d6f6e657940676d61696c2e636f6d00001140776f6c666f6663727970746f73745f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414a9d939bb55ac3e6eb452fa37b17f70343b605f204004392380def7958b0743c14fee14e8feed54": "0x040000000002000000000000000000000000000000000667616d626f0000001e616264756c6b6164697269626e69647269733240676d61696c2e636f6d00000c4067616d626f3030303034000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414b749bf7b2b2249c4727ccdf094ab0897e53c8c3a9537a78109daccc48241b5b991295d7a511432": "0x0401000000020000000000000000000000000000000006444552454b0a444552454b20594f4f001c406d656368616e6963616c77617463683a6d61747269782e6f726714646572656b40707572657374616b652e636f6d00000a40646572656b796f6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414d831e44cf7b70cd800934b3567595ef527a3ba5f962f8594024a870ab4f25ed9ca51de8006e01c": "0x0000000000000000000000000000000000064454444944001868747470733a2f2f6c696e6b74722e65652f6474646964124064746469643a6d61747269782e6f72670e646f744064746469642e636f6d000007406474646964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414e7f5695bdcfeb7fca6074f8a41b2f8b52e71dcc4273c4012ebdd8701d3ced2e64332475f7b3175": "0x0000000000000000000000000000000000076b617a6b617a0101011a6b617a756b696b617a75746f31313240676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471414f43fb7c9ca8d300cf88657e8a5e5005c67c0ae58b0ea1137b817f32d30d80aba618a70b13bcc66": "0x040000000002000000000000000000000000000000000d504f4c4b414348552e434f4d00001440736f6e676875613a6d61747269782e6f72671b706f6c6b616368752e7374616b696e6740676d61696c2e636f6d00000b40706f6c6b615f636875000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141502f6b55d13fb36ae619a936ca92134102dfb470cdf8529756bf2270e661cfe322b1851f151e370": "0x0000000000000000000000000000000000035641000000000000094076615f735f7661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714150b14558bc6ee972ec748871d5079ed3d19a3bd8bb029f8b02d6ef1820fe786c703ead515b52d33": "0x0000000000000000000000000000000000094c69736f756e617300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714150dc822f025a4b3ac2306883197ed88bc2b4c27541c85b0b7754e4f8cdc6b2ca8c1d06f23eeba35": "0x0000000000000000000000000000000000104d61726b5f56616c65726576696368054d61726b00001b6d61726b76616c657265766963682e6740676d61696c2e636f6d000011404d61726b5f56616c65726576696368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714151958930b5ee93dbe40e9fb89b6a296813c638eeaa8e0cc3d04acc3edb8c55db7691da053576a32": "0x0000000000000000000000000000000000186461726b667269656e643737207c20616a756e612e696f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714151f26dae857e5e4640ee7e0735e1e7f68ce1d600f9eafbccc311cb1bb25542721dc6d6432d86971": "0x0000000000000000000000000000000000074d6172696e61074d6172696e6100001770616e7479756b68696e616d40676d61696c2e636f6d00000e4070616e7469756d6172696e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714152b5d77fe21288c1cbb9921ee063aecedec0d33588aff5943da3374e172a78395a75228e82215bb": "0x00000000000000000000000000000000000a4942502050726f787900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714152efa862046d2aea2421e1acb1f1b912f1a020979c61899f1d53e6d967760f7446b660858485a27": "0x0000000000000000000000000000000000074d616865736100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714152f5e61256c5cb31a95c3968b83520b8e43f82edb0f050b1ce7281873a93bf9c0798efd50f5c41a": "0x040100000002000000000000000000000000000000001243727970746f6c61622e4e6574776f726b1243727970746f4c61622e4e6574776f726b1e68747470733a2f2f7777772e63727970746f6c61622e6e6574776f726b144079616f6873696e3a6d61747269782e6f72671568694063727970746f6c61622e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714155ac70cb4838b627acd5cd13cdbaebd17c3118f06484e10d23fa25554b5da3e5b088c25f757e737": "0x0000000000000000000000000000000000074459443433420c44656769204475646165761b68747470733a2f2f747769747465722e636f6d2f44594441454200156465676964756461657640676d61696c2e636f6d00000840445944414542000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141566fd1ee1ca92c40cf6f55eafa3e54268f4de745c8e50afdaebddde55f33a4dd19d0a93e552dc05": "0x040500000002000000000000000000000000000000000f41736875746f73682053696e67680f41736875746f73682053696e676800001b61736875746f736873696e676831304069636c6f75642e636f6d0000104041736875746f736873696e676768000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415693d619c1eaa27282a304d8c9425a79907218152427905b9e49974b64da3cfc2eddeea71958559": "0x00000000000000000000000000000000000c4465722053616d6d6c657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415712b2ff79535e5c273794ac33c95766fae2316b99e80398db94d6fb5a7ce605d729d2024bff14d": "0x00000000000000000000000000000000000748617573656e075275736c616e00000000000a4068617573656e7561000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141574c008249b324302ea6389f75ff1996c75777891c4b0464e1b50ef040fffb1e0f86bd071324d21": "0x0000000000000000000000000000000000000000000000000f405379726f74614e696b6f6c6179000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141580ba7f98ba82640a6919d7771b79bd1100c2c98d53b391faf80eefca6849ba7c55270f31163f7b": "0x000000000000000000000000000000000008417573416c65780000000000000a40417573416c657835000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415903495cbc91581406bbe4ba309d9a5347d0e04eff4f03970a9eb55f2dfd146029375cf3ce66f2e": "0x000000000000000000000000000000000008526f757374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141596b645522e66dd2c4f99c0f8272e38f7169e264234dc13a4da815517564a538382e5828f61fc28": "0x000000000000000000000000000000000009706172616c6c656c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141599a0b4e7422a9ed67f7ef8999964790cf4e6c0815b1a7015e0c55d87f9a25d692d30f54a20a976": "0x00000000000000000000000000000000000742334e4e3354000000000000094042336e6e337441000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415a1183d2b1701e754981a7d9f137487f5a99c7b9b65beb94d2bd9c7f157550334eb020164dfa27d": "0x00000000000000000000000000000000000c43727970746f4c6f7665720d5a6965642048414f55414c410000136d61696c2e7a696564407961686f6f2e667200000a405a6850616e616d65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415af92d249d5d2bd828ac4562ae8e39f5d5b11dc1025a4cafcca85bb229a393ecad83ac2d26e6a09": "0x000000000000000000000000000000000000001268747470733a2f2f317061722e636f6d2f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415c94120ac277390b621338096828389f1fcb1e0141a937060a7fcaf834c7661c0fd57acc1fd5554": "0x040000000002000000000000000000000000000000000c53554d4d45525354414b450000184073756d6d65727374616b333a6d61747269782e6f72671673756d6d65727374616b3340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415cb248f0f9af445fe56be5933800b45a21ee8e9817eae9f49099fdf4a20076718497092ed43c62b": "0x04010000000200000000000000000000000000000000064875746368114368726973204875746368696e736f6e00174068757463683a776562332e666f756e646174696f6e16636872697340776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415dcd927177e5b7aaee65bf22cdf1f98c91b6c176854d8072f1328e027d2e84d23607b517b1b9429": "0x00000000000000000000000000000000000d446567656e204c656e6e6f6e0000000000000a4044617a6c65514254000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415dd7df6ad3b6cb94457c23aeab0f27293a09da367f8b8dd0a615c19e6025a2e896d255158683851": "0x000000000000000000000000000000000008766972747567720000000000000d40766972747567726f776565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415edbcc783a17ddece01379052888c89928e0352e33dfef3078c9f6401965e0371e87ac1cbecc83a": "0x00000000000000000000000000000000000850726f776573730c49616e2070726f7765737301011963727970746f70726f776573734069636c6f75642e636f6d00000f4043727970746f50726f77657373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415eee78443792d00346ebc3380be6816f828d1d1df372c51fbe99c95a321d7510403bb98f067695e": "0x040000000002000000000000000000000000000000001450726f6d6f5465616d2056616c696461746f7200001340616c65782d6d3a6d61747269782e6f72671c706f6c6b61646f7470726f6d6f7465616d40676d61696c2e636f6d00000d4050726f6d6f5465616d5044000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471415fb3d63dadb3c7cbebc314286e78316762fc56c14d7472f22197b227cabfcc894d8a5895ca94662": "0x040000000002000000000000000000000000000000001047494749204d415354455243484546000015406769676965736d633a6d61747269782e6f7267184749474945534d434070726f746f6e6d61696c2e636f6d00001140676967695f6d617374657263686566000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714161735619834be83b8be96d986897797d117987e4368640ffdf32bc967ba7467d012136c22dca33c": "0x000000000000000000000000000000000005636c307700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714161ff3e3a856b4f6f45d6d4a8639fe14436a978b8a2e5aa3ff7e66273e765498e94c4aa29c8fd41d": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000000c7777772e6973672e64657619496e666f726d2053797374656d732047726f7570204c4c431d68747470733a2f2f7777772e6973672e6465762f706f6c6b61646f74144069676e617465763a6d61747269782e6f72670d696e666f406973672e64657600000d40696e6673797367726f7570000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141623a7cb16b84b252c01c386876d1675bc75dd5d14e83568ff4b7da0b2a3ed4e85dd5bed380ef143": "0x00000000000000000000000000000000000c43727970746f477561726401010101000011404e46545f43727970746f4775617264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416241458d0b2403010f9466b8cd5c4011f48acddbe50369262afc63c91341e75b43149f26e03c732": "0x040000000002000000000000000000000000000000000770616e7661640000134070616e7661643a6d61747269782e6f72671669616d70616e766164696d40676d61696c2e636f6d00000b4069616d70616e766164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141624238a93c8c530a242df8ab59ef53f106f818046753ef02bdf49a9d4ca25f1037ef77eb1556b00": "0x00000000000000000000000000000000000c4368616f732050616e64610c4368616f732050616e646100001e6368616f7370616e64612e73696e67756c617240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141627a7ca07c7aef778dc106e241524180b2594b639d2f0eca4d41b1eb7f9e973c253402a7cd2ed4f": "0x0000000000000000000000000000000000076d6179616b61000000156368657a696c69616e6740676d61696c2e636f6d000009406f72656b6b6969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714162d191a925aa718de943b956ea058ad55b4ec09eb895a3a9d1034bbcd9c98757d041740b39c3125": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000d4c65616465724b757361465200001740737461727461726f6c693a6d61747269782e6f7267166c657361697264726f707340676d61696c2e636f6d00000d405441525441524f4c495f53000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714163390f116bec9ccc82b9f35aa042379ed3d348d95985dcbf148e38621ffc7cdf7efbc9a03a9a729": "0x0000000000000000000000000000000000047062650000000000000e405061756c6576656e64656e35000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416446fc5f8e8b0567e982817a217352323d960736af202f8f9b69e57f213640302862798d2575031": "0x040100000002000000000000000000000000000000000c7a6c7563686b61796161610e59756c69696120536e696879720000167a6c7563686b617961616140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714164b9c1fd02f19d330599dba50b5f3ba0b36f856a761eb3c0aee61e830d4beb448ef94b6ad92be39": "0x040000000002000000000000000000000000000000001043503238372d434c4f554457414c4b001168747470733a2f2f637030782e636f6d1640696c6c6c65667234753a6d61747269782e6f726714696c6c6c656672347540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416530c8e1e5dda93b43ec7322956d133d41e28758fc64d2da34d2888d93af64eb41f7afa26967961": "0x00000000000000000000000000000000000741727475727312417274757273205374726f67616e6f767300001941727475727374726f67616e6f7740676d61696c2e636f6d00000d40415374726f67616e6f7673000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714165d81fde4784f18e2c0bbb663dd3508bf5538c94db4505f736c8374071934ff8de4b38522620016": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714166843d53ac1c5d58a0219142b23ba0a4ad6d232fbcc3e6f0959a357d40f53ef4635714cedb24c28": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416709400d558465ddc20836f2e4b88c1858d1e3f918e7358043b4a8abcd2874e74d91d26c52eca2a": "0x0400000000020000000000000000000000000000000005476162650000194061727275646167617465733a6d6f7a696c6c612e6f7267186761627269656c40696e76617263682e6e6574776f726b00000c4054696e6b6572476162650012406172727564616761746573233239383900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714167c929df558b1f3c6d12fd424e6cef84c929c04dfe79ac7172fc84db2db0d0b607158d97cf20b38": "0x0000000000000000000000000000000000054354525000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141683ada1ddb8e9cdd8a79369cc8a25a7c8dfd684bbd27aa8545cdb458e615ad53d5ba91aa32b3729": "0x000000000000000000000000000000000008406461656c786500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141690453f12c9d5688876fc0567bacb2e5e78fe3ab4b8c711343d3d0c6a54e33bcb038dc3d542ae3e": "0x000000000000000000000000000000000017486f67204c6f72647a204e46542054726561737572790c4b75726f2043727970746f117777772e686f676c6f72647a2e636f6d000000000a40486f674c6f72647a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141693037ad1bbc4c910eff714e067c3037940f23485a42500956a5997bf5a0e6d80285a165ea7ff72": "0x000000000000000000000000000000000009737567617275666300000013737567617275666340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416a09d0fe8fce61c09a7a5c8cf9ac932cc4a84b295319371769b54a19d6dae4b0b92778133a99b77": "0x040100000002000000000000000000000000000000001b444f542056616c696461746f7220416c6c69616e63652044414f001b68747470733a2f2f646f7476616c696461746f72732e6f72672f1440706d656e73696b3a6d61747269782e6f72671b646f74616c6c69616e63654070726f746f6e6d61696c2e636f6d00001040444f5456616c416c6c69616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416b87c95a1b585d36a98646b16346b02b1be34f9274ff4a42b76521796aefe30fd12bab2e5aafd18": "0x000000000000000000000000000000000003572e0000000000000b406e6f6d616e6f736565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416bb7ddd33f15b4828bcee6bb03eccb17bdda4e9ae32a520be410dd8e99c23145c067f93bb342e16": "0x0000000000000000000000000000000000104a6f686e2044656172626f75726e6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471416e8fafb94c43111fa6520668dd6ae84ebb91735e7e5086a16873a11256c58d4a2609e69b171974b": "0x0000000000000000000000000000000000075279616e2056125279616e2076616e2064656e20426572672068747470733a2f2f6175646975732e636f2f7279616e766f6666696369616c01177279616e766d7573696340686f746d61696c2e636f6d00000f405279616e766f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714171684044d2e7dcc72544d5b200e2e791aa6afa994b8bfbcfc51ebe00ad850a01a9977353a79d527": "0x0000000000000000000000000000000000054c6554690000001056767431393836406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714171ca88a3597ca4a1097c82198eca584e8d9bedca6a5ffc1f1eac3c1fb91d0ef4ef313b842b04c3f": "0x040400000002000000000000000000000000000000000b50726963656c6f676963000000196e656875656c6e72616964616e6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714172675ad2d8df76c947c59725bff412592b6c1ea91e7b356bbaa8dc7412834bfb2a4c81c069e810e": "0x0000000000000000000000000000000000184d61676963616c2041727469666163747320546f77657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714172c6fa97a3aa682e494cd7bf392e1b283b46af06353294fc463b52fd5ff8a3655ef7fa57ae82738": "0x0000000000000000000000000000000000084d6174696c64610000000000000e40547275654d6174696c646132000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714172f5474abcf5643a8b5707defe6889dc178861ea7b68861fd0ab5427b54119950e6788afe1cad2f": "0x0400000000020000000000000000000000000000000006596172696b00001740796172696b736c6f766f3a6d61747269782e6f726717596172696b736c6f766f406f75746c6f6f6b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141733b5dcae3127ad6c8c82eae6fd28b35a4f5dcac9f1abd1ddc48f2558995de75647a5d628221b4d": "0x040000000002000000000000000000000000000000000a486164657241726365000013406172636530353a6d61747269782e6f7267156a6f656c31306172636540676d61696c2e636f6d00000c40617263655f6861646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141734c607245624b99429cd7476ba80dd82059e739251a8700e975927f18aea27455223e0155a8b34": "0x0000000000000000000000000000000000044d5853044d58531868747470733a2f2f617263686976657273652e6172742f000000000d405f56756c6e337261626c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714173c712e406fc7a20a54e1448806b2c0cbdfd5da73198f12554bc972045fc9dd3f2e22b6c5a97c1d": "0x040400000002000000000000000000000000000000000a4665646553616d6d790000001853616d6d796638354070726f746f6e6d61696c2e636f6d00001140466564657269636f53616d6d617233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141753ca6a40031261f68651982a6ea4d1308c93fcf09afe6715991f38e750d577f2a264a50a44ce2b": "0x000000000000000000000000000000000005496e5f4b04696e6b127777772e6c696d696e616c6974792e636e000d726d726b40696e6b782e636300000840696e6b786363000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714175f30d1aa274e0cc6017764e7f85421a0fd04dd3c2b916609ac77049eec9d33178dc51ea1d03b5e": "0x00000000000000000000000000000000000d4d6f6f736520506c616e65740a42616c692047616e670000176d6f6f73652e706c616e6574407961686f6f2e636f6d000010406d6f6f7365706c616e65744e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141768730a1a57b3f1621c276f370bf87cd2a2f783b068d77f5cfa93e40aadee1467eea589ae000624": "0x04010000000200000000000000000000000000000000096b736d6368616f73000000136b736d6368616f7340676d61696c2e636f6d00000a406b736d6368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714176ef9e475846411e84348ac16a3cb2d199bd5cac4e10f3e304428552c44203ed54919b04e80af0e": "0x0000000000000000000000000000000000075265706c76790641727475720000147265706c76796b736d40676d61696c2e636f6d00000d407265706c76796879706572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714177d87d70120c0c15a9e357de87525b67cf9ed1d0f06a15a6363665ca1c9f43ff527c87c0945597c": "0x04000000000200000000000000000000000000000000114341504954414c4e4f4445532e434f4d000000126a6b656974683440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417933400a0288c12e486d93536b8055694c790badd03ad1c868ce5a6624740dfddad1d30e4e60735": "0x00000000000000000000000000000000000b4a4a204d6972616e64611d4a75616e204a6f73c3a9204d6972616e64612064656c20536f6c61720d6a6a6d6972616e64612e6964000000000b406a6a6d6972616e6461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714179dd96996e1932802e9b1c0fa28781e31ace481a848fe28de05f52d5b4c3889714eddbf1f411974": "0x0000000000000000000000000000000000104c657069646f70746572616e417274002068747470733a2f2f6c657069646f70746572616e732e6769746875622e696f0000000011404c657069646f70746572616e417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417d1a13d5f1f6edf700e71acb30246769cfcd04fdecb96b35bfaa74a629a6515c0031043582d0323": "0x0000000000000000000000000000000000084d4f4d5f484b4f00000013646f6b746f725f31323340756b722e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417e2bd7d0c1ac830dc147d01e94744113a08f1eff356f9a55fa0fee362936cead0d0238e3f395356": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417e4668fc5316ca9661a725c195aef6d9c12fea11f866cb0ea649ee958ddb2de88b4e561295d674d": "0x00000000000000000000000000000000001253656e73656920436f6e74726f6c6c657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417ea820fcdf6ef6efc6a2f393e7206dbccb882cc74dbc1e96a0d678b4990ad768f6e0bcdf3951733": "0x0000000000000000000000000000000000094a75616e6d6130780000000000000a404a75616e6d613078000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417f2428f049676136029b5b2d1d0ff3a0a4aed8721f480386c8c866d79d86386e5780a6454cd7f24": "0x04050000000100000000000000000000000000000000000000000000000000000000000000000a5f65636172646f356f104564756172646f20436172646f736f00001a65636172646f356f406b7573616d69676f732e6f6e6c696e6500000a4065636172646f356f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471417f938a8129122a8284492a0069965cc3f671d9e4d583cdee2bf11356546da5fd6a0e0c19f50f93f": "0x00000000000000000000000000000000000641726173680000000000000c4061726173686472653231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714180b27ec3ca0969990c85597a7a30b57bc3c2a76ea47c370d708dc8879ecbd51c7997ee88feb2576": "0x00000000000000000000000000000000000b4c6f737420536f756c73010d6c6f7374736f756c732e696f0111646965406c6f7374736f756c732e696f000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714180fd664cccfede652408fc260667fc591756cebc976059023dc79231650ad542fa0af5f836a2c74": "0x000000000000000000000000000000000006436f636b73001568747470733a2f2f436f636b734e46542e636f6d000000000a40436f636b734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714181824b302aefc4e54eea4ff693f65e8c7e7804593d04a14abcdd1af82a3a4671ff17fbdb8f03873": "0x0000000000000000000000000000000000114b4e524420636c75622073747564696f114b4e524420636c75622073747564696f0000154b6e726473747564696f40676d61696c2e636f6d000011404b6e7264636c756273747564696f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714181b85c49f4a19a78e8d9c0952b54c45d0483df33c8fa020079cd1787a6e2c5f7425bde850058524": "0x040000000002000000000000000000000000000000000e3136384e6f64652d417269657300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141857664d3a630f31ac4e247ed1b3e51a17ab049447b706dd7e9d0e3735ef7e62e155d006cbc0a846": "0x0401000000020000000000000000000000000000000009736179615f6f72670d5175616c697479436f696e730000197175616c697479636f696e73383640676d61696c2e636f6d00000f405175616c69747943727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418871df8131a10a56041e8f550869197a24ed9e968eae648692cde7bbc04077114639c249cc0a043": "0x04000000000200000000000000000000000000000000074875626e65740000001461756b6572696e636140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418a693a77c144adf0cfe5be1f2fa7957855cdeb45af84f6598c581c13644650468d56d162580062f": "0x000000000000000000000000000000000007446174446f74001468747470733a2f2f646174646f742e6f72672f00166e696e616272657a6e696b40676d61696c2e636f6d00001f68747470733a2f2f747769747465722e636f6d2f646174646f746f72672f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418b39c8e20e6adbea2c727e5b643684209178c8b6ec45b5ad4567edbe8ea5bd14f2e87ca853dbe39": "0x00000000000000000000000000000000000a4a616d65734c696e6b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418b47e3024d66dfe628f36dddf8cdb0242104a2531e7d3efd4860a9a4633be69aaf30f63ccb25a5e": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000000b537769737320426f6e640000001c7377697373626f6e64706f6c6b61646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418b666b3bc75a17480947c3d3093c4b634138253abe071bdc1086af52ac8aae1afe79a7b60bdb030": "0x00000000000000000000000000000000000c524d524b204576656e747300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418c421afc6f1c1d600f41077d32f48fd9bb2ad2561fbb6cecd1f19a99f68a50838619534436ce342": "0x00000000000000000000000000000000000741757374696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418c42cb719c881dd6ed537e76f1ef68764d7544cd7a8be19cbaba2ef8af181090d281d80105fd963": "0x040000000002000000000000000000000000000000000e4c4155524f2020e298aeefb88f000000156c6175726f677269706140676d61696c2e636f6d00000c406c6175726f6772697061000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418e1b02fb972087a40c6e021d4d80b9b38d850b1c5334ea88b2bcc148d07e83f5be1b45b8ceb3740": "0x00000000000000000000000000000000000e6b7573616d61536f63696574790753657267696f000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418e56cb66eec57a80acc4b263efe14a089124745b4ae3ccf89eefb0cda261e8b876a7464120d634c": "0x0000000000000000000000000000000000144e5249207369646520696e766573746d656e74044e5249010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418e9b69f585d7a7d3c10da0654ed968b149f27cf9db0203337c79b6d86f6741f156598fb7699ab78": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000074c6179657258000013406c61796572783a6d61747269782e6f726714696e666f406c61796572782e6e6574776f726b00000f404c61796572586e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418f0062e466404f0976ce4203c844a11164d1b3f8342ad16a4cc5d99ac8eaae5cd74f4b1cc68c764": "0x04020000000200000000000000000000000000000000085355425343414e085355425343414e1868747470733a2f2f7777772e7375627363616e2e696f2f14407375627363616e3a6d61747269782e6f72671168656c6c6f407375627363616e2e696f00000c407375627363616e5f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471418fa2b57a84d2e6d28d64ebe3a8db9cf3e59929c85a4a049fdea156a9c6df6e94c34bfc08d104f35": "0x000000000000000000000000000000000013414c49434941204b5553414d41204341534100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419099c64f6b6cb0284aea4a8a382252eaef972d54ddce03f274004d28fb542d41d9dc2d1789c175d": "0x040000000003000000000000000000000000000000001b4b534d202d20446f7473546f4c696e6573204d756c74697369671b4b534d202d20446f7473546f4c696e6573204d756c7469736967000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419411887ef1bc949ca4a9b2c4e29603522c99d328c25a962c45aaac963fe90a916c02dce24404f09": "0x00000000000000000000000000000000000c204d616f20736e61696c7308417368204c656500000000000c4063675f6173685f6c6565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419522f0465b284216cb2a6e7b4c6451a1a1fcf05a4545dfbda0215f15ad77851be9f7f7e94171e6c": "0x0000000000000000000000000000000000094755535f5441564f000000126775737461766f4074656d706c6f2e6363000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714195e7803308f4eaf7e5f11c88bb727fe14d78f2196451ee57bfe065be7056e4328a3ea68a4139716": "0x00000000000000000000000000000000001050737963686564656c696320417274000000000000104050737963686564656c6963323939000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714197cc6b330ccc49f1cd0839b944fa3be33e09d4248cff45f9ba0c69b3c4063534bbc891026946477": "0x0000000000000000000000000000000000000000000000000b40426c75654775697461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419818e7a5e77f11fce81499c6c1257670571c97382c0301d19122da7168495a09546b7e53b28db4a": "0x04000000000200000000000000000000000000000000064d61726b6f000017407461636f747572746c653a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141984b2e10bc954a21c7a70feac4745c20ffb33960e4b64f9a154ed22fb58fec6ed0a0db885046869": "0x0000000000000000000000000000000000087564697669616e087564697669616e0000167564697669616e7465636840676d61696c2e636f6d000010407564697669616e5f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714199500833949f719f60db3c614a6d05747e20325a2dbdd4e5551c19964410b4f4c669dda1e82f97a": "0x04040000000200000000000000000000000000000000084a6f686e2057750000164068696c646f6c6672783a6d61747269782e6f7267126a6f686e406c6974656e7472792e636f6d00000c40426c61636b33546f6675000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141996041f72713a580a1e687a718e1ee0ce04385054cd2b23b8f73e0a73b5ba8ce0bba59bed388178": "0x00000000000000000000000000000000000456697408566974616c6969000016766974616c696b3236393840676d61696c2e636f6d00000c40766974616c7567617a7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714199f24e2487e567b321ec507203650141d2ec630b967b76ec45dd53d852b9cb25f220dd3a3fa2e51": "0x04000000000200000000000000000000000000000000084e4f564f534942000014406e6f766f7369623a6d61747269782e6f7267176e6f766f736962726672757340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419caab1fd4cdabfaf287534dd5ead6c0247a1b0d3ada5588e578602c2ed64caa6f6fc2a5efee6f23": "0x040000000002000000000000000000000000000000000d4272696c6c69616e74696e65000000156461726b6d697361343340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419cdaeb61f1cf1fb9aaa22e75104164e85637433e174dfeed603a9aefdebdcca5d27ea2a445c1e72": "0x00000000000000000000000000000000001054484520415045204f46204e2053541054484520415045204f46204e2053540000167a6163687a69676779393340676d61696c2e636f6d00000d405468654170656f664e5374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419cffb91b0e9f1d9e2131969a7a7e3fb17cfabeaaf24e4ffd9648275a675007df661d81594b3e05e": "0x0000000000000000000000000000000000084d72526567616c145265697a612047616c6968205065726d6164690101010000104070616c6f6d61636172626f383032000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419e56ebac4e0e2b6deef1b2ff187a7da287e1bb52d607937e42d625fc973d4cd06438639d70bad4a": "0x040000000002000000000000000000000000000000000c424c4f434b20414547495300001840626c6f636b5f61656769733a6d61747269782e6f726717626c6f636b2e65676973383040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419edb33b4c8af5aeaa738e7a216d2c1ce1428e0a27d92d13c04226dcc6b7a7b19db8f5defaa41a64": "0x0000000000000000000000000000000000066b752d6b750000001369722e627579616e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471419f3c2d4255caa6f62728347d414dc13c2cc74cd0d13e817efd069147654f1ffbcfc90b34e1e877c": "0x0000000000000000000000000000000000104765745f526963686172645f536f6e1143617365792052696368617264736f6e1968747470733a2f2f696e76617263682e6e6574776f726b2f001d436173657972696368617264736f6e34353040676d61696c2e636f6d000011404765745f526963686172645f536f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a163f442e4b2bd9aa4852c7108621b0eb5f5f8f8cea3234047089a41e843aec51548bed8135dd5e": "0x000000000000000000000000000000000005546f70650000001574626c61636b363940686f746d61696c2e636f6d00000b40647574776f7272656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a3b45ae59c7404966b69f1a4704f62fe379ce2ff60a139520330dfb53ab5fb94455c928fae88403": "0x0000000000000000000000000000000000054d61696b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a3e1d1d8b70566f4ccb039d696dc732bd51d48022d1cdf4d8efffa839025086962614436c01ff25": "0x00000000000000000000000000000000000673703463330000001c63727970746f7072696573744070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a67626b57e204fcd4a31711fb281fc5ed03fd717e4528ac92faf96c204eedd0d6243c144cc7e067": "0x00000000000000000000000000000000001142656e6a6f6e692052696761746f6e6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a6a978ce3d0119272e18096821e06203efc1c77555b2776299b24b3c73602dfd5bcc6690781a12b": "0x0000000000000000000000000000000000074b75706570650000000000000c406b75706570655f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a80421515da8bfffcc72d3d698e28a48179a368defd26f420b7dbb123b91405b03ae150f0c18069": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30340e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a8ac12411fafdb1ccd85718c89027a619892e7abba120a79ed4450f4b782f59cce83ceac03a864a": "0x00000000000000000000000000000000000d5265686162204b7573616d6100000018746174746f6f6973742e65746840676d61696c2e636f6d00000d4052656861624b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a8d88fdf65d76e7fefee61c97340537e49fdf7be4ebb5e6f16b2a30e3b8cc54c96f703353e0d270": "0x0000000000000000000000000000000000055465636806666c6f6f72000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141a8ff977452cfabf1666ca0ab5164b168be0188697042111e9185ae90c13d4a6c197c7209338a34b": "0x0000000000000000000000000000000000065a6571756900000000000008405a657173696c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141ab9ea3b498f5eb6424bcc780141fed6ef6cf2d08091a1a98055bd04d7c10b9007d04894b520d729": "0x00000000000000000000000000000000000f53686f776d65646163727970746f010101010000114053686f776d65646163727970746f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141ac1fbed207ef96bd640e992a6d2d245f67a7307f6fb14a4d0481284217b99444dc9b6c9cb3f6844": "0x00000000000000000000000000000000000d4a6f616e4b696e67f09fa4b401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141af418c70ecd35e54e4ef936dae8a5cc6cdb24ab8022a7cd037e618d7bedaa0ea669610ba5e0e07c": "0x00000000000000000000000000000000000742727568686801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b2d52234edc009738f45bd8f6341dac4486eedaf00f2357cd19b8d4b8f0271c7340d56fe02bca72": "0x040000000002000000000000000000000000000000000c53746f726d5370697269740000001b6d696c64726564616e65796d6579657240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b2f4ad5ff2cc79f808b67e6130479626822fdab4428ed964bdf693a1117c2423fd1bd5a1ac57a2b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b3451eaa48abc21fe7ebc934f2a7d948b99c431a8fd8a7d79b072ed207de36a980c95e45390442c": "0x00000000000000000000000000000000000673616e696b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b59abca638b56cdac646de777448f2e8286434406f2491c335604874953bb2276c068be20838222": "0x00000000000000000000000000000000000a4b7573616d2741727400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b8ed26348cab57d4eedde4b28175a6f6f119e646dfd4e47fde33e63409bb06e1f33b1217245fa2e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141b9caf038b0533985ef5ac84c374d36cf366dd2bee433b8e98b205b9e3abba931f9131bfed3df862": "0x00000000000000000000000000000000000b526164696f4b6e69666500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bae1c6e2aeffc6736e5e3c157d3d1fe30f47d4317fd8f984ac02d891d3f15b18e49fa6de5ed6123": "0x00000000000000000000000000000000000943617074544b313300000014456e646572544b313340676d61696c2e636f6d00000a4043617074544b3133000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bbd03cd3ab6347c6817038f23e3b1e7d91f641929205495b7be633fc2247d0bcc5a6f9709a8f82d": "0x00000000000000000000000000000000000bf09f9088e2808de2ac9b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bcae011029977921b0fa0b1a8e6d3ca06224ada945bd41785e55822a36102e48d584ddbb03e9573": "0x0401000000020000000000000000000000000000000009506f6c6b61424f54001c68747470733a2f2f6769746c61622e636f6d2f506f6c6b61626f74001b63686576646f722b706f6c6b61626f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bcec27087365f75b241c5dcdd41f564d5ffbc53b8936742796f1d0ac688e42c76233281183de826": "0x00000000000000000000000000000000000a6c616e64736c6964650000000000000e407370726f62696e736f6e3935000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bd7316875d7fcf8a0340d617b2e5fecf5813d12bf441eb025f610edf738af8f79a98a9e168f690d": "0x040000000002000000000000000000000000000000000b54616977616e203030310000144079616f6873696e3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bd93ac250c3d818068678e139a4ee538b249b95483d330fae73b3cdb1bcf98394341448e2254c19": "0x000000000000000000000000000000000006415045203204496f6e00001466657261726938333940676d61696c2e636f6d00000d4050756e6b324d6f6e6b6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141be2a3fab16ae5e58429c11f2ff4fc700087c7fdad402d6e97c6df5e73988c3a36c2b6fde7daee21": "0x040100000002000000000000000000000000000000000c5a4b56616c696461746f72000011406172726f3a6d61747269782e6f72671668656c6c6f407a6b76616c696461746f722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141be91660cfdb5962765d8a5b7f3b10122cf3e3e010bd993eb2f61b47e306fe7cefc8b1fecf6ca579": "0x00000000000000000000000000000000000c6a616b6572756d626c65730000000000000d406a616b6572756d626c6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141bf7451ef7153ca24cd019a2da5b645d6477d1c0237c7c8c36c7bf692e8b89d12a5858f97396194f": "0x04000000000200000000000000000000000000000000074175726f7261000018407374616b656175726f72613a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c018fecf61bedd2f7034438a748412760539f824f38f3f9ecbf77ced8716de97c5ade5d2444c8c3": "0x00000000000000000000000000000000000d4a61636b20456e74726f7079001968747470733a2f2f6a61636b656e74726f70792e636f6d2f18406a61636b656e74726f70793a6d61747269782e6f7267197468656a61636b656e74726f707940676d61696c2e636f6d00000e406a61636b5f656e74726f7079000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c2d8deb6a6e3afd008cb31b41ba9432b9bbfb2928d7f18dd71606168df3130d56406ccb4e1d1514": "0x0000000000000000000000000000000000085250565f4e4654001472617269626c652e636f6d2f7270765f6e667400126e66742e72707640676d61696c2e636f6d000009405250565f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c41a9e87e8a611f3667dba518c61e944f337affedc80902c018f24038d71bd055b4a591b783e351": "0x000000000000000000000000000000000008597564683336300000001579756468697368333630407961686f6f2e636f6d0000094059756468333630000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c41dc4bdfec08cd34cd97eea8d7958109c6db5e35eb407390555d9d07313768c374358cda816412": "0x000000000000000000000000000000000004434150000000000000094073756d5f636170000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c445a00466b4840ee56cfc4d1c1d71960386cd613829467a547ff9e30e060f95291378188c5d21a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c60a329d8935ce844cacfd17802a80e37f5db9ef661010285b5bd3c52530edcce377b2188912a36": "0x0000000000000000000000000000000000046b736d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c62d323cbfdb49f6c80b666f924d2789063014747b0b9f68ba2944a5a837ed43b01cbfc7f626230": "0x0000000000000000000000000000000000074d617269616e114d617269616e6f20426572746f6c657a000000000011406d617269616e6f626572746f6c657a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c7999ba22fd7e800682ab4f191b4213a69ab58265de100201a6589461006c4c415f253612895c65": "0x00000000000000000000000000000000000743424e4b4b540743424e4b4b540000000000084043424e4b4b54000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c8477920524dc7b0ea98f531883490cdf295130f08044ec2a2db498f07b8005194a96ff561fd82d": "0x0000000000000000000000000000000000135468652046757475726973746520326b32310000000000000d4043726f75744d6963686f75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141c8e5b0e240c90b788faa93b49dc999c0d466cd7f50fcd6f20f31bdd90aa6dc74d082de84763c43e": "0x000000000000000000000000000000000009417175617269756d09626c756520736561000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141cac1a7ef3f230dafe5958a79fa0df10dd6462aa2bff168669b1254d53d22e435e0190f8736db843": "0x00000000000000000000000000000000000753746f726d7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141cc61414be64fa4946781375b828cd1e774103d484f3c54877b8e88d9689db40ac0e3285fdde4b05": "0x00000000000000000000000000000000000a4b696420446972747900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141cdb2accf576d950527361b149506f93445192fa012f9118b4ecf0db2a1570c7cf8a4104db9e7758": "0x00000000000000000000000000000000000552756479105275647920436f7272616465747469001640726366726f6d636c653a6d61747269782e6f72671a72756479636f72726164657474693440676d61696c2e636f6d00000b40524346726f6d434c45000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d06728f5cf68e4a96815bbe365675730b16ac7f3d50224673ac974f548ead737ef65e6d6a51c965": "0x04000000000200000000000000000000000000000000094369707269616e69000015406369707269616e693a6d61747269782e6f726719746865406369707269616e6961636f62657363752e636f6d0000094043697072694941000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d2126e97da297743a969caac23093c1575d9a76f274406e59f2b1422f52930924b47ea87e641960": "0x00000000000000000000000000000000000b54657874437572736f720c5465787420437572736f72147777772e74657874637572736f722e696e666f0015746578744074657874637572736f722e696e666f00000c4074657874637572736f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d235a8aff868b2764038661dba05e6560cd16e0e7f6a3c6aade4438b3206c656b198c447f8a7a7e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d2375e335e2ffe0c000439b3c05aee26b38c1116874efa9e7cd6cb73633c9aece8287d79ca84927": "0x00000000000000000000000000000000000a43726167204861636b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d2acfefd1a8740906d588674d7859e56ed1ddcd2e5bde1d56ae61294b842a2ede11f7cab494771a": "0x0400000000020000000000000000000000000000000014474f4245524e414e5a4120504f4c4b41444f5400000019676f6265726e616e7a612e646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d31100cfcfa2db62c01c4cef5058330f7f9641903c18f4faadfaf6f7756eee49d27b9ed38cce66c": "0x04000000000200000000000000000000000000000000067a6c617461000016407a6c6174612d6b6d763a6d61747269782e6f7267147a6c6174612d6b6d764079616e6465782e727500000a407a6c6174616b6d76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d3a4b2bf76f654ecac24813f1c9e61fc9cc2500bf4eb8b8d9af7548714cb0b1c1ba4785b46bb37f": "0x000000000000000000000000000000000007486f686f686f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d462405631809fa2aaa5497ddea7e16416a7e7cd668565cf10f67763d0a9143dbbbc1104cb19817": "0x00000000000000000000000000000000000a44756d625f42656c6c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d4d1c3fe955b6e940c6413e8373b0e702dd0e04ecf51a6c785e76dd910b5907512969f3cdb9702a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d4f0e009a9528d0f2695f946087950cf6d6082c331294f31d23ae54ab2dfc3739fb4def83676e23": "0x0000000000000000000000000000000000054d65746100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d6bdd6d8cc672c232ad1a9e5ecaa5b5f3b88bf41e24eee2591dfd5d3a53d9c09a73bac517f28a58": "0x0000000000000000000000000000000000066b7562657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d7259e4eafa026b88e89854ec5f225c9a3b8889d4b1afc0cf6cf473d4265a96463c08cccf38905b": "0x0400000000020000000000000000000000000000000008316b766e6f6465000013406461766534343a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d77b5b5e1a11bfd62a79f3b924342c4f634d8ebdf77f50ac051d41387a72d22f2f38155762c125f": "0x040000000002000000000000000000000000000000000a4c6567696f6a757665000000146c6567696f6a75766540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d7c0832ef85bb40ac8861de74cdf782c8261d2c36d27cdec982688f6d03311e53cfd65402211856": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d9735b2d16e21311c11f14c57d6a787a9a317691e40481a394591b7af72e22407016b498737ae38": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d9986fc3246a26b4aa5e51e6ca0b24646f378404ad16b7f1fe9e0ec864147011db66265813fa02e": "0x000000000000000000000000000000000012566c6164204973204c6f766520f09f92950000000000000b404372797074756c6c6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141d9e0e4a748d5f2cc805058130871797c503fd545ffeb106c470953d95f88c6814bf2ecbc0c9986f": "0x00000000000000000000000000000000000c42756773794d61726b32320000001662756773796d61726b323240676d61696c2e636f6d00000d4042756773794d61726b3232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141da8bd150ad49b557886c5a642b89daceb2744feb76cf20cc06603fa2a652cc8be5e5e155f57e33f": "0x00000000000000000000000000000000000c61657468657263726973700000000000000d406165746865726372697370000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141dd245eb6059ff64e29c5c2a82d191bab4e3d4a573d0e5743b19cd8ccd2b4a978bdc1784d5af1c7b": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33320f62696e616e63655f6b736d5f3332000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141ddfd86abf974afab47109f622b8dbf0bbcf84277b807130c085082546669b0d15c739843e09c109": "0x04010000000200000000000000000000000000000000086b796f73616d6108626fe288826869001440626f646869736d3a6d61747269782e6f726715626f3668694070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141de11c43602580500e15e7844eae688a5a8d5bb2239878e14e49c73534a0a3fe258e0869e9ed6727": "0x00000000000000000000000000000000000f506f65706c6527732048616e642001010101000010406c616d61696e6475706575706c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141df3fc920874707bdc5d17441dab98682c0b6d8819768ce2aa4674fcb1ad68f609b7c620ad45ba4b": "0x000000000000000000000000000000000009706974696d696e6900000019706974696d696e692e646562756740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141df6123c2d60f917b2471fd517548674e0710bcdc4961033f6240c4c5c94cfbe38cd032a493c5e74": "0x00000000000000000000000000000000000a4c6f72696c6164794f0000000000000b404c6f72696c6164794f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141dfc2330c656d5231a890513e2c8835cfc12813248806f24436f757f0dbcd8696a7f56bfa2c3f17f": "0x040000000002000000000000000000000000000000000a4541524e5354415348001a68747470733a2f2f7777772e6561726e73746173682e636f6d16406561726e73746173683a6d61747269782e6f7267146561726e737461736840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141dff89fb25833ea0a616a89a50c3a144a2af6202dd4550d067dce77c8775cf713cc6e34b93a00b45": "0x00000000000000000000000000000000000b417274656c6c656f757301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e0159188b70dcf6941f8d212a457540ff86a877ea367c1a74c43a58e7d3382a987ca12cae0f7524": "0x000000000000000000000000000000000011446174205068756e6b79205661756c740f546865205068756e6b79204f6e65137777772e6c75636b796672696461792e696f00147279616e406c75636b796672696461792e696f00000c407468657068756e6b7931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e023a512a423fadae0d9af68f58dde7e3279b2dc61e51c29509b10e29605dbb6df2fcddd083ad22": "0x000000000000000000000000000000000009776572747971323000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e1bdb5f0bc06203e8072c43338f9819be9bce372ed1afd9e945d4c827d4e3e02cfb7b32122df764": "0x04000000000200000000000000000000000000000000094e616b6570656c6f0000001862617279636865762e64696d614079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e402acb5899dbe10ccbbc7077de681489e3548876c3106219899576c0b9e3a9abfc93559449da61": "0x0400000000020000000000000000000000000000000008476f6e74696a6f00001740676f6e74616a6f6e65733a6d61747269782e6f72671c6172747572676f6e74696a6f4070726f746f6e6d61696c2e636f6d00000e406172747572676f6e74696a6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e495b9d3175bbcf109e87a012b2754d0b23501fe1fa775db374927f09c228f07948f81ad84bf617": "0x040100000002000000000000000000000000000000000e5061756c2057696c6c69616d73105061756c20502057696c6c69616d7311687474703a2f2f7061756c772e74656c13407061756c70773a6d61747269782e6f7267147061756c40626c6f636b736d697468732e636f00000f407061756c7077696c6c69616d73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e517fa60da3439f60fee6404e47fe7fc88c2df8f2ccbafcc2bb76501c0f082cedac9586cb7cfe3a": "0x00000000000000000000000000000000000b53706163654d696461730101011961626f6761646f7363726970746f40676d61696c2e636f6d0000104044616e69656c3636363332353734000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e5ed2f050989443765e6df27b038557938e92d267e4d3e9a7826f3e1c628443b72c54ccb2530f7b": "0x00000000000000000000000000000000000c4269742e436f756e74727900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e6c109558238bfd8cf8184ab08b4b112452b90cfbe958b9573939bd0dfd0dc78b77f3248f28c025": "0x0000000000000000000000000000000000000000000000000c4050617261436861696e7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e76c389661c3a415cbf9588da096c69d2c6f3cdedbbf146d31f0f43f39d251d09f9b368aad1a852": "0x0000000000000000000000000000000000076c696267656e104c6962726172792047656e657369731368747470733a2f2f6c696267656e2e66756e0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e81c54a25bd302dc09ed6b82e56f934bddde307fd655fc512c88c9a66ab77325d6d8d804de95e0b": "0x0000000000000000000000000000000000054861687a0b4861687a2054657272791568747470733a2f2f61727672746973652e636f6d000d6861687a356440706d2e6d6500000b406861687a7465727279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e88363895c100068c4bf3ba9633b121af862532bb08432c3cd450f363e04a2862b07d50abea775c": "0x000000000000000000000000000000000005616c616e00000017776a6837363232393032313540676d61696c2e636f6d00000c40736c6976657266666f78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141e9839b3a4a537a7ee8d75dede514ed1aab7fb1db5e6a959c3ee250062aaae12d463a7b8329d1224": "0x000000000000000000000000000000000009536b79204b696e6709536b79204b696e671c68747470733a2f2f736b6d702e7375706572636173742e636f6d2f0012736b79406d6f6465726e73746f612e636f00000d40636f6e73756d6572736b79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141eed9dff4cea873e1635a4853f034ba42d82dee7d8eb4eedead8c2350de115251dbd6d4e3b65c713": "0x00000000000000000000000000000000000b4e46545f5061756c6965001d68747470733a2f2f6c696e6b74722e65652f6e66745f7061756c6965000000000c404e46545f5061756c6965000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f2628d8321b371238be8006279f7e6c45bea9c49ec6148ff405719f6b66357308246a04d8f8dc70": "0x00000000000000000000000000000000000e506f6c6b6120506f74696f6e730017687474703a2f2f706f6c6b61706f74696f6e732e696f000000000e40706f6c6b61706f74696f6e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f2feeea09705452f6dc9f6798b0673697a24cc012c6c63b2634557893f3231ac186afddbb421435": "0x0000000000000000000000000000000000000000000000000b40656c63696432303737000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f4321336da7ceadf4d95d4c5c0131969148d3a16b3d95ab3d051771d971a1955d7e745b0a3a4f16": "0x040000000002000000000000000000000000000000000e5044505f56616c696461746f7200001440706176656c64703a6d61747269782e6f726718706176656c2e627574656e6b6f407961686f6f2e636f6d00000b405061756c4241636944000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f48bf37f549334442c6245ef5eb308a001e79ad19006295ca4f647f53cf848a654986bcface4042": "0x04000000000200000000000000000000000000000000064942495a41000013406962697a61313a6d61747269782e6f72670f7265672d67616e40676d782e6465000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f4abd8814aa23d512e468b6c0ef22342134f181810fc0adc14a6aa964e9d2e8d6d89840b69b603c": "0x00000000000000000000000000000000000d53656143726561747572653100000000000011407365616372656174757265686f646c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f5112fb03b23ddef2a85c638724c62596fd6b39b96940e8469b445fe79c6416e00d055ee895f211": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f5305062ef877dbe24f4ca2f10d6a709a24b0cc692ac7be7f8d273b20301b48ad9ed4686b7fd319": "0x00000000000000000000000000000000000643495649540c4f73636172204369766974137777772e6f7363617263697669742e636f6d00156f73636172636976697440676d61696c2e636f6d00000b4061736369695f626974000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f638d3271ed7e11f246c69b8f8c849cce66563b2e98d4d92c3d310f0a71c961f52d998faf83f67e": "0x0000000000000000000000000000000000084f6479737365790000000000000e404f6479737365795f4c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141f7fe908aea4a3c53289d9f38247655a5018d093324d3fd1b9daeccca5336b69577ae6b466576b1c": "0x00000000000000000000000000000000000d414d45524943415320322e30002168747470733a2f2f747769747465722e636f6d2f416d6572696361735f325f30000000000e40416d6572696361735f325f30000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141fb2ba94e04f61c026a31499d0df85f8053df28ee11f7c0a3715892fd57a92b4edcbbfa322475a4e": "0x00000000000000000000000000000000000664696b6b7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141fcece1cdd847b0ec86205a2ca8d23217fda44d2d969447b9c02ef7949442473c2991a6e60212f04": "0x0400000000020000000000000000000000000000000009475247544e534b4d0000000000000a40677267746e736372000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141fd0382f79e2a2d7ba55c080cad203ee8e64deb867ffd6c628a36159aef2bd90e1ca99669218d566": "0x0000000000000000000000000000000000064a756c657301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141fd33ae9ac7ec1387e3301e524b5134478f3705cf85e4999ae44f8ecf7732884ae18c3480e2b9a56": "0x040000000002000000000000000000000000000000000b5374616b6520466f7274000015406770617468656c613a6d61747269782e6f726715676f75726176407374616b65666f72742e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141fded061878099ed6cbce2cc9280bff6f25382a49f2f6ae459d8c96e53e72fbb7de120955918df14": "0x00000000000000000000000000000000001042616e6e6572205468656f726973740b43686164204368616f73000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047141ff46b051efecfe4806369b4f04792b7bd1a0d8586b7aa528591ba732362e3fb3d52d7b01e741b18": "0x040000000002000000000000000000000000000000000773336b7269740000184073336b7269743a6661697279647573742e7370616365000000084073336b726974000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142018212ed22c14c0a44871a6a8764d496fe18d5f9044e3c62cee35d0b30ed9e707227bfd8a9c0711": "0x040000000002000000000000000000000000000000000b636c6f636b636861696e00001740636c6f636b636861696e3a6d61747269782e6f726717636c6f636b636861696e687140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142022778741b4653e1434dd9ad7d65aa4fd7befb0af4819a25a022402d55489fa8c290c97b38df230": "0x00000000000000000000000000000000001a456c656374726f6e69632047616d696e67204361706974616c000000000000104074686567616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420326aeae6bc2643a4c7753db70defc6fdcc8efc9c9c050207648b35b7e52213f8963b03e4f56c0c": "0x040000000002000000000000000000000000000000000a736b79657264656b6100001640736b79657264656b613a6d61747269782e6f726714736b79657264656b6140676d61696c2e636f6d00000b40736b79657264656b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714204538a0dc29db896ad41858c3abc9bce8dc8ed3b789112bad138dbf9c62472aa881c6ce1b985204": "0x00000000000000000000000000000000000c50523046495442554c4c59000000000000114050726f66697442756c6c7931303530000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142050d45992f4c9ef2652c2a0824e6d3803d9616e5499b32741fe224108363f2423e5063978885f07": "0x0000000000000000000000000000000000074b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142055e641717d8d1e567c29ba7c8504fcf16d91413a5a71f8e81c33752c743506cd26198997f48421": "0x00000000000000000000000000000000000467756100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142056c8f9b2090920dc64ebe91ae1dd904651525eb5fd91eb0abf458cb0f5986158803e0075604153": "0x040000000002000000000000000000000000000000000a546f5468654d61727300000018746f7468656d6172733230323240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142057c2e1894e9a819e92823bda563f6821bc3b7af00917608d454dfa89de101414ee0b51ac3ab57f": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000045450420000001a676572617264706c616e656c6c657340676d61696c2e636f6d00000f405072696d6572426974636f696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142067c893ca23078d2899477496b6c390ee6a83d1e533d860d1ed9d3093e9f74103185879c65de25b": "0x000000000000000000000000000000000007726f694c656f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714206b45f2fa65a57512b21d2798eeaa9401e833534b50cdc8cb63dba399374d291f223b691b35de23": "0x000000000000000000000000000000000009736861323261727400000000000011407368613232626c6f636b636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142073848901eac9089068ef7e2275c53204ce2f7fdc06eb8c5b2b7d6e67a137738dbf9708f207ff23": "0x0000000000000000000000000000000000064a77617769064a776177690101146465636f6c6a656e6540676d61696c2e636f6d00000a404172744a77617769000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714208d340a192a7ce08433eae795936e63871cbcf0410517d1dad4755f2da4a6d88c1cc1c589b8e86f": "0x0400000000020000000000000000000000000000000013535452415742455252592d5354414b494e4700001740737765657462657272793a6d61747269782e6f72671d73776565747374726177626572727933303240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714209e98ff9424a50460750d915c81e3c139cffb0418c1c712b3ed7486694f4ab51032735d4a7bc628": "0x00000000000000000000000000000000000c6b7573616d61686f6c69630000000000000d406b7573616d61686f6c6963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420a0096c7425466822f00d3001f42ca632c44bc08b5832edfc5b68f71bba9a5489e72bbf36759675": "0x0000000000000000000000000000000000134b656e6e792773204b696c6c2053686f74730c4b656e6e2053686f74747a0000156b656e6e73686f74747a40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420a09cd983d185ada625107ed5deb9bca0d319ec0614f4cec7442d7d1d834c94edb2ca33dfefa041": "0x00000000000000000000000000000000000c4e696b6b69205269786f6e124e69636f6c61204a616e65205269786f6e0000176e696b6b697269786f6e407961686f6f2e636f2e756b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420a8c6d581b4662724bd4f1c895eeef95b593114f9f5ba0abd74c95532defed6a94e56fbf4aba642": "0x00000000000000000000000000000000000a46414333205354523800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420acc90488da905fc699cbb879646f36ca046a3d26df97d1c83ed24d2a4975d823ef00ca4c94f509": "0x04010000000100204aa9d10100000000000000000000000000000000000000000000000000000c4465736372696265646f740c4465736372696265646f741d68747470733a2f2f7777772e6465736372696265646f742e636f6d2f00166465736372696265646f7440676d61696c2e636f6d00000d406465736372696265646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471420e84b09cc5488ab56025b6817d74310f334c8c7b2baa3cf708f6c1501aec104d91d951751f88643": "0x000000000000000000000000000000000007422e492e432e13736972206261736564206964656e74697479000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421101bd08c63245f043a5cddc14c4ad1fbf90999e4efe595993c71e0be149400f5f1e6b3e073050d": "0x00000000000000000000000000000000000e4a6f20706f6c2077616c6c657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142132d2b9d69b1260a8300f53d9cda28b136491a9b18b937eae584f7f08fbb6aac29e0ea38e38f864": "0x04000000000200000000000000000000000000000000104c45545241534352495054494341530000001a6c657472617363726970746963617340676d61696c2e636f6d000011404c6574726173637269707469636173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142137b4e662fa80a05a37c441df3f0fed7ddef5581ff70437b00fb071e0b09537caca8adc4354913e": "0x0000000000000000000000000000000000094e696b6f76657261135665726f6e696b61205361727661736f76611668747470733a2f2f6e696b6f766572612e78797a2f000000000a406e696b6f77657261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714214241a7a6830640485a526526a8eafc2c5705aa658cbe9c28fa11d29b0595e9117631ad7b370f61": "0x0000000000000000000000000000000000086c554f536b736d05416e6e61000000000009406c6f75736b736d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714214343ca4a50f9b586b151fa5df9e1c7f5530a1ce12aeb4957ffb6d2e15304fa6b9b5f40bb3ff31b": "0x00000000000000000000000000000000000a4e696e6a614d7a666b0e566974616c6979206c6172696e2168747470733a2f2f73696e67756c61722e6170702f73706163652f476562583600146e696e6a616d7a666b40676d61696c2e636f6d00000b404e696e6a614d7a666b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714214a284ee9e9b01cd61813f456c8f11087d572921c67afff25605aa712899d6a6b04cc42c3d2d417": "0x040000000002000000000000000000000000000000000647335251300000124067337271303a6d61747269782e6f726719673372713076616c696461746f7240676d61696c2e636f6d000007404733525130000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421545827f452a76be49cd2b1bb9e68033d664d63b4776bc51f900147cdeb6f009fffa8c1d497ae3d": "0x040100000002000000000000000000000000000000000d536f6c6f53696e67756c61720000001c736f6c6f2e73696e67756c61722e61727440676d61696c2e636f6d00000e40536f6c6f53696e67756c6172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421610a341cde1430ea466b06c8c16712d05c5f607b740a39b72f8356f175320697df6f2a73dbcc4f": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000085669746135363700000017766974616c696b647a656e6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142162588dd88d3a33aa48a9775be7af0521acefce054dc7e9e461814dc167a5cabf52aef8534d8249": "0x0000000000000000000000000000000000194c6520436f6d7465206465204d6f6e74652d43727970746f0d4d6f6e74652d43727970746f0000126d6e746372707440676d61696c2e636f6d00000e405f4d6f6e746543727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421667555f2586f1cc852bd64d95e1c2fc164ba7ee6c2cce6e87ff8cef81c60940d46f710ed712b7a": "0x04000000000200000000000000000000000000000000066b6f757469000012406b6f7574693a6d61747269782e6f72670e6b6f757469406a6b76632e6465000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714217d6680e09965aab2b62cbf89a7a9265639614f153be16189006b3c0b51cce22227f4af703c9e1b": "0x00000000000000000000000000000000000d4b7573616d6153656e646f680a416c656a616e64726f00001a616c657465636e69636f706331303740676d61696c2e636f6d00000b404b736d53656e646f68000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714219805b19867f93320fee6eafec3719729d9c5ca944da46b05443e2e8f6bf199e0011cd0e2c7e148": "0x00000000000000000000000000000000000f506865656242206f66506865656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714219c4cf4d922a8a65e6943dbb9c8cfd53377a67307290efac1aff4aa23f2862bd8640af3756f792c": "0x0000000000000000000000000000000000174b72697374656e207c20573346207c204576656e74730f4b72697374656e204ac3a46767690000186b72697374656e40776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421aad0a24a729734c0b881e2db47fb95982cd5c364b87e6cdf5a5c8a336d980156623b53815c597b": "0x0000000000000000000000000000000000054b494c4e054b696c6e1068747470733a2f2f6b696c6e2e66690010636f6e74616374406b696c6e2e666900000e404b696c6e5f66696e616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471421bd505b865a64bf380b24a4886b392ee4659b85f5605cdfab3eadce66eaadd848c37f4fde65fd06": "0x040000000002000000000000000000000000000000000c474d2050656e6775696e7300000015676d70656e6775696e7340676d61696c2e636f6d00000d40474d50656e6775696e7331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142200b6e2483bae501aaf37daa4afffeb0d84c47f52330d8293ea648e1bba5fe0e35355057e63c167": "0x040000000002000000000000000000000000000000000773656c6265720000164073656c6265725f61693a6d61747269782e6f72670e6f70734073656c6265722e6169000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714222fa12fb4681a4d0e47ff458bb2f80c4bc89a6a7bd022a555e9c1bc719726f475f8a1841428832f": "0x00000000000000000000000000000000000761706f6c6c6f084e6568656d696100124e6568656d69615f736f72616d69747375186b72616d65726e6568656d696140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714223452b8432e93285edc25673a48cda235c2d234b8cce6fc441c1f2edaca141226509d4e34443f32": "0x00000000000000000000000000000000000d50726f6a65637420495a415205495a415200001b70726f6a6563742e697a61722e6e667440676d61696c2e636f6d00000e4050726f6a6563745f495a4152000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142237b569888e1b73789b24f57aaf20f362378bb7b2e560920a5c09e18d292ae991365283fbb63d46": "0x00000000000000000000000000000000000a6b7573616d61676f6400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714223a4a6652ff6ba41ec5e682f355b27a4d5a5cc933edcdf3a4909fab848b5c36ca82c6ed9518404e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142246a94b347c9dd6d4af1aa1af17d814c5da505868f6c55d53371fdf90d774e5d61d6e02a29bde35": "0x00000000000000000000000000000000000c467453342e2e2e664653300000000000000d406b696e676d6f6f73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142246aa733317c875da16e9adb79c6c6264ff8c115577bb33b4ee54e8dc9abe25a91ca670b61bd552": "0x0000000000000000000000000000000000116d6f6e6f62726f776d616b65726d726b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422501e6d8f21e9dd5e97f331813198763da88ad2b1f5deb3f42373a93e8895c43de399aa6255da47": "0x040100000002000000000000000000000000000000000e47656e657269632d436861696e1554776f20506562626c65732056656e74757265731968747470733a2f2f67656e657269632d636861696e2e696f1a4067656e657269632d636861696e3a6d61747269782e6f726716696e666f4067656e657269632d636861696e2e696f00000f4067656e657269635f636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714226c1e0df53526ed80460dbf1dcc3ed518c81067d27eb8278a7a1abcd834ffc79dcc1c35e4a9b64e": "0x0000000000000000000000000000000000064241444552001268747470733a2f2f6261646572792e636f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142285d6ef6ff9cb66120dbd220521490559af15d7fb3b6cd95c313d06180901d2de5a54e63d9cfe22": "0x040000000002000000000000000000000000000000000f395374616b65206279203947414700001840397374616b652e396761673a6d61747269782e6f726717397374616b652e6b7573616d6140396761672e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714228f1b7216fcfd78ecbb4ad02852dc96234c83eb42528d08e17ef8e787f503caee5fa0d687d74025": "0x00000000000000000000000000000000000e416c657843617074517561636b0000000000000f40416c657843617074517561636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714229b18b3f2754f1a429599ba5f521844f2332524dec987f9cfb116a2570f83b2417184af0c74ab13": "0x0000000000000000000000000000000000064772657461001768747470733a2f2f6465636f6d3838382e7370616365000000001140526f636b657442756e6e79426f7373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714229ce4e5e00a4f0b1e6ea78e3190ac2cfde9c0041ea7a0e1f7b89d52f4a58f01f69258150b782466": "0x0400000000020000000000000000000000000000000006736e61696c00000013736e61696c407473657276696365732e6573000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422b4e5d0ac25c3f4f0221438819364133d39e26672983929d4656719d10ab15c8f974b8856daf664": "0x000000000000000000000000000000000005466972650546697265010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422c077d1ea9a54d260f2cec43064a352b55aec95917a2935c01ae5d9ddaa47d8063991d65b4b9450": "0x00000000000000000000000000000000000a46616d696c796d616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422d261d77c92c974201f968f24fc0df93fe98dab905ff103d00a9a232329bfe78c22663dbe60a12d": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422dad67368716274fa24d4027d0a467580d44b1c89896a8bc1bb9c77d1a29f555c4ba85b7241d84f": "0x0000000000000000000000000000000000095468652047616e670000001674686567616e672e6e667440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471422dc4c22ba0bc0065c05d5f192c927b30b33c85470b53474f2a736a01c3c5da905384329a430f22e": "0x000000000000000000000000000000000007446a7562726500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142305e79ce427e9ee14173ee9728c9186c8e72b474dd743f18b0169106f8d63e2973bd9563882347f": "0x00000000000000000000000000000000000968616d616b61676f0000000000000b4068616d616b61676f78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714230d1532b07653236895ad261e06f09bee24fbadb2586f4c5ef811ab95debdf1c683025e12665858": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31320f42494e414e43455f4b534d5f3132000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714231960a7d766214bac5090f086d4848d1830e5aa59349a24ccfa5dc9bbcbf97580c26371df64d904": "0x00000000000000000000000000000000000766347573743001010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142319f3e78aede826d4621034776e25cee77bb87bc6a14a8e0f74dc45ec194bfb8ce7fc5f97c42406": "0x00000000000000000000000000000000000a486f6f6b61486f6f6b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714233517e12f6d46687ef6ecff86959a7b564427a3b66d0352b3f513c990accb1a836a41322d08d311": "0x000000000000000000000000000000000005526d726b0000001a63727970746f7477696e4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142337f11734e7573816e0eeb71e92b68959e490c6e0c5dd54a61fb9faabbdfbb4fd7a6ae353dcf573": "0x00000000000000000000000000000000001653616e74612773204c6974746c652048656c70657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142340baacf03bc2b65865da029ac7366bc43ae9d19382b3a85f49d2a660fef29259f9bdd742767d0c": "0x040000000002000000000000000000000000000000000b4541524e535441534834001668747470733a2f2f6561726e73746173682e636f6d001367726f77406561726e73746173682e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142340d0950ebd480968fae6be10c90d572388d42129e074005005baf68d116a993073c5648ec78865": "0x0000000000000000000000000000000000064b414e525900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471423439dff64c47d6062f21f6587843801d599ed5855ae0ebdd2a84c822919e80cd6f12899e5088772": "0x04000000000200000000000000000000000000000000064c65676f73000012406c65676f733a6d61747269782e6f726711706f6c6b616c65676f7340706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714234aecb53dfa52ee846537d237047bc2784332bde7c2495a8ced463b2470834c989ab0221880b53e": "0x0000000000000000000000000000000000084d414347414e470000000000000a404d414347414e4778000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714235333782a45d3df229f2896c2bd6f30162c9cc0f5899432515f2cffed36a4dc6b42d48bd2b2910d": "0x00000000000000000000000000000000001044454144424c41434b434c4f56455200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714235e6cc48616ecf948df9c1a60044840351ef0fbe6b9713ee070578b26a74eb5637b06ac05505f66": "0x00000000000000000000000000000000000e537472757473656e6b6f415254074e696b69746100000000000f40537472757473656e6b6f415254000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142366851b398c75ad02f6ed445ee9bf4e2f4b4c017439de5df61f85059a05faf2d0bce28d7ae2a755": "0x0000000000000000000000000000000000055333335200127777772e736565722e65786368616e67650000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714237b203fe8adc4e71c351b39b792e67cf1251e87877511ce1d302a4048202a7a66f130324c39c171": "0x000000000000000000000000000000000008535552494b4f560000000000000940564f4b49525553000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714237b38e4959de64e265a775a6d7ba9de83f9584dafe39e8329019c1e881b4c5097048fa72d392369": "0x0000000000000000000000000000000000057272656d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714237d0c1537de97bd0cbdd520a7494178d304b7cd4d6b5ab879a78153d9e594f4900b615caefe5908": "0x0000000000000000000000000000000000175468696e6776616c6c6120496e766573746d656e747300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714237dfece766977faf655bc5071b58f4e4789e92567ede362496ffc8ef0f0d9ebc00c2ad4c57bfa7f": "0x00000000000000000000000000000000000d74776f70626c7374617368311654776f506562626c657356656e74757265732e696f00001b61616c624074776f706562626c657376656e74757265732e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142380d19831504ba65a2d8e3ab4f6b9d9e0f920d4d2b6877be7ee0b1b28c2f6a8d83751a143510b1d": "0x0400000000020000000000000000000000000000000011686f6c64706f6c6b61646f742e636f6d00001d40686f6c64706f6c6b61646f742e636f6d3a6d61747269782e6f726719737570706f727440686f6c64706f6c6b61646f742e636f6d00000e40686f6c64706f6c6b61646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714239d9993b7848d1956f5560a9a7cebbc2b81e92c3f080f384fc7bc0cb8a20484bc42cdcd423b7863": "0x040000000002000000000000000000000000000000000b5354414b455a494c4c410000154064637a6f696361733a6d61747269782e6f72671364637a6f6963617340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471423c2022a748dbc54406bfcf1fc5e75a39525555d86756e304fbc7fb4d74f49feca2f02cee457167b": "0x00000000000000000000000000000000000879696e7a68656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471423d4008003cb78a9582c6d97aa93263387550545127dd79d0bb69e0b2f792867660b8761b8551a1f": "0x040000000002000000000000000000000000000000000b4d59544849434e4f4445000018406d79746869636e6f6465733a6d61747269782e6f7267166d79746869636e6f64657340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471423dccf7b667b32e5dc399b0b033525131eac94bf1432ec9112cc69862dac20a16c3462ae8c64c017": "0x040100000002000000000000000000000000000000000e4b494c542050726f746f636f6c0d424f544c61627320476d62481068747470733a2f2f6b696c742e696f000d6b696c74406b696c742e696f00000e404b696c7470726f746f636f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471423e2879b116fb58ca6e782e566e272302b2f81d98f84a883eca8dcd86ff3c05ba0a98599fa86a516": "0x0000000000000000000000000000000000044a65680945766768656e6969010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714242a4e67e17b982ad890e8221d99486fbacc20023108a5a1411cde82171d65a531495b7a47d5bc76": "0x00000000000000000000000000000000000c757365726d6f642e6e65741447656f72676520416e67656c6f706f756c6f730c757365726d6f642e6e6574001367656f72676540757365726d6f642e6e657400000b40675f757365726d6f64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714242d0d33e8dcca4f40137e2016218754a9ff93a24dcf522a8533be538402e496929ac91f7c9e5900": "0x00000000000000000000000000000000000844656c6761646f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714243536f899777cccb892b5e5793918855e5fe7c16b78b94bcbc4bcabf6936ec3edd1c0043a026545": "0x00000000000000000000000000000000000a496d6f62696c697a650000000000000f40496d6f62696c697a655f6f6666000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714244c1487133d32acf2718a102c908ff26947b45596237f761fae16f30499dd9e9ad99370f38d490c": "0x000000000000000000000000000000000006757262656e011668747470733a2f2f757262656e2e78797a2f6172741240757262656e3a6d61747269782e6f72670f757262656e78797a40706d2e6d6500000740757262656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142465e11c805e40714487e71c1a15539cabdf996a4383b96221d6c4afb071b29e5e344c085c1cb706": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714247b27e4de021f0e443f4ac4d297be577e7db2e5ec57eabd33c10dac033e9482b33c508d1c2e6878": "0x0000000000000000000000000000000000097873616e746d616700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714247e5b51518dcd9f7ca164245d48ed5035eb6fecd7557ec58ac8869c54855c6663b8a3439960d611": "0x0401000000020000000000000000000000000000000008415245534c6162064b657269631868747470733a2f2f6172657370726f746f636f6c2e696f0015696e666f406172657370726f746f636f6c2e696f000011404172657350726f746f636f6c4c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424883d27e305ffe5f89d4c543e6cd62e62136614f7b98a423cedb9fd863584a2f4ff887259432437": "0x00000000000000000000000000000000000963796265726e657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424899ec201da1fbef4f9224c619c930a1c5d86b01cd4bd1d454809ee83031f1442fabf12355b426e": "0x00000000000000000000000000000000000a5072696e636970616c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142489e525189c647aa4e129cd956559c21c899e2b0acccb250e14a8c072d03a2cb3e4625f8c9ea171": "0x04000000000200000000000000000000000000000000094d7973746971756500001740726f62696e2e686f6f643a6d61747269782e6f72671f726f62696e2e686f6f642e76616c696461746f7240676d61696c2e636f6d000000000c726f62696e2e686f6f6f6400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714249c9b2b424049dd50d6ffaad41dc59e96f29914ae09f4f618d8d24a649ade27491dc74b09945a70": "0x00000000000000000000000000000000000e5665737065722044657369676e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424bca730e73f4adb967cf83e4ac7ec8f62925eee4b90e459522a323fbd50b5408561657562546531": "0x00000000000000000000000000000000000962726f772e7765730744616e69696c2068747470733a2f2f696e7374616772616d2e636f6d2f62726f772e7765732f001564616e2e7261626f74613131406d61696c2e727500000a4062726f775f776573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424c80eb0f73c29c48402585743ecd763fde5b8582caec19198b04ba1b6b57b86855203203ffb2b33": "0x00000000000000000000000000000000000744696d612041000000137569383766696d6340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424c849079ee8bde4921d3fe712adae750defcd81cbd13fc63226c907ec2961204617fb4620f4ba15": "0x00000000000000000000000000000000000753494c56455200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424cca5c49a0392d3a6ae3f09425544ce2f852a638e82b8a9ae49486b34583e77436984f13b824754": "0x000000000000000000000000000000000010426966726f73742046696e616e636510426966726f73742046696e616e63651868747470733a2f2f626966726f73742e66696e616e636500166b6569746840626966726f73742e66696e616e636500001140626966726f73745f66696e616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424e34420f18ed441e8fe2f9cd7b9e68790ca9ffbc328cf496162907a526bc335cb51cb5118f4c43f": "0x00000000000000000000000000000000000761656d6f6e6b000000000000094061656d6f6e6b31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424e872fcdd80ae390229fda198aa937ca03036032b9b1680acf37d6366ac18a5133d414e7448890d": "0x040000000002000000000000000000000000000000000d4775737379204b7573616d610000001667757373796c616d626f7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424f00986851bb8956af63165579ca558359619fe514fd5b89adcaa5710bd25ebcc789c2fa7602270": "0x0000000000000000000000000000000000047975750000000000000d40365f73656e73655f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424f992f424aeeefd1455048def79ccb4e4bc0d59baaf2a8a0d2e734ca0100bb8040fe7ab8aac1e30": "0x00000000000000000000000000000000000b4a696c6c204a6f756c65054a2e4a2e1d7777772e696e7374616772616d2e636f6d2f6a696c6c5f6a6f756c65001b6a2e6a6f756c652e73696e67756c617240676d61696c2e636f6d00000c404a696c6c5f4a6f756c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471424f9bfe2f5f566ba2a69669a1ed766923a30b1e7cca2c9826f8a0e488afda158de90d7d5bb3f2c24": "0x000000000000000000000000000000000009696e7465726e4c460000000000000a40696e7465726e4c46000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714250ef6a5cbd72bfa16b034f4bf8ab3117bf2bf4feb2babb28379bb9899870303ce71c91dd0d48355": "0x0400000000020000000000000000000000000000000018556e69717565204e6574776f726b206f6666696369616c18556e69717565204e6574776f726b206f6666696369616c1868747470733a2f2f756e697175652e6e6574776f726b2f001568656c6c6f40756e697175652e6e6574776f726b00001140556e697175655f4e4654636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425235c4616852bcaa6c197a5b757309578dfde7a02e19aa9922b8f81a60e81bb0c6b7295090b3456": "0x0400000000020000000000000000000000000000000018564953494f4e5354414b4520f09f9181e2808df09f97a800001840766973696f6e7374616b653a6d61747269782e6f726715696e666f40766973696f6e7374616b652e636f6d00000d40766973696f6e7374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714253268461f29d2acccb0f65823925167071b3eb927035d1343bfaf8cf417b92797a6ed086e89a102": "0x00000000000000000000000000000000001070696e617475626f2d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425353340b14f223feca02a9b52d76d20af3ae90bf5b94103c133d5527e16efd65a35dfaa37985d19": "0x0000000000000000000000000000000000085469656e2043501b466f756e646572206f662043797072657373204361706974616c1668747470733a2f2f637970726573732e776f726b2f00000000094043617962616368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142543c8452e8934bd38772a0fd7eb47babc5fb6c790dec561f05e2adfad50dd61c8b8d173af2be865": "0x040100000002000000000000000000000000000000000d4464656d6f6e20706f6c6b61000000186464656d6f6e2e63727970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425469260aabde91ea8c5c990641c47a3a8469c4ad213eeb46f2801980b10dbac0e9017cfb33e083e": "0x04010000000200000000000000000000000000000000114d61746575737a207c2046656e6e656c001b68747470733a2f2f7777772e66656e6e656c6c6162732e636f6d16406d61746575737a63613a6d61747269782e6f7267176d61746575737a4066656e6e656c6c6162732e636f6d00000f406d61746575737a5f706c617a61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425551d356c585aa2ccce0525a37c12d0fac63ea107465b64b4c17a3909264bb6bb415d12afbe5233": "0x0000000000000000000000000000000000054d6174740101011f7472656e64666f6c6c6f77696e677369676e616c40676d61696c2e636f6d00000a406d617474686c6962000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142596b8a2c5a7ae9c3e7b612fc6c728479e6abddf22f53e7069268b1f87dedc584bb4912fbf42da0c": "0x0000000000000000000000000000000000084d61785f44455600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425a03b4e2357699ce0b8c79103a2b1c659912f45ebadf84a78b84562ca27e3b5cfa4af706be20a56": "0x00000000000000000000000000000000000f4269676d616e74696e67313939350e4b696572616e20436c61726b6500001a6b696572616e636c61726b6530323240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425a7fa8b48b0dc6e1896ac947535ee6c006b54dbf3e01a0de2b718ba3b38b14f540d8d71e86d2d4a": "0x000000000000000000000000000000000015546575746966204b7573616d61202d204d61696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425b4120dcbbe9fbe2e3f0a9ceaf7d69fed8e15a7e2b1477ca3f16195815d09b9508dc87cfef97203": "0x000000000000000000000000000000000003444400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425b4af64c3e38cbe46996819b24f30d5fd5dc85ae9d4c7b7943e72f4070bd9f2a87ac77198ee5f48": "0x04000000000200000000000000000000000000000000076368746f6c6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425c679865a91ba59c66f4d91ebc7dd0065a5a2837014e5f4cef5d36d36d4ba7c915137d885dd7640": "0x0400000000020000000000000000000000000000000016626c6f636b6275732e636f6d206964656e746974790000001a706f6c6b61737570706f727440626c6f636b6275732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425dc4c79b17138074041c5f5872efdc4fb7b09ec7b6e68b6ce3196c799ad3de2982d8ebc9baca81f": "0x040000000002000000000000000000000000000000000b4e6f7661537068657265000017406e6f76617370686572653a6d61747269782e6f72671673686170616d6f6e69636840676d61696c2e636f6d0000114074616d6f74696e6563313737383938000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425e76612e7693e49429de6ac8a65ed9b4c69bbd0f2ee9c1bfd11128756886505fb8bcdbf6fa79d0e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471425f12f3d544b80bd34b05254d36fc7ffe4b638171bb90a9b468c3de832375d46880204b9ff253d53": "0x0000000000000000000000000000000000114f75747374616e64696e67204f776c73000000157468656b6f696e62657940676d61696c2e636f6d00001c747769747465722e636f6d2f4f75747374616e64696e674f776c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426211b2f2f0598491e104b112afb4a9f23112f3eeb28f0e7a707b5a05d9a2d135b6022fc4b01bf25": "0x00000000000000000000000000000000000e537065637472756d204c61627309436172696d616e421d68747470733a2f2f737065637472756d6c6162732e73747564696f2f001c737065637472756d6c616273747564696f40676d61696c2e636f6d00001140537065637472756d4c6162736e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714263009f5614f119d3aaff7070b2622937cc10f63da0c5ce84b487bd2c83eae3bb7054e7089a9dd05": "0x00000000000000000000000000000000000b67662d6e6574776f726b0b67662d6e6574776f726b1368747470733a2f2f67662e6e6574776f726b0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142638a30dc57d656ec085d0dad974c2fc1e90f79317b3703c5161f72e5d22bef963287f6ef23cca44": "0x000000000000000000000000000000000007506f6c6b613200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714263e102005892ac7f8d2eedd093b0a70e25c5a48bf9a499d146ed4992658523e97b3ff165768cf6c": "0x0000000000000000000000000000000000154152544f4245205820504f554e444d4f54494f4e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142643c0564bb7e30e26842927c98a50ab1d439ab45f21c5beb6970556e1fd7b52df44977e4344b148": "0x0401000000020000000000000000000000000000000011447261676f6e5374616b6520f09f90b20c447261676f6e5374616b651768747470733a2f2f647261676f6e7374616b652e696f154064657266726564793a6d61747269782e6f72671b647261676f6e7374616b654070726f746f6e6d61696c2e636f6d00000d40447261676f6e5374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426539dd1197511f342669bcaafd39bc9125bbd0199a6cb98ee674008cd2920b82c8357207753e803": "0x0000000000000000000000000000000000054d696b65010101156d65746177696e646f7740676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714268082072d3e2d0b9421c10cb74e62cb8f5e6ca928c519587c563f9516037cf193f720f0a882e930": "0x00000000000000000000000000000000000b4c656d6f6f6e6b61746500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142695e8a0520bfa9dda6b80813a57b98ed3b95c6dfa6c5b0fedf8ed8547bca16e7310a7354f85d35d": "0x00000000000000000000000000000000000a63727970746f6e696b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714269ee4e3b1539dc2acbe56e4e00aac105c15e7cde200eac5232b9ee4f0d8122b02f847134bfc136e": "0x000000000000000000000000000000000012426c61636b736d69746827732053686f70000000126f7065776b6f4069636c6f75642e636f6d00000f404f705f4b6f6e7374616e74696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426a2abbc21cd770cd88a4b558274e57737ffd3fc9741848596199a29d77fe511804d20810cb76050": "0x040000000002000000000000000000000000000000000d5374616b65506f6f6c323437000019407374616b65706f6f6c3234373a6d61747269782e6f726716696e666f407374616b65706f6f6c3234372e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426a6a8ae22d0110eb2586fbb5db54f99a3aa3a99b2c87fda3498df4f30f8fab356fc86a842dec01c": "0x0000000000000000000000000000000000124d616e6672656461735f4576726c6f6f740000000000000d406d616e6672656461736d69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426adffd4419ace43f6fa0cf7d27491e295e6a4f2709e8eb8927a97c46f7dae68626cbd313684191b": "0x0000000000000000000000000000000000064d696b797300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426b35cf487044dfd1ea3706798fbbe6699c767dab7560171c3ad1ad972987d18e63c23c9bd736369": "0x00000000000000000000000000000000001041686d61642e6773204b7573616d6100000014646f7564792e31303140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426df78e6ebcd1d0c3662167b8a0a620ff11573a953f92c9da6245a263efcaf2b61af65019ee3e55d": "0x00000000000000000000000000000000000a626f6e676368696c6400000000000008403078426f6e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426e7f4ebcd01d4dae6dd0a94c6dc8091d357cf0092af2f8e108daf432d02d27dcb7ffd019d98a509": "0x000000000000000000000000000000000007496e64696b6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426e9d47393173c428a65f2773ad69cccedc0a58ef7ebd2d446b882231b4b97044105b2035a8d9546": "0x040000000002000000000000000000000000000000000950524f584641524d0000000000000b4050726f785f4661726d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471426f51cf99f66fce5e41f9361b1bd23844ab32b6f1b635064ff5c99769c05eb09f5a3c9fa00de150b": "0x04000000000200000000000000000000000000000000174f6e205361696c7320f09f8fb4e2808de298a0efb88f00001440616e647265793a6f6e7361696c732e636f6d127374616b65406f6e7361696c732e636f6d000009406f6e7361696c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714270aa664dc019028d02c1edcd16c17e8e1a9b6d3bf8c20df4c1427225868599d0e11da1442eb297b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714270f33fa5ffc88e7fe98d7eebee0a3c28cbb5b7449632fe9b13cae934d94d81e586c2ea9167c906f": "0x0000000000000000000000000000000000086179796c6d616f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427183e524af681e5420a3bb7932c1b6694b1c93d9e9790850e2078b8cbec088a627ca8b9b5dc6967": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31360f42494e414e43455f4b534d5f3136000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714271ff91c2b1791ebb441c495bb40425f2fd7462637cd29bd01c9dc55ca02a673ef072c7a9bc77c7d": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714272d85207cb7341e54563af23dac19e85f9bd579b947129c25ebbb716f24cc68c969f722ba417622": "0x00000000000000000000000000000000000642757368690b487970652042656173740c6361742d64616f2e636f6d001443617444616f4e465440676d61696c2e636f6d00000b4043617444616f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142730809323ff3aebc29ac3c17a8bb1145487c9f80bc86e6982b95bfb522b6e191ab95ad8f248f07c": "0x000000000000000000000000000000000005486f6f6e09486f6f6e204b696d0000106d61696c40686f6f6e6b696d2e6d6500000b40686f6f6e737562696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142738f0604af4e9680c641da3001395ee6a8d44faed230e8cc7f039191fab991021ca58dad3172b60": "0x00000000000000000000000000000000000744696e657368010101010000104074686564696e65736870696e746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714273e2115b33b2f4960a964547185528c66b393c996dd1ea1a2fc678ccfa4f28e03d60827f49b6542": "0x0400000000020000000000000000000000000000000011536f666969615f56616c696461746f7200001740736f666969612e6b6f6e3a6d61747269782e6f7267136b736f6e696e393540676d61696c2e636f6d00000b40536f666969614b6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142759a5301fcfb0872e9416cca9f463361a1bf01b274de3e4af349dbaa8132ac4a9e5566c5dbef43f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142766b6d320142106cefea2b648a56b300b4511b7feace87a8dff2b99f163ac2ad17cbbea3432ab45": "0x00000000000000000000000000000000000b4c6f6e64757a626f756201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142777a559c125897fb8897a746ceaa53376946a3da353c1c987df8c0caa4395ac0eaf0e6c74874054": "0x040000000002000000000000000000000000000000000b4a656c6c6965644f776c000017406a656c6c6965646f776c3a6d61747269782e6f7267156a656c6c6965646f776c40676d61696c2e636f6d00000c404a656c6c6965644f776c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714278fa2422dbf57da1a7905c207ba3df34886df12a314267e511c90f8ef357424cc6af0477661a37c": "0x00000000000000000000000000000000000953696d697374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142797bb0bbacd54cfa8eafa89c9862249c89e31d6d78bf5392b4659fd33e66016a789653677f9125b": "0x0000000000000000000000000000000000086c6553717261780000000000000a406c65537172617831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427bfec468e3649a946869d994ac3ddc5d2ce93cc76f9f92b675b41ccc7b31fb60d9fadd663084552": "0x000000000000000000000000000000000005486f646900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427c0c7503f888af4507c59dd084108f16b86c906157a8249cf5f750652e76b937a22e3f551a5ae31": "0x00000000000000000000000000000000000870756e6b4d757800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427dc7bc51117cc44d46e6f10cd59b0f6d7082dffb33d27c9f29801233f8e28fe3f5edf2d51762c6a": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427e3665867fc087e60653ca4d287e643df8f9486e158c6eafa04e5d8feb9769009ab627ef1dd5f2d": "0x00000000000000000000000000000000000c4261626565617a79417274054d6172790101166261626565617a7961727440676d61696c2e636f6d00000d404261626565617a79417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427e9a7919c98f38360052cf9f18f47b46ea52cf4473db3ca3c959b2112b819a60c1d0f36ebccd61f": "0x000000000000000000000000000000000006756e7a656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471427f56a6db2b3eecc9451838c59891cd58256365f2d308e0144ef49acb3cbf5596367c8afaef0db66": "0x0000000000000000000000000000000000095a6172746861617800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714282a8872a6cadb12700066767b3608dcde8ee2786b93d9c2e165713b53b6cda62ea106816fd99275": "0x00000000000000000000000000000000000b54696d65202d204e4654085469782e6f582e1c68747470733a2f2f646973636f72642e67672f3432716876613452000000000d40456d626c656d5661756c74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428850aae739e89a2387d4dd17e44506ef67c50ab4b10bb102b9666ad954a3fb1977aa46eb6ec5928": "0x00000000000000000000000000000000000a466f726573746f6f6d06416e746f6e00000000000b40466f726573746f6f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714288be1c561b186005c4704c11534f0e15a863cc2cb28488c9b8ae614d1fb783cc852e39751415423": "0x00000000000000000000000000000000000d526f636b585f4b7573616d61001668747470733a2f2f7777772e726f636b782e636f6d0012737570706f727440726f636b782e636f6d00001040726f636b785f6f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428a876cad533fcb536677e8e5d84c1a25bdac951e9055abff3df4c7a656abd841197a8726ff29a3f": "0x04000000000200000000000000000000000000000000094c656e677569746f000012406c656e676f3a6d61747269782e6f72671530786c656e677569746f40676d61696c2e636f6d0000094030786c656e676f000c4c656e676f37233236363400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428cb5aade7584f6236d7b7a05501f3e93e7eec83c53739147dd9824554e4907136371ca062820e3d": "0x040000000002000000000000000000000000000000000c4d414d415f4b5553414d41000016406e61737461736979613a6d61747269782e6f726714696e617374696b6e6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428da33985b8d542b60db22642e7a1b7f871e2013ca39ab20b15b9416a5b7e9ee91e1e17fa92d5393": "0x0400000000020000000000000000000000000000000015416c746169722062792043656e747269667567650000001468656c6c6f4063656e747269667567652e696f00001040616c746169725f6e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428db6c1e91cbc43002385caf9a08b92ca458a0b817a8cc303cefd5a0c6e108cb939e04242b9e007d": "0x0400000000020000000000000000000000000000000014537562517565727920436f6e74726f6c6c657211537562517565727920507465204c74641968747470733a2f2f73756271756572792e6e6574776f726b001d6a616d65732e6261796c794073756271756572792e6e6574776f726b0000114053756251756572794e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428e36dda90f16500f4589b70331ebfba6b8234b1c07b16147d6078068532b53c1a6cd8805e69e851": "0x0000000000000000000000000000000000084c6f72696d6572104c6f72696d6572204a656e6b696e731b68747470733a2f2f6c6f72696d65726a656e6b696e732e636f6d14406c6f72696d65723a6d61747269782e6f7267146c6f72696d65724077616c6c6574792e6f7267000011406c6f72696d65725f6a656e6b696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471428fb6c72ec6fc14e848c56fc8974dae17c36f18d1e913ded6985fcd583df94391d0fc4a50a1c0924": "0x00000000000000000000000000000000000e546865546f6d69657374546f6d0754686f6d617300000000000f40546865546f6d69657374546f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714290aec17ae7c197466fae573cabe4172bdfc60dfd00dff703a4323854715c151f868293db828190c": "0x040100000002000000000000000000000000000000000d4a61636b20456e74726f7079001968747470733a2f2f6a61636b656e74726f70792e636f6d2f18406a61636b656e74726f70793a6d61747269782e6f7267197468656a61636b656e74726f707940676d61696c2e636f6d00000e406a61636b5f656e74726f7079000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429318d8841335dc7701eaba887e5794e19bde970c93ba68b9ea14c2d48be3f2d9a12a789f2902c27": "0x00000000000000000000000000000000000a496861766563616b65034d6f010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714295296813f75420be0499159353e5c5651dea2347d516d5ffb1e3496e62a6a087f7439b222d1e665": "0x00000000000000000000000000000000000853747564696f4a0000000000000a4073747564696f6a5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142960a5a23c329652582e9acd4386d60a8d3de206a575ab9ab0c383f3b4ee88d2a2ed144afd356504": "0x040100000002000000000000000000000000000000000b696e74656772697465650e696e74656772697465652041471b68747470733a2f2f696e74656772697465652e6e6574776f726b0018696e666f40696e74656772697465652e6e6574776f726b00000f40696e74656772695f745f655f65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429654c28b22ab06086c19b8337e75a61904cb730732c64c378b2922700da9818668a94ec35829e0e": "0x0000000000000000000000000000000000056473746e0d44617374616e2053616d6174000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714297025ac0a2861c0fcef6b2f12605598c64baa5ec72a1db7a6e7654360badcd2e67dbd1d2b2d9256": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142982470e0bf01d0a9af05930538bcbd3d1528f59c4df5d615040cbe411289089cfe743ca48be7319": "0x0400000000020000000000000000000000000000000019f09f8f8e204e4f444520464f5220535045454420f09f8f8100001440776f75746572643a6d61747269782e6f72671b776f7574657240706c6179696e672d67726f756e64732e636f6d00000a40576f757465724466000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714299784d2cc9f99090e29197ee74a3422dda534d19a173a3dae9afc1773191a37c85590d25c67be4b": "0x00000000000000000000000000000000000d66726f696c616e63727970741346726f696c616e20546f676f6e6f6e204a721a68747470733a2f2f66622e6d652f66726f696c616e70746a72000000000c406670746f676f6e6f6e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142999edd4b53f027ecc91bf4a6540ebedbe7ab2bb1a2ee957ad2fcbd832598cbe4e9854d5157fae11": "0x00000000000000000000000000000000000b4f7a7a7920426f62627900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429a258cec4ae7bede4791bfac251c2d421fc66581de126c16b072150c9af2700fc1350b948184819": "0x000000000000000000000000000000000021536565722050726f6772616d204e4654204172746973742053686f776361736501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429b138c94f24ba807c4e144380357ad3e690e74f5b7bbbe4b7d6ab1579d4c6d7c844ef003cad9a24": "0x04000000000200000000000000000000000000000000094d65676154726f6e000000166d65676174726f6e407473657276696365732e6573000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429b9b611bc58a5c6b85a4656256013cfb7410f0febbc9a1ded0f040b7e5b7b865eb0ab16a5742b2f": "0x04000000000200000000000000000000000000000000064261736d650741647269616e00001f62696c61736576736368692e61647269616e406f75746c6f6f6b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429c4999a48e5667768f6e4f77f043dfcb9fe88519996ee25ccae674ccda259bc49efec6b6eeb9607": "0x040000000002000000000000000000000000000000000769636869676f0000154069636869676f39343a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429cca489d7d2fc39fadbad8979264e72d837f2b49a43abcd743143676bbe11ce1cdfd879c5def616": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33300f42696e616e63655f6b736d5f3330000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429d473e4b9c6ee4e2cb14594939f2e2e92e4a59865b659d80be0098ac588dc505f23a9a920cad53b": "0x000000000000000000000000000000000008536161616161610a426f79616e67204c490000163234637572696f7369747940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429d8b41991794e5af304702103a2e260caf32e751ad3118da93f5d63fd2df34d2e712cdc73fbd885": "0x00000000000000000000000000000000000d746f6b656e65636f6e6f6d7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471429ead3ff3726eb80ca4b7bbbeac7ff1d48696fb7cdf933462c6c88a7ebe705f9b78f6ca1118a847a": "0x000000000000000000000000000000000006547963686f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a034e76d17b70ce66823a843da63136d51a51334c6a771685c15258684e29d2821c3c395646187b": "0x08020000000203000000010010a5d4e80000000000000000000000000000000000000000000000000000000b44616e205265656365720000154064616e3a776562332e666f756e646174696f6e1464616e40776562332e666f756e646174696f6e00000b4064616e726565636572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a0c6cd2b29fcf6d60c48535dc707316c51bd853d9b05b977a3760c501706ce9478115de6559663f": "0x00000000000000000000000000000000000a4b7573616d61446f74001a68747470733a2f2f7777772e6b7573616d61646f742e636f6d001468656c6c6f406b7573616d61646f742e636f6d00000c4063726f77646c6f616e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a1134d83a717cc23ca3ed66a374595d4e050482af14bc60b90bb7d8df76188c71d634ee96c35d53": "0x040000000002000000000000000000000000000000000e50657266656374205374616b6500000017706572666563747374616b6540676d61696c2e636f6d00000e40706572666563747374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a1320a99290f3dd9ecdab6f55231e079a117c5f06f01bb8bf0cb3b67c376852d8af206c355b191a": "0x00000000000000000000000000000000000f547269636b79204e4654204172740f547269636b79204e4654204172741768747470733a2f2f747269636b792d6e66742e617274001e6f6e6c792d747769747465722d646d2d406e6f2d6d61696c732e636f6d00000d40547269636b795f4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a185e7f1e6a0461ac03820d55ca72a6676284bb540a1d18c7746371f450998a5ca3e0b1354d5e13": "0x0000000000000000000000000000000000074b656c6c657200127777772e6d6f7573652d64616f2e636f6d001f6b656c6c6572636f6e6e656374696e67646f747340676d61696c2e636f6d00000f404d6574614b656c6c65724e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a251205d65518b0e6b912626c9dfa3cd9e65b4412b19eb9d123edb1aa22d492a58a88091c483a7a": "0x00000000000000000000000000000000000e506f6c6b61686f6c69632e696f001668747470733a2f2f706f6c6b61686f6c69632e696f0013696e666f40706f6c6b61686f6c69632e696f00000f40706f6c6b61686f6c69635f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a3601b2926d2aa7ee5472873e774a1879d8fe0912f0a136413ff823109b9c068e8a7cd4bd0ead28": "0x000000000000000000000000000000000005686f6c6101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a5c73c6ad046c7c067b80b3c8b6fb55b60cb6521bdba3d1ff34daaabbe4644e3ae75c8e7bccff28": "0x00000000000000000000000000000000001145636c697073696e672042696e617279001a6d696e64732e636f6d2f65636c697073696e6762696e61727900196d61696c4065636c697073696e6762696e6172792e6e657400000c4065636c697073696e6762000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a65c9799fef41adec3d304da58d77a4384fced1c59dd3cbc9618dd1ec92e6feb64293147272a21d": "0x00000000000000000000000000000000000a526f636f20536170650f526f636f202f20446f7463617374000017726f636f63727970746f343140676d61696c2e636f6d00000a40526f636f736170650009726f636f7361706500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a71ae4fc6878ea9141511ed1278bc4166aefccb1eb7b6d8dcde86cfd02dd6e618107ba76f6cc905": "0x000000000000000000000000000000000009414747454c4f533100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142a9b352e5eaaff5751f78769768fc88c83546881a768523b3c70c2500159047a970ac4ef16768af6": "0x040000000002000000000000000000000000000000000a436861696e5361666517436861696e536166652053797374656d7320496e632e1568747470733a2f2f636861696e736166652e696f0012696e666f40636861696e736166652e696f00000c636861696e736166657468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142aa13e08bfb58aa40e4022c39c8e100f36455fc8ef6a2a0999baef80c518e806adef3ee7608e2218": "0x00000000000000000000000000000000000a496c6d6972204d455806496c6d697200000000000840746865773071000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142aad13c977c6bc57764ae05560f633f233c4aeac3330e9a926c32ccfcb57f901467a4dafa879752a": "0x0000000000000000000000000000000000084761627233616c0000000000000e406761627233616c6d75736963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142aada661b281a2ddf299e83c04aff581d1178bc3dd281429d9943509d7eae0324bf8d78584fda712": "0x00000000000000000000000000000000000a486f646c2e4c616e640000000000000e404c756d6265726c616e643839000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ab19abf6982483e78d53a2db8434656a5620d77fb78b554ad096691357fec6d7fa8da47a2478e22": "0x00000000000000000000000000000000000f464f52455354204457454c4c45520101011576616e6176616173656540676d61696c2e636f6d00000c4076616e61766161736565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142abb6322ab12c37de80dbb410667a153e62d495a9e0f9bd4b903879e531fefa123aad127e8d33f67": "0x00000000000000000000000000000000000961766568756d616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142aca435ad8607d4a7a53e11bad682523eb4fa9d18bd1dbdc84b50162e2005c0ee93b1cb235414732": "0x04000000000200000000000000000000000000000000076879706e6f7300000015696e666f40706f6c6b612d626c6f636b2e6f726700000e40636861696e616e646d6f7265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ad59b47893766e9a215ba2d1b408fd5350b93f2566124331dabc06e94c16d7080d3cd5771d59958": "0x04000000000200000000000000000000000000000000124265737456616c696461746f724576657200001e406265737476616c696461746f72657665723a6d61747269782e6f72671c6265737476616c696461746f7265766572407961686f6f2e636f6d000010406265737476616c69646165766572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ad67d457f83cdba42988a08e2e4e44a78abcc93d99d458eaf9cb23daf6de093ca2aaca1b2111025": "0x0000000000000000000000000000000000096c6f7265666176650000000000000a406c6f726566617665000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ae9d42a8da3cf5b1cc30a09ab89ebd5c6750f7df34378d6d750a2fd3be256735fae11dd04412f6e": "0x0000000000000000000000000000000000086d61636e66747900000013646d61636e66747940676d61696c2e636f6d000009406d61636e667479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142af56ffa9ecf488b30743e11bca3faf36dc95314e5640f330c12669b9d90a800fe2c1fa20c890777": "0x0000000000000000000000000000000000084d722e4c696f6e0000000000000b40636c656d6f6e635f63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b031c075ea343ce443c76dcde19df9387486ded7845c6d85ec2a4c17f38f8b1e7a0a14de7968d7d": "0x04000000000200000000000000000000000000000000064b414d454c0d6b616d656c7374616b696e671968747470733a2f2f6b616d656c7374616b696e672e636f6d19406b616d656c7374616b696e673a6d61747269782e6f726719636f6e74616374406b616d656c7374616b696e672e636f6d00000e406b616d656c7374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b0cbf1e0fccd13f6e829382b887d84d8fbb444ae215bac5c1b639e7c5cae2bddb49f35110b16213": "0x040100000002000000000000000000000000000000000b5368616479626c61636b00000016626c61636b736861646565407961686f6f2e636f6d00000c407368616479626c61636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b14414c029d53fe7e02cb4148b7af9c92f176daf919bbc75df1ba8de7446788d07846817a9ab85a": "0x0000000000000000000000000000000000076b6f6d6f7269114d6178696d6520546973736572616e641d68747470733a2f2f736f756e64636c6f75642e636f6d2f692d772d73001573686f76736f726940686f746d61696c2e636f6d00000b406d61786b6f6d6f7269000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b1965d612c430d2087a435025db114c8c7f0778e86efd968ee4a60bfcee8dcecd19099e28daf46e": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b2a875868c6b85caa32859a54b9ea9d36cf5af9ed03febea761fb5d9f380b6d517874b96d87866f": "0x000000000000000000000000000000000007616461636f7907616461636f79000013616461636f79313340676d61696c2e636f6d00000a40616461636f793332000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b6e818ad6aaf2194425333101d35f55eccfe16b28f0e65007a0076ca42eecb050405f6e0ac4737e": "0x040000000002000000000000000000000000000000000475616900000018616e6172636879636861696e734070726f746f6e2e6d6500000f40616e6172636879636861696e73000e616e6172636879636861696e7300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b732c11caed7a5626902bc2f712f4c3fe8d6180e162376ba644cc80ba99e84cb9bb8e50c20c546a": "0x0000000000000000000000000000000000094e65772041656f6e0d4c656f2056696b746f726f7613687474703a2f2f6e657761656f6e2e72752f0117736974652e6e657761656f6e40676d61696c2e636f6d00000a406e65775f61656f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142b757a72ee144495f0d30ae836bb1d44542a6ceeeb6ce03aa7313cc47b96a4ad19160074bed83621": "0x00000000000000000000000000000000000c4b7573616d61427265747400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bab42363fea46ad00f52ade889dac25285059b639359071c2aad88e3f1f60593f86cc460ce20213": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bac4814c142df16f89d49e97071dfd7f8971ed816c0fc60a34aa6a8d0b1af8f7c6922659dfbd789": "0x00000000000000000000000000000000000d63796265726e6574776f726b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bad7c5b850e0c22423a671a90c3fe2169dbaf169d5446c1470985ba05bee19614f2afef4eb2f15a": "0x00000000000000000000000000000000000945475245474f5245011a7777772e736172616867696c626572746b756e73742e636f6d011973617261682e67696c626572743840676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142badf2d7418dbc94fa2ee018998f963b05d05b960d10a8b47043ef1fa552415e0f128e239d9f4a17": "0x0000000000000000000000000000000000095a69676775726174001f68747470733a2f2f6769746875622e636f6d2f72756e7a696767757261740000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bc21eb1a6e88498ea524b9e0dd9bd336d31e71bc1a172388b10d4b6571ace5e7e6e836483110216": "0x0400000000020000000000000000000000000000000009446f7420506c757300000016706c757373696b6f6e64654070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bc675823ce5a7ffb49815cebdde0943433b0670fa66180bf2b957cd6ebe203be6e581149fc38113": "0x000000000000000000000000000000000007416e696d616c10416e6472656173205a7573756e6973127777772e426162654472616b652e636f6d1840616e696d616c6f756b6f733a6d61747269782e6f7267126961676f73383140676d61696c2e636f6d000009406961676f733831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142bce7bc79ded2adecaf177ad58c772e31f10a83e8b76e4905bb78d5547e8976e19ca4c3366609015": "0x0000000000000000000000000000000000094172636f694b756e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c044452e691b7312c2689f3c9b59f32f1730cd3bc8c54fe55ba31d2525cd7ec80a3dc6726809240": "0x00000000000000000000000000000000000453616d000f7777772e706f756c70732e636f6d000000000a405f73616d5f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c09493faa9e924efc5d04e7ff3965c8285a2c23aa573117deeed886bbe5e3be0974f1cf0a2ff216": "0x0400000000020000000000000000000000000000000012e29880efb88f536861776ee29880efb88f00000015736861776e40706f6c6b6177616c6c65742e696f00000c40536861776e5859616e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c0e09d90be40d90180da4776d78804652df766f9f002b4f448f183732eee12da7c3816f02031e64": "0x00000000000000000000000000000000000866756368736961086675636873696101011867616c6178796675636873696140676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c157c9e312512df503fbcd2efb481dccbbb4c6d7ce0c60700e0fd3c81bc126372d6e8efcbe2bb2a": "0x00000000000000000000000000000000001148656176656e734c617374416e67656c0000000000000e4048766e734c7374416e67656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c1a489d7e391b077c64f959f2bfd05207d426c9e28b0bdfda70d0fdac821107c426570205e67779": "0x0000000000000000000000000000000000084150452058323701010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c1efb90638974dc0c30a71e750654bc69b1e570c34c27c623f3e42f94632e3e1508f88bf97a1d5d": "0x0000000000000000000000000000000000074b5553414d4100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c2dd4393185b96676d76166add74cc4fad0151e7780acb5555dc57e14ce131251df83de6a5fe841": "0x00000000000000000000000000000000000c6c61692070696f6e65657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c3ee724586db259eaab0cb55c147ffaf184a4c00513e85f6d5bb6416994fbdd0dd168f3c59a291b": "0x040000000002000000000000000000000000000000000c437970686572204c6162730000001d6379706865726c6162732e636f6e7461637440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c74588f39d962f18813e7282320dc3025353a1dfd830f346e4d1440636185949584211859a75a75": "0x0000000000000000000000000000000000074261726b696500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c823c435a39d571c8a863618f72322a02f9d0028e6a6b907326041ee098e3259b39193a0cac5a41": "0x00000000000000000000000000000000000f4976616e2052204d6174682023320000000000000b406d6174685f6976616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c870467e584bae74292ae067e7aba72e9d415daa26425b96c13c059b76a9cacfd1edb2e1563be0b": "0x00000000000000000000000000000000000d50524f504845435920415254034a5400001970726f70686563796172746e667440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c8d642db83d4b3caeddba72d260d2a9d78d169f5a6762909502702e9b2e9bc7722c51cc5eb8dd31": "0x0000000000000000000000000000000000054b616e79000000196b616e7963727970746f383940686f746d61696c2e636f6d00000c404b616e7963727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c9114f608ac39a9a45d1c3020272172fdb2238d4b68c1f8d6178dfbf4a80404dcd01da024dac33d": "0x0400000000020000000000000000000000000000000009476162654b6f696e0000001c6761627269656c5f626f6e75676c6940686f746d61696c2e636f6d00000a40476162656b6f696e00114761627269656c5f564453233735383600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c99d1fc868ada3d123fc89c054713d7d6cea09d68bba5e3c45d3267549c5af73c5be3950afd3370": "0x0400000000020000000000000000000000000000000007536f6e64657200000014736f6e64657240737769736d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142c9bb7cb7587271684546cfff5fbfa479772bca48aad4222d5d56aea6027594293a87ae664c60b51": "0x00000000000000000000000000000000000442454311426f726564204561676c6520436c75621c68747470733a2f2f626f7265646561676c65636c75622e636f6d2f0019626f7265646561676c65636c756240676d61696c2e636f6d00001040426f7265644561676c65436c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ca72e801f676e6fe034fb93b0d06e8a0db8dd5fac4edd8657c2cc78247ce5200e0b5c4ee6d55f3e": "0x00000000000000000000000000000000001e524d524b61626c652044657369676e732028756e6f6666696369616c29064d2e20532e00001a726d726b61626c6564657369676e7340676d61696c2e636f6d00001140524d524b61626c6544657369676e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ca762582cb6a0a95227e6087c3098806a03e82a5db0f33308340c7fdc3ab90cfd6f8be97ce28456": "0x00000000000000000000000000000000000a43726f776e6c6f616400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142cc588273271e0810837f57eb5dee33b7c8895a425116e9dcf32708397c630ca9a5cb1d71bd2d20c": "0x00000000000000000000000000000000000d43726f77646c6f616e2e6d650d43726f77646c6f616e2e6d65000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ccc8f3bf5790f3e7a5c852e5d78fb634282eccd5d38dc9b353a6c88841816710c12b4ee243ffe2d": "0x00000000000000000000000000000000000b4f6e6520506562626c650000001c6d61726e692e7261626173736f4074776f706562626c65732e696f00000c404f6e65506562626c6531000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142cd98d2b43b99a0b6a325e3630266fda0ef7f7725ef8199726e29d569d609f3cf068c4db7e82591a": "0x0400000000020000000000000000000000000000000009444a5f416e6472650000000000000e40616e6472656d6f6973656576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ce0ec76a2fab446d600c37c06c4c1c4fceca07e2a33e1db5f0958f4d36ce6b05fbc65d7d526c320": "0x000000000000000000000000000000000016486f757365206f66204b696e67732042616e6e65720000000000001040486f7573655f6f665f4b696e6773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142cf2c3bc9ddc0e47eea5168acc75ce334e39799ff680543ce0217605b078f22967448aa781ba6925": "0x000000000000000000000000000000000010506c616e6574204e656f20504e454f001768747470733a2f2f706c616e65746e656f2e636f6d2f000000000f40706c616e65746e656f5f636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142cf3c07511b5dad1d9c958ec068aaa78b0d6256fea94a50cd19bdc1f82f905e88b4bd0bb5626ecf0": "0x00000000000000000000000000000000001253686f6b756e696e205472656173757279001968747470733a2f2f73686f6b756e696e2e6e6574776f726b0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142cfc30ea1aabc0e1d0cd1d5442f98ef9105aeadc08f225b4df5ebcdf62479ec5b0e540b57c313a3f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d287fe916fe23dc925000bd5b83d502f56c49f2a91e3532af9f919d6eb52d750b72539c6b62d45b": "0x040000000002000000000000000000000000000000000a4b534d2d736b756c6c00001540646f74736b756c6c3a6d61747269782e6f72671268656c7040646f74736b756c6c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d294ae179111e4afa0099be3ab25140ec53154e141885c824f52fc67184630153baa07e1fc1c10c": "0x0000000000000000000000000000000000056476736c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d51e75bf4f0eb6a367371f79b82ad8954a69d5bfdde1c06489909c9a12cb8501b949f58b6a03926": "0x00000000000000000000000000000000000b42794d6978616f6f7073084d496b6861696c2168747470733a2f2f7777772e61727473746174696f6e2e636f6d2f6d6968616900136d6978616f6f707340676d61696c2e636f6d00000c4062796d6978616f6f7073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d52491d0ed316bd6ccfe70c7201bb25d4c6d73cabc89a8dc1d76dc165b691db825c3f4b19889129": "0x0000000000000000000000000000000000064265657a7900000000000009404265657a794a4c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d52913dfdc412f8103b98301a063f5153c46f5c1afa1624ba72db328f8a76b3144eb7d6aa646330": "0x00000000000000000000000000000000001548756d616e2047656e6572617465204e46542773001c68747470733a2f2f646973636f72642e67672f685a464b68426354001b68756d616e67656e65726174656e667440676d61696c2e636f6d0000074048474e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d60b5c259d3d208620cceb8ca6241f9ad974b5719a46a33cf158e2e4ebc86b0771f909d4ff2ef62": "0x0000000000000000000000000000000000094e46646f63746f72084261747568616e00000000000c404e46646f63746f723033000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d697287022039ece6ba43544c8cb8f23a0d86e506d37cd74b63f07ae99714c3915068b4d0c7792d": "0x0000000000000000000000000000000000124b7573616d6120436f6c6c656374696f6e0101011c6b7573616d612e636f6c6c656374696f6e40676d61696c2e636f6d000011404b7573616d61436f6c6c656374696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d7cf31d9f27e677ccd583d619471f2ecbdca885d80a949e38c6c5b4c3ac8ea86837a45407530658": "0x000000000000000000000000000000000010616e647265735f6f6e5f65617274680000001b616e6472657369746f39384070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d859f3bd54b349892e02ce87428939cfbb7fbeeb1ee758b749a5854a1bd3ae9ce36b3bcb753010c": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d8a3df03fe6535f0815155bdc6775c63aceb731d5ebe8d55043b8598d4ed1308b4666bf0e66ba05": "0x04000000000200000000000000000000000000000000135468652052756720436f6c6c6563746f72730000001b746865727567636f6c6c6563746f727340676d61696c2e636f6d00000f40527567436f6c6c6563746f7273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d8b973a55fc6b24b4e398d5f14cefa2a00e1f9faeb8f2fdbe5ff83638ff3e1711301c39eca6e553": "0x000000000000000000000000000000000010446f6e7079726f2e4b534d2e444f5417526f6d616e6f20446f6d696e676f2041617264696e67000014726461617264696e6740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142d930a562d1da7c24cb651038cd04fc360e95c5db473d3236c69fd68e57ce9ffa6bec307c450b038": "0x000000000000000000000000000000000012414a414c2047414d45532053545544494f12414a414c2047414d45532053545544494f1e68747470733a2f2f7777772e616a616c67616d65646576732e636f6d2f1640616a616c67616d65733a6d61747269782e6f726717616a616c67616d656465767340676d61696c2e636f6d00000b40616a616c67616d6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142dca72940cf66478a25c9b1c6ebb2832b2ccf7812a405dced6866efa8ff595fbfc408a4091b5631a": "0x040100000002000000000000000000000000000000001050696e656170706c65587072657373000014406f6b6f6a616d6f3a6d61747269782e6f72672070696e656170706c65787072657373314070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142df274fea56f1419fc659bba6d3985002708101d9c2aea9155bd520c105688751281cb40e4d37163": "0x040000000002000000000000000000000000000000000a524152455348495053000000147261726573686970734070726f746f6e2e6d6500000e407261726573686970734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e0a33dd13e78f0efbaebc5c7327144be51df35bb50ff8612c8c9ad73fc7b60b4382b979563de20f": "0x04010000000200000000000000000000000000000000094b6972757368696b0f4b6972696c6c2050696d656e6f761368747470733a2f2f70696d656e6f762e636319406b6972696c6c3a6d61747269782e7061726974792e696f126b6972696c6c4070696d656e6f762e636300000a406b6972757368696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e15b07440923f7648fad007551dd2cf911c9ab936c50be87a01cbee939cd9bc5ba6fde3064cd515": "0x00000000000000000000000000000000000e54484520434f4c4c4543544f520e54484520434f4c4c4543544f5200001f4c414e44534f4349455459524d524b4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e31c7d323f7b00deafa84f0fbcc838d944b1375c809bc99f800d225286b7f25edbdc33f6c469b16": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30390e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e338a8ddaef9fa642fa2391ee121af5f64b30bb2b63d9764735ac422fa2fefb0dfac90ee03a512f": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30380e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e61081843efc3b7105c06afbe01ff98801bf3e46b96d61d0d7aeadf7af7d6c39a20dbf946b0fe41": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e6833257186cc32886267a39c2dd0cd8175ac3e50d353375c694874ba6f48d6aaa4bb9e88ce3930": "0x04000000000200000000000000000000000000000000084d79706c616e410000001464656e6665726d383040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e7e56460089fc7a54c473bf199d05b878ab34e9a37d17d0a8bf70498edb5c759672e984fa38b432": "0x040000000002000000000000000000000000000000000f4170706c6965644243204c61627300001a406170706c69656462636c6162733a6d61747269782e6f7267186170706c69656462636c616273407961686f6f2e636f6d00000f406170706c69656462636c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142e872013d9376606ac9ffd09502123eba056c7619c9b96bec443840450e7759bd0a9817abbbc1a33": "0x0000000000000000000000000000000000066d726d743300000000000009404d724d74453231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ea6cb65218cf1ca90c6619c6ba60125e49e75e1ea5d9b46431ba834d005319cc036104c94fcfd34": "0x0000000000000000000000000000000000114576726c6f6f74204f6666696369616c00107777772e6576726c6f6f742e636f6d00116c757575406576726c6f6f742e636f6d000009404556524c303054000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142eb239de2237ff4464c92fbc08d8d3594de7a9eeae4ef24891cf7e8330faf07ed804cd0045e49e6d": "0x040000000002000000000000000000000000000000000a53686f7274795f33350000000000000a407273686f7274656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142eb552e15974a83bc96e8af1ad79932da28f515b436b020afdfd6a389631609ab07c2fcf2e140d12": "0x000000000000000000000000000000000019506f6c6b61646f7420416672696361204d756c746973696700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ed50d6c1327ddbc1cb5dafe7d8501739003634d34c9e44c526cff633093841194dcbe98ec229920": "0x0000000000000000000000000000000000106d61756e616b65612d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142eda38798820d6b442b5e9dc13290ed285216681dfdf7e2a948b541a618830bee3387d34bd23e262": "0x000000000000000000000000000000000006536163686100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ede9598e62bc86e52e4df0f3307bcc319ff009b0390f8225293b344ef27dc328a0c341d842bb23b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ee91b64f947da118e8bb8ffed82a876768d15ac8dc37d613d3d55abf82c23f9dc644b4c1d3a2513": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142eebecf8e65e7682b8920b8c8220efc9c49ffa5271b5e5356fbeca4f9bfaf73e2b887613d2cc4966": "0x00000000000000000000000000000000001151554152545a20425920554e495155450f556e69717565204e6574776f726b1768747470733a2f2f756e697175652e6e6574776f726b0012697440756e697175652e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ef08ea2ef087797ee50f5c29bb5a49cf456ef7717676a8d905eef37031a02eafb99b203edefb92f": "0x040000000002000000000000000000000000000000000b48697370616e6f446f74000000136869737061646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ef7355afce0085c3a68b37cdcb55285eb9e76ee8744cb3c47c62b6bb07b104116077df4b8460573": "0x00000000000000000000000000000000000a626974736176616765077361766167650e7777772e61646f72732e78797a0b4062697473617661676500000010407068656e6f6d656e616c6d61726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142ef7dd71f889f0050c841e6aea307d8704d5b7b7b71afad58548ce47dce090e25d01b84925e5c48d": "0x040000000002000000000000000000000000000000000a43616b655374616b650000174063616b652e7374616b653a6d61747269782e6f72671f63616b652e7374616b652e73756273747261746540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f01f5b6d9f688b11245242cb72fd4a3b8a7423d647e0463df0017eb7539ea511bf6f7e68b3dbd22": "0x0000000000000000000000000000000000054a70657800000017706978656c6f736f3035323740676d61696c2e636f6d00000e405069786f3632353735383835000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f134a0eed4de1af79454e81bd1c5d52ba72c96494e83f33e2aa22e93d3e500843857b6a7815a11d": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f20db1fb9bc54324c042cc1451781f79ff3bc34cacd5329b21591b2b2d82ad57426a5079ad1c455": "0x040000000002000000000000000000000000000000000a53686f746d616b65720000001c73686f746d616b65722e7374616b696e6740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f2145cd985eff31bcb916e7a7ef77dd1f610ed27ec519b4ec226028eb8edade41f95b217f89f620": "0x040000000002000000000000000000000000000000000df09f97bb4261736563616d7000001840776f6c667374726f6d32373a6d61747269782e6f72671b6261736563616d702e7374616b696e6740676d61696c2e636f6d000011404261736563616d705374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f317d0ceefcb30d381612c21d537305340416604931c9d1c99a50c3f99c794f75d84db494079318": "0x040000000002000000000000000000000000000000000c4a6164652057616c6c6574000017406a61646577616c6c65743a6d61747269782e6f726718646576656c6f706572406a61646577616c6c65742e696f00000d404a61646557616c6c657431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f344d81d36d4b7e7403af740812442eb174a83b37da8d7f8dc2d8b6cde6e7ff968b5cb4b07ffe68": "0x00000000000000000000000000000000000a4e6175777573616d6107446d6974727900000000001040446d697472793632383633333737000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f392ac03e9ede7930dedb2a379560d56675e977ced75752b912f35165ca8380499f8be7b74d426f": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31330f42494e414e43455f4b534d5f3133000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f42d98a8e441c40566fdfde57471dd26ff6213ab7190765d9d10b135cf911b45508a009a95fb03a": "0x000000000000000000000000000000000011647a6c7a76207c20537562737175696411446d6974726969205a68656c657a6f76001240647a6c7a763a6d61747269782e6f7267000000084064697a68656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f694a8c100618ce0209638912655716404e7787a88325ab80a7b0ca614aa5b8e3daea1cae0e1c31": "0x0000000000000000000000000000000000084b72697076616c000000166b72697076616c65786d6f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f77a540c5c2d555742717df0d5932f1d83ab0400a162e39e93a0823f8172cb880c46e1b6dd09c72": "0x000000000000000000000000000000000005416c616e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f816440610f862600ec9f324035cbb3d86ef51a32b5ca578c65271dcd882036d03e77601745d807": "0x000000000000000000000000000000000009416c65786269746100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f8e9f741508842470cff2a79754a54f7dfcc423111dd79554320512a153f45df50abac7e6f9d20a": "0x0000000000000000000000000000000000096368616f73626f6900117777772e6368616f73626f692e636f6d000000000a406368616f73626f69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f8f1ddeb924bbdf5cadb1617794ea8d20a5b0bf1e3275a815229a34c834c9eb6383602ad47ecc55": "0x040000000002000000000000000000000000000000000d504f5354434841494e2e494f000000116b736d40706f7374636861696e2e696f00001040706f7374636861696e646f74696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142f93d78dfd49d0a462d9d0181b12100f1740ab9260827746eac283a626d77755c56bea5ddf3f097a": "0x000000000000000000000000000000000005416c616100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142faeb9cc9f49512f1ea25dc95281641f4b7fd9b8c8d7b970fbe764ad49b2ca1b4402baeb8eb32d04": "0x000000000000000000000000000000000009736974752e41727400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142fbfebd49e947bc8decb110ce95c05a22ef28e342b54a2a7efcba5b6c64fa8ccec033c1f5ebf9504": "0x00000000000000000000000000000000000c426172657944657369676e12446d6974726979204166616e617379657600001664696d733930323338393540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142fccfd4d73aaadfef8c309d6472fab1a89e619867d57934db759e5d76d63b9e67968e36f02787335": "0x04010000000200000000000000000000000000000000084d72457863656c134672616e636973636f20416c626f726e6f7a0000176672612e616c626f726e6f7a40676d61696c2e636f6d00000a404672416c62726e7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142fdab663781fbd7a162f163b179ad5c7c13073565aeb1272868861738802c33bc921b69a9e0e8a6c": "0x00000000000000000000000000000000000748617273686107486172736861000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047142fe1803695779c79b2636043fc3b8dfa608167a9fb6fb9d065b9f2f5821dc4bfc9785a244b24a92a": "0x04010000000200000000000000000000000000000000044a6f650e4a6f6520506574726f77736b6900000f6a6f6540706574726f772e736b69000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143020cac001d284991a0d2dde7dd9defc8db6f97b28e3c6a8b4a6887f27a62f60268f6061553fc719": "0x0000000000000000000000000000000000144b7573616d61205374616b696e67203230323100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143036130cfabe43d906a991c8e9af2d6e2422d0909ef0aaf0dbd5cc8c9985fe2967cb159a0f9d906d": "0x0000000000000000000000000000000000094b7573616d6f6f6e0000000000000a406b7573616d6f6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430364fbaff46f65ba081e51d00d0908deeac6cfb45d3e977f37085d2905be73e32c4b9e6707ab754": "0x00000000000000000000000000000000001250726f7665726273204149205661756c741250726f7665726273204149205661756c7400000000000c40416950726f7665726273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714303defe256c66ba0e0fb683f9ef19a5e932b6232272697fabd62213de02d7801aca1e94b03c0b23b": "0x00000000000000000000000000000000000c43495320466c697070657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143046396b7c34c0b3eec4bd650a277342ebba0954ac786df2623bd6a9d6d3e69b484482336c549f79": "0x00000000000000000000000000000000000664617678790f4461766964652047616c617373691468747470733a2f2f64617461776f6b2e6e6574124064617678793a6d61747269782e6f72671264617678794064617461776f6b2e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430669b7d5c8f7c3ab23801b12140968daf5304a7c38e81dbf8d75bedf02b85ae0ca8b4fe394e8337": "0x00000000000000000000000000000000000e6d697368616e79612330303231094d796b6861696c6f0000176d6977616b756c696e69636840676d61696c2e636f6d00000e406d6977616b756c696e696368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714306c8cf26d4e0d752673c96d918a62b9af204d09f3b8a9b984daf0abbd176974da17aa688f991a6c": "0x040000000002000000000000000000000000000000000857494e2d57494e0000001877696e2e7374616b652e77696e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430829bec9693a3c7581bddaf5249dcc6a055652c0654ba073e21bd622d8a5b2aec629a9bc8921562": "0x00000000000000000000000000000000000a53544153204c45474f145374616e69736c6176204c65676f73746165760000186c65676f73746165767374617340676d61696c2e636f6d00000b40737461735f6c65676f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714308ca83512dc5d0c00c6fad38515e62f83f804861803773ae17af068898dec6d558c903663078754": "0x0400000000020000000000000000000000000000000004624c6400001340626c643735393a6d61747269782e6f72670000000740624c643737000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714308d9c16e268f1b512713003b0c7826f024d4517aae0e5dcbfb2b9ead74c4c668f572698d012b754": "0x000000000000000000000000000000000010536174616e69636f20416e67656c6f0000000000001040416e67656c6f536174616e69636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430a74a4157ce4ce35c1be3d517926a6c194d42131d996140f3e8d7398764423cab176341b882ee7b": "0x00000000000000000000000000000000000d756e7374617465736c6f7468056a6f616e1b68747470733a2f2f786e2d2d64723868306474376b2e792e61741940756e7374617465736c6f74683a6d61747269782e6f72671c756e7374617465736c6f74684070726f746f6e6d61696c2e636f6d00000e40756e7374617465736c6f7468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430ac3f1c5457a413d602fcca19d55a03e44eb46202b906cca9d97b3e866b9b4ef584c957c135f109": "0x0000000000000000000000000000000000084761726261676500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430b98fcd88ab4d906463b8663469c48312ecb51fe6151c4fa1e91f93270cb23326ce9d8af3a80f01": "0x040000000002000000000000000000000000000000000a4b7269737469616e4b104b7269737469616e204b6f7374616c1a687474703a2f2f666969742e73747562612e736b2f3439303300196b7269737469616e2e6b6f7374616c4073747562612e736b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430d3bc09d2bfcfb50c7f10142a81fedec753f7c556f5b93a400c280805e7fcdff668719637b13434": "0x040000000002000000000000000000000000000000000f47656f7267695f444f5453414d41000000126a69673737303940676d61696c2e636f6d00000b406a696763727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471430e79056e8a84474ee06959ae4cf287f2e3dc249d46c25dc777851c755931b486d7fb552932da259": "0x00000000000000000000000000000000000b477579576974684c534400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143113d3db76841af844a91dfd908b2b82a43037d003c90f884d3e03e7ec64b460c7caa2c2f5dcf448": "0x0000000000000000000000000000000000104a6f654a6f736570684a6f686e736f00000000000011404a6f654a6f736570684a6f686e736f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143118f1715a74c330aef5e12ceb56767d94848a252a5d258186547a3e9fbc2cb1b4c916d8ac888554": "0x00000000000000000000000000000000000a4163636f756e74203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714314002c34f6b0e235818a8031736e2d320bb0c393bba318521b265f60a449e66567840734ec26c6f": "0x000000000000000000000000000000000013537562736f6369616c204d756c74695369670019687474703a2f2f737562736f6369616c2e6e6574776f726b000000001040537562736f6369616c436861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143149ce02bbbc85a0f809131fc9ebb8441aec7ae0c271a24d13d129266705fb0fef99aec4c1dbac31": "0x0000000000000000000000000000000000064167796c65000d74616c69736d616e2e78797a000000000c407374696c6c6167796c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714314edbaf8df5f693223e082b8fbcf1ff9271ee9630974f9807c33d3beaf0463d069be5e59f2e9e7c": "0x00000000000000000000000000000000000c30784669736865726d616e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714315041883e0df8a8da6a7b717c79a7c7737652894ae316e658fe616977042aa4b41bb9bb1b108371": "0x0000000000000000000000000000000000084d616d61446f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431511477c988aab2e875fa3fb75a0c715e26e7aceaae87e2c8a158b4e6cd5732985efb48b7023474": "0x00000000000000000000000000000000000645696b61730000001765696b617332304070726f746f6e6d61696c2e636f6d0000094045696b61733230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714315b69d6d9952265924cf81bb5b38134cd8676c29a495f7277ff111b6a1bb6b22caf80d32a1b5c57": "0x00000000000000000000000000000000000c48656c6c6f204c75696769104c75696769204c75636172656c6c691f68747470733a2f2f6c756967696c2e61727473746174696f6e2e636f6d2f00174c75696769417274776f726b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143161b54cf940118e9aa6373b24df370b863773f45f2bed6ebd80c886c58b4232e655a9b130b6d615": "0x040000000002000000000000000000000000000000000a426567696d6f74696b000000157361617066697269756d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143168f24ac9fff4d65e576cdec1179c77d81cca7e34d35784bf47d6667300642a7697403deb967d37": "0x00000000000000000000000000000000000a7374726f6d626f6c6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714316c889b24fdb42688040f8566edb50fd272f65b2f232a8008fc9d1127b8d543b529306c4ab3ee65": "0x0000000000000000000000000000000000094d6574612d67757903416e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431747b68fd9a8689a0e1a33870981aa76012429e64409e7445f64ba6b3bf75a2e0c97ed51179a64f": "0x0000000000000000000000000000000000086e796d65747661000014406e796d657476613a6d61747269782e6f726700000009406e796d65747661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143174bf5b787aca25e277549039e36cc29f87b3faea4cdc1957238e41a88fe7702eb6486c618f4366": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143182c3bc7056e978c6c42b648b7ba1fe5c4395c5d0465b522e3fcb7b82d8839526fb4384a8d57130": "0x00000000000000000000000000000000000e53746572656f6772616d417274034d4b00001873746572656f6772616d6e667440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714318ee29c136c23ba24d6d7cd9a0500be768efc7b5508e7861cbde7cfc06819e4dfd9120b97d46d3e": "0x000000000000000000000000000000000012537562736f6369616c204e6574776f726b001a68747470733a2f2f737562736f6369616c2e6e6574776f726b000000001040537562736f6369616c436861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431946c413eb637175681edd930e8ed28fb6d74c6d4ddf28067e73e562bd0fe5bae97eb943fa07759": "0x00000000000000000000000000000000000e626c6f636b736272616e646f6e086272616e646f6e00000000000f40626c6f636b736272616e646f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431a1b217ee0ca06caaad489ec818806f0fe0474670170482c6c30c637cc9346895f4829799d3b73d": "0x00000000000000000000000000000000000a4b6f542d4b6f4b6f4301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431ab29bb118a97e0641fc26bf772a415828c28c203d3058b65171ba36adfae02eee832c6ae723e09": "0x040000000002000000000000000000000000000000000a636176656d6161616e00001640636176656d6161616e3a6d61747269782e6f726713636176656d6161616e40646d61696c2e616900000c40636176656d6161616e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431b2fdb72ea0daaebe0b3284497d66688f69f915798eb39419480581d8af1d947081cccf478c3a7c": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431b53430fbb80701a6b7a488577dc9c35aaf6fd9cdb6959eed7d73764ef4909330aeb3179315c921": "0x0000000000000000000000000000000000086772656e6164650f726f62696e207468696a7373656e0f68747470733a2f2f726f622e746e0014727468696a7373656e40676d61696c2e636f6d000009406772656e616465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431c600177e63ce4012e3ea2518656228d1b018a56cf4f968a33342cef3a03eb86a0d7d93cd1a856e": "0x00000000000000000000000000000000000b736164616d626f6265720000000000000c40736164616d626f626572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431c6b74df11dd22926219557f2597e5d6194b4c8f9b23570220d6cac37f05fe10e8f780dcc0c0a22": "0x000000000000000000000000000000000008736d74616e30780000000e6277354070726f746f6e2e6d6500000940736d74616e3078000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431d0fa954fe513fec6f2b101590b7bd089df91f5c01093b83217ffcd1c6867c1512de33cff1f5e06": "0x00000000000000000000000000000000000d4d6178446f744465764b736d0c4d6178204b534d204465760000156d636b7261766164657640676d61696c2e636f6d00000f404d61785f5f4b7261766368756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431d8dbf29af0af35f0b64148873fede866ca5f0c92fd48bf6eadbe447d71dbd331f83f0555ee044f": "0x000000000000000000000000000000000018616e64726540636f6465736369656e63652e636f2e7a6106416e647265000018616e64726540636f6465736369656e63652e636f2e7a61000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431e2782ae179fbea3a2c6f9e020bc5b17dff66bf280199df9d76dfd0936d912bb75ee8275a64a733": "0x00000000000000000000000000000000000861706f7069616b00001a4061706f7069616b3a6d61747269782e7061726974792e696f1261706f7069616b407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431eb5724c95ef0d7f883366aa0218141016c6bc826e0ec376bea1e39b119dc1f402ac6f5964e9f69": "0x00000000000000000000000000000000000c43756c7475726120332e300000001a736f6d6f7363756c74757261332e3040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431f2c7371b41417c08be3b4777517573d95a82ce78b6833c4db0092078a6dabffddc699905a2f013": "0x0000000000000000000000000000000000096e62307564696162010101136e626f756469616240676d61696c2e636f6d00000a406e62307564696162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471431f8c44fbe7173049c1bf5e2ebc5301283cfbc96e83265efa80b326b5fbf5a6845c2c26fbef17c3a": "0x00000000000000000000000000000000000f616e792d636f6e74726f6c6c6572000000186d6f6e657963656e746572697140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714320eb468db7ea3c7aeb9fc068a3340edead118ac3cf3decc6743724cd5fb11edebaa98b540a08f07": "0x00000000000000000000000000000000000a59756e672042656566001b79756e6762656566626967626167732e6d656469756d2e636f6d184079756e6762656566332e303a6d61747269782e6f72671a79756e67626565666269676261677340676d61696c2e636f6d0000104043727970746f436f77626f794f47000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714321d91ef1d84c6471ef2167f2d144a220bdd1dba23aca800112c04f027d5751f9518f021394ae515": "0x04040000000200000000000000000000000000000000135a656e6c696e6b20466f756e646174696f6e135a656e6c696e6b20466f756e646174696f6e1568747470733a2f2f7a656e6c696e6b2e70726f2f1840766963746f72795f76616e3a6d61747269782e6f72670f7676407a656e6c696e6b2e70726f00000c405a656e6c696e6b50726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714322c4a1c125cf6126053336ac8500f1ab1d771ba627a5d555d22eea84ad860a37a137aefa31bba4d": "0x040100000002000000000000000000000000000000000b414e414d495831303030001468747470733a2f2f616e616d69782e746f702f1440646270617474793a6d61747269782e6f726714616e616d697840706f6c6b61646f742e70726f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714323ac9ca334c2bce400a075c48b7985fad91dda0b168b2185958c9fee280f145d2dfe24958a12737": "0x0400000000020000000000000000000000000000000017f09fa681204c454f5354414b452e434f4d20f09fa681001568747470733a2f2f6c656f7374616b652e636f6d15406c656f7374616b653a6d61747269782e6f72671974656368737570706f7274406c656f7374616b652e636f6d00000d406c656f7374616b65636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143245cbbc0d5339b2f4158285b53521c4304c0524941fc1fc64ac08a54b48a45448045248cec18925": "0x000000000000000000000000000000000021504f4c4b4157414c4c45544d41494e284b534d292028455854454e53494f4e2900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432534b4132eff74f56d29c67120f126ad44692c0fba5dc3ca6562485bdfdac135c7e5fb549694545": "0x040000000002000000000000000000000000000000000a50695f3331343135390000000000000c403331343135395f50695f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432540ee9d648f9c790c68164d33e35017d4303436b705e60fa485573f6531d1eb503a6b0b863e63d": "0x00000000000000000000000000000000000859616b616d6f7a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432667cae2c5726a94e544545258bffbd3739e69d0b3681ddfc7da593e4de4d3b709ba9625ad2a962": "0x00000000000000000000000000000000000f6b696c617565612d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714327fdfd66e528b9662d8c4e1c6fbab57ba4df15b8120db4cec5c150371d0755d8ee5312382f47f09": "0x00000000000000000000000000000000000b435249534e475559454e002168747470733a2f2f7777772e6c696e6b6564696e2e636f6d2f696e2f7472756f1740637269736e677579656e3a6d61747269782e6f72671e7472756f6e676e677579656e3139373139393940676d61696c2e636f6d00000a40637269735f76636d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143295418a4c4962cf587a4c5c081f8bf812c0b3824bc9fbd42d39809323488a81769f4699ef2f0e51": "0x0000000000000000000000000000000000056c69616d01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714329d31b54575b3148222952107095b593c6b7b300a4936b35d5064c55f7eded395c3022488510c58": "0x0000000000000000000000000000000000064265636b73064265636b73000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432a8d229e117b02904588a18498ca81fc97612420c9268aee42e4fcd4d33bdcaf34c0246f787e659": "0x000000000000000000000000000000000007736875746b6f107665726f6e696b6120736875746b6f0000187665726f6e6e6176736567646140676d61696c2e636f6d00001040536875746b6f5f7061696e746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432a941ceca936305eef0f6b882a5ab6c4798da18e4dace54e39a476e5299d7d6b5a84181b7495420": "0x04000000000200000000000000000000000000000000044b534d066c6972617900001461727573753239303640676d61696c2e636f6d00000d4070756b757075796f746169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432ae0c69a5fa3b31b4425e543594e2c64686f9be729eb42f8402f00485ba4d778c7965b0c70ffb30": "0x0000000000000000000000000000000000067175657463000000000000084071756574635f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432b4607867325af47e34eeb5e6312c8dabdf13264e7724f9eeda65214e8d45ef1aa63646bc90bd63": "0x00000000000000000000000000000000000d4b7573616d612041636964200000001273746563636f6740676d61696c2e636f6d00000c404b7573616d6141636964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432bdcffa7889f0078cb9e71e14f09dafab743396e139bead9dc662abafc0039c74cccfab1fc7346c": "0x0400000000020000000000000000000000000000000015f09f91bb4469676974616c47686f7374f09f91bb001a68747470733a2f2f6469676974616c67686f73742e78797a2f1d40706f732e6469676974616c67686f73743a6d61747269782e6f72671763727970746f406469676974616c67686f73742e696f000011406469676974616c67686f7374706f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432e3ab575cc440288693796a66327edfad41d99ce9606316637ed9f553d61c43f0b4a658d6b4c170": "0x000000000000000000000000000000000008416c69204e46540101010100000a40616c695f6e667431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432ed1c932b701c300e993f475e1085cfe2d313b1089c3fbc33c78c178ed19bfc94be3d7937709371": "0x040400000002000000000000000000000000000000000a54726164657769736500000019726f6d616e61726e6f757837373540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432f20048368ac529387f657be6913b17c0d5ad2eb24d10cbbd319e142f39c60a000b175744aaad42": "0x00000000000000000000000000000000000a42697474656e736f720a42697474656e736f721668747470733a2f2f62697474656e736f722e636f6d00196f7065726174696f6e73406f70656e74656e736f722e616900000c4062697474656e736f725f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471432fa3d1c089ff9ebfe88f2849c8b51127fefbb618de330c811b4092da0b9272edf2b8b7fddc05c1f": "0x040000000002000000000000000000000000000000000a375468756e6465727300001640377468756e646572733a6d61747269782e6f726716375468756e64657273323140676d61696c2e636f6d00000c40375468756e6465727332000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714330184541fb770392c11ec1e01ccd10cc21bab08d2ce15deaba048bb86b1ddba8fc51e1a988d9a51": "0x00000000000000000000000000000000000b5374726174757332313100001740737472617475733231313a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143303b463054555c594b84205e26b1239950cb66fad5f97873a7a3b60a5b8a0e5d648b07c936f451d": "0x00000000000000000000000000000000000a6c756e6172747970650000000000000b406c756e617274797065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143305daa457b057898c8448f9c214a50cf2419b6393994e0ebf1f6ecb2be98156fb611c9300f4075a": "0x0000000000000000000000000000000000064375726c7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143308804a76f50044ce6e3dc917919ccb44e66c8a5d4c693b96265d5e7072433971fb38d083d0587e": "0x040000000002000000000000000000000000000000000a546f6b656e6765617200000019726f6e6e656c73696d6d6f6e733640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714330e295310ab558958d00cc86df5a4d8320764ef4b5f0cf4ff21ebba4355b58a8845814102060d53": "0x00000000000000000000000000000000000b5a756b6920426c617a65000000154a746f6b616e363940686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714330f2a703c07a43ded1d56154af1862efb63fc12298d73411b024a7b5312346ca95effe7011efec3": "0x00000000000000000000000000000000000e4a6f73696168204b6f747a7572144a6f73696168204a616d6573204b6f747a75720019406a6f736961686b6f747a75723a6d61747269782e6f7267184a6f736961686b6f747a75723340676d61696c2e636f6d00000f404a6f736961686b6f747a757233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143319feb5b0bf9d1f5001f6559f948d59e184101e646c568bb7ef13efb4db683d7a7ec3addc20913d": "0x0000000000000000000000000000000000084c656d7a79706f00000000000009406c656d7a79706f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714331a1a8d88aca78396f39b336285f5069eae5651dd6f48e1552d55939e6175f0321becc3f1b2ef72": "0x00000000000000000000000000000000000954656154726970731154657265736120416e746f6c6968616f197777772e626568616e63652e6e65742f746561747269707300197465727279616e746f6c6968616f40676d61696c2e636f6d00000b407465615f7472697073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433370a1e53cb424dc47e87dfcd927cc014340f95d4a35f94eab0a418753ef596364955a0ffd85e00": "0x00000000000000000000000000000000001d4c6f6e67204e65636b204361706974616c204d616e6167656d656e7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714333ac2982066a85918363192e42fe9184f072cb098189ccef8150287fbaf0014859917c0aecd4e65": "0x00000000000000000000000000000000000867656d626162610b646f72756b206f67757a127777772e646f72756b6f67757a2e636f6d0019646f72756b6f67757a4070726f746f6e6d61696c2e636f6d00000b40646f72756b6f67757a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714333c08553d75ed2cdab8ba7a028d62fe9a5088e46acdbd2039f01abd8baa7c695d9377661c3d406d": "0x040000000002000000000000000000000000000000000664616b6b6b0000124064616b6b6b3a6d61747269782e6f72671464616b2e6c696e757840676d61696c2e636f6d00000840646167696465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714333e68c5f182853d28dd66875b9cd452d1d72193557b6b3dd0d90b32ea9c9e3f45657cf0add29919": "0x0000000000000000000000000000000000035430000000000000084054305f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714333e840aee386d7c1e0cc20dbeeb37538f83781aec7f2f707c665037681183092a9066d0a7c8dd20": "0x0000000000000000000000000000000000105461746f696e65506f6c6b61646f740f5461746f696e65204b7573616d6100001b6165646a656e6775656c652e69636d7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433446753bac3f7d8d49e16d1c4f6a051815c5865058cb218fe7d460fa893907bd0cf8596b493f45a": "0x040000000002000000000000000000000000000000000a676c617373666973680000134064616d6173713a6d61747269782e6f72671a676c61737366697368406879706e6f7469632e67617264656e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143356311bfa9f24835225293d2cd9e6ded0d8c2326e3e83db641db1660dcf04cabf1996e3bb586654": "0x00000000000000000000000000000000000a42554444494553c2ae001e68747470733a2f2f646973636f72642e67672f39485362515137677077000000000c40427564646965735f5374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714336272cd90b6e25af6ef7d80dce5697e079078de31bf5d55ec6b9b19b999062fbee55172c48eae22": "0x00000000000000000000000000000000000e4a42204b534d2057616c6c65740e4a757374696e204275746c65720000186a62406f726967696e616c6368696d6e6579732e636f6d00000a4069616d6a62757473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143370e35af77dde916cf513881f519aa8ffa7b6631e934e954afba13b14629e9683c20d697fbf5d5a": "0x0000000000000000000000000000000000064d6176656e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433816f27c89df87b3c10f599d47ddb88464f7785a359a32f844b08df8b934a997c6dd8c355beba03": "0x00000000000000000000000000000000000a4d6174742049736871104d6174746865772048696c6c696572000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714339633d10397f8728c4631b84124de831cc1d9c74c40b9ff4408faa6ee9bc04dbf133afeac872f41": "0x00000000000000000000000000000000000d4b414e4152494120323135300000000000000d406b616e6172696132313530000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433b7c4e68d541ee54c8510f693bac7c4f1b5eddabe8b18acb255bfbe7d9822f4fcdca22f94809b05": "0x00000000000000000000000000000000000a2e3638204661726d730d44616e69656c2053746f6c6c000017706f696e7436386661726d7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433c1a1b7b16e21902cb7a7443e82f0510532b184fd139194ea5d179542bedea10a473c504ac0ab69": "0x00000000000000000000000000000000000550656b6f07596f68616e6e12687474703a2f2f6e6c742e726f636b732f0016796f68616e6e2e6d65706140676d61696c2e636f6d00000b40736f566572794e4c54000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433c7715ceb944ae1e6583ee03e4f19d6ff1fa84eb9beec7aec0d96a4114a484b5e7a63350144f42d": "0x000000000000000000000000000000000004456b6b0946756e6e7953756e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433dcd2db3d5bedf0c68a732184cd98dbf750752cd4ddfef8435da930c06bcd207c8a1059bea0ad49": "0x04000000000200000000000000000000000000000000046b6d77000000147a6c6174617574736140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433f0f3849914660f162eed692523a2755714b288f9b18c4775c3673da41a7935f7bbf669bc5cc27b": "0x0000000000000000000000000000000000114d61676769652074686520426c61636b0000001b6d61676769652e626c61636b406d61696c66656e63652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471433f1232919bc79e13a81aea610fd2332295967d1c7846599774a112f2d6cf7e3ebe92392b7b17779": "0x00000000000000000000000000000000000661f09fa5a900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714340a8e74a21cd5fa14bab5b2a35355fbaa601d9ec4976e05b881f53b5df7e61c56b7a41d0b987733": "0x00000000000000000000000000000000000f48797065204d7974686f6c6f67790f48797065204d7974686f6c6f6779000019687970652e6d7974686f6c6f677940676d61696c2e636f6d00000f40487970654d7974686f6c6f6779000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714342142ada362a590fccd142fbfc7d9a3b55795804456d22d515ad559a57d7e6e2d95c10b42e30c1f": "0x00000000000000000000000000000000000b4f6e697a756b61313731054d616e7500000000000c404f6e697a756b61313731000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143422f12ebd49b52714cae80b8974ad74a47ee2f104c029601bde0cb7345bb040355a0f89d9745f4d": "0x040000000002000000000000000000000000000000000d4169722050726f746f636f6c094a6f7267652052451061697270726f746f636f6c2e6f726709633474616c797374166a6f7267654061697270726f746f636f6c2e6f726700000d4061697270726f746f636f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434268d32efe050e902c28aa0f96968db5317f8a199297ba47b1d11cee314125f12fa09cd1e5d1147": "0x000000000000000000000000000000000006596f68616e0101010100000940617269796f6170000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714342d10fd36c3ac43cec9484c231e2d686bc8932300191a43fa515f95c02ceebda09ad8d8f5fc5305": "0x00000000000000000000000000000000001754696e6b65726e6574205465616d204163636f756e74000000000000114054696e6b657250617261636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714343126692e3c2e4112d49078cd721faa2f041d0cf96e0d8194561fdcb4ced457270e52f209e76c0f": "0x04000000000200000000000000000000000000000000064c6f67616e000017406c6f67616e3a776562332e666f756e646174696f6e1378406c6f67616e736165746865722e636f6d00000e406c6f67616e73616574686572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143446a63253264d390c44b382fcf02cb9140cfe395af7409c9dcf90111a4178c91f9f4b72c0bf6527": "0x00000000000000000000000000000000000c537061636520526f737369001b687474703a2f2f7777772e7370616365726f7373692e636f6d2f000000000c407370616365726f737369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143480366b70f0bdd226bde67388e055556db32212b34a6b54863a68bde20ee8ac3237c2f8c7e0d748": "0x04000000000200000000000000000000000000000000096e696674657374790000134065656e6e6f6f3a6d61747269782e6f7267116e696b6c61734065656465652e6e657400000a406e69667465737479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714348d4ac14c12c66a52399f4bea6b67b35c699fa9e62d9e0dd0df8e6b77827f3a597ad59ca120436b": "0x000000000000000000000000000000000008666972656b31640000000000000940666972656b3164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434919c833ac161e16244de863562c83bef71d904006f17e4ac8c8d48aa254488993a007ea3293c67": "0x0000000000000000000000000000000000065265656365065265656365000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143493fe8d1494832ec62cf673ac24528062ca2dfebb72f5d32a0b562620536abe72a8fb7fcdce2c54": "0x00000000000000000000000000000000000854617261676f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143497da8d6cf4d6517ef2c40e61477ca83ac11a69a7d3700758cd7c80fd351b942f33a9860bef5c57": "0x00000000000000000000000000000000000a56696e796c73616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143499871fa32ffd0568060f25d5e2559890850d9e7f3090d2892da1bf44ff49e08d879139569af157": "0x0000000000000000000000000000000000066a6f616a69001570617261636861696e6d6173636f74732e636f6d0000000010406a6f616a695f6e616b616a696d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434a85255605692712c9ff1d449d4a433f155b6e0da1c283fab4c3269e4495779ad6f0a29cdf6b170": "0x0000000000000000000000000000000000095061646479626f7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434bafa4989ae96d2126d0c2d4f0884c2e829cd7f63235323c66f7c19cec693117810ac06918297f2": "0x0000000000000000000000000000000000055269636b144d79206361747320616e6420726f626f74732000001b317261662e636f6d2e38382e3838383840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434bd1b4448aed1acf00168a3d082a8ccf93945b1f173fdaecc1ce76fc09bbde18423640194be7212": "0x040000000003000000000000000000000000000000000d506172614e6f6465732e696f001568747470733a2f2f706172616e6f6465732e696f164070617261646f7878783a6d61747269782e6f726715737570706f727440706172616e6f6465732e696f00000b40506172614e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434c19217b89473a6fcf0d5eccb7d0f8a0aa8a7b204db27cb8428c6576ad7bae55f194238c2aea53a": "0x00000000000000000000000000000000000a456c6f6e204d75736b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434cd31c4c02baaf40845506f4ace125170d1d1861cb0deac761cfe2b3538d3b80fb4feb465d9885f": "0x00000000000000000000000000000000000b497361616b204c69656e0b497361616b204c69656e1d68747470733a2f2f626561636f6e732e61692f697361616b6c69656e0015697361616b6c69656e3740676d61696c2e636f6d00000b40697361616b6c69656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434cdf837d56a264302302a200a9ead164617576a79dded74ccf9094d6222cdf93ed575422e9f5837": "0x04000000000200000000000000000000000000000000136f6b74616e6f646573206b7573616d6120310000001661646d696e40736861646f776e6f6465732e636f6d00000b406f6b74616e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471434e1695e7aec00cd2470066d3011ff4f5a582dc406244cd8ada9972cbc09197c4f746b3cd951fa47": "0x00000000000000000000000000000000000d524d524b2050686f656e69780000000000000d40307850686f656e69786578000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435050fd58a5fec6ccad8f26d3a6ce0ccd4aa88ef73904ed673267c502f9d1704c8842715ba7ef33d": "0x000000000000000000000000000000000012496e7370697265207820524d524b2023320101010100000a406363776461766964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143512543d0def14a69a569de2e5bdfb09afc678d03cf44e576409c90326bae832fa88d114efcc2f6e": "0x00000000000000000000000000000000000d4d69636861656c204b726f7a0d4d69636861656c204b726f7a2168747470733a2f2f7777772e696e7374616772616d2e636f6d2f6d6963686165001b6d69636861656c6975646368656e6b6f40676d61696c2e636f6d00000e406d69636861656c5f6b726f7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143513a7e35abd2c67c46a6bab44a8c15f7c71fc8abbde63bf128fcd626e328b351f8c2861b1183318": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435262d5febf811713c3defa1c97906bb8d689ff9791cfa1825a8ef5e3ff2640d5f76cefed049cdb2": "0x040100000002000000000000000000000000000000000d5562696b204361706974616c001668747470733a2f2f7562696b2e6361706974616c2f1840616e756e746a6f637572693a6d61747269782e6f726715636f6e74616374407562696b2e6361706974616c00000d407562696b6361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143533fb45c1708948625a907225b8ed830c16996d75cda73ef03750b535a6d83ca2ba1246be2dd424": "0x040100000002000000000000000000000000000000000ef09f8fa2204d49444c2e646576001168747470733a2f2f6d69646c2e64657610406f6b703a6d61747269782e6f72670f68656c6c6f406d69646c2e64657600000a406d69646c5f646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143536b008c8bdf5eaa8c65922638840726e9b9203f89734be64b61b2e50cbc85a2d8eb147032c793f": "0x04000000000200000000000000000000000000000000044e4c5a000014406e6174616e6c7a3a6d61747269782e6f7267186e6174616c6164617a6c6174614079616e6465782e727500000d406e6174616170706c653133000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143557b2fa873c85d70251da37e1b58a76ce238547801127124fa17d3010baff384a2da3bd52961257": "0x00000000000000000000000000000000000f4e46547320464f5220434c4956450000000000000f4043727970746f436c6976657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714357f962bde6d00d270b553b4cbd93585c4dc2b13699e960a1f8fd5f31f50f304106a2bb8aa2cad64": "0x00000000000000000000000000000000000b727566696e6f66756d6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435868ac081666f4192f0611c424502b047a7052dbd07846e2d01f757a99db50b825984409b44cf6d": "0x040100000002000000000000000000000000000000000c44535256206b7573616d61001568747470733a2f2f647372766c6162732e636f6d001776616c696461746f7240647372766c6162732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435891656bf938dec687940be7bb769432186706f4e9167f078bc2f092bb445c6f2fd6c617f64e556": "0x000000000000000000000000000000000009325468654d6f6f6e145374616e69736c6176204b6f6e6f6e656e6b6f001a40737461736b6f6e6f6e656e6b6f3a6d61747269782e6f7267186b6f6e6f6e656e6b6f7374617340676d61696c2e636f6d000010406b6f6e6f6e656e6b6f5f73746173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714358c4c1a81950208d4b4f2d7581dea1c5b32d601fea80468da90b7c8a66ba5b8ee0612c0b368d363": "0x0000000000000000000000000000000000074a757374696e074a757374696e01010100000c407a65726f70726f6f6673000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714359d405fa784835ea8a89367cac10048b8e025cda5e0e391f4664b4c97b50377685e65ba09a5a460": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435a390c3506c1387482a9a411b630d2c3f850f435c4566a6a93143422e6cce181320f022a7451236": "0x0400000000020000000000000000000000000000000012537465616b20e299a8204e6f6f646c657300001e40737465616b5f616e645f6e6f6f646c65733a6d61747269782e6f72671a737465616b616e646e6f6f646c657340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435ae67dea62435324ccd96ab1b42e8a1a0cf69f0eec21200f9a8095c4da99f44d14c5181f3955a07": "0x00000000000000000000000000000000001154686f6d6173204a657272796b736f6e0101011d696c6c7573747261746f7274686f6d61736a40676d61696c2e636f6d00000c40544a657272796b736f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435ba3891cd5a1f1af4d1d7ee3de4691a94c7691da5d29681cf0c7e01b283c8741c32d6e712fdfc2f": "0x00000000000000000000000000000000000752796f7368690000000000000b4045734a617966697665000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435c408ac02c2a02dfae63fdb20e3ec7589586b14ea019731b5089e2d1b22a7911e48603a5939780c": "0x040000000002000000000000000000000000000000001df09f8cb2f09f8cb3506c616e7420412054726565f09f8cb3f09f8cb200001940706c616e742d612d747265653a6d61747269782e6f72670f6c6a7564766140747574612e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471435dd86d8f494ed5b3a33330086b97b130e60e53e5f19a7aefd249bfe935abed57adb19fed0525074": "0x000000000000000000000000000000000004417368074173686c65790101196173686973686d697474616c383640676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714360a99286860e95d9e3209ee615fbeeb2803b78f79e38d2750b261d2cdf03aee378953ca5187702b": "0x00000000000000000000000000000000000953696e6f7661373900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714360c398fd5e777baf6d6531d9623034efed118d00dc62831eb6f017dcb45d66ec6af44947ef41431": "0x04010000000200000000000000000000000000000000064461617665000000176176696461636f6e74726f6c40676d61696c2e636f6d00001040426c6f636b636861696e65723931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714361c04bb87dbdc8fded1ee76b3793ee4765d0e4ae3810234e2bdbfa5b7b9368d53e8097269106d53": "0x00000000000000000000000000000000000a4d696775656c446f740000000000000c404d696775656c446f7437000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714362e63bff395d5365ee1d8f4e275365ce386eca5dced8da68495954da5df694191446123b64d3950": "0x00000000000000000000000000000000000c42656172204772796c6c7306526f706572010114642e726f706572406f75746c6f6f6b2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143664fd682b63101efa1946d3fbddce1df50333701d2a14f895517f6c3144bfaf0b5ac25892f23672": "0x00000000000000000000000000000000000a43696369205279616e0a4369616e205279616e00000000000c406369616e7279616e3932000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143673545187abf2d44221843a04508635174403b3840ebffbc6c5f487373a75507291fe72019b8421": "0x00000000000000000000000000000000000a547269636b737465720b566961636865736c61760000124f72736f6e303640676d61696c2e636f6d00000f40547269636b7374657230363036000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714367c0b2407c22e99e22baee6a790a63088620f7483290c83fcb3337664866cd8d239568f7554bb14": "0x040100000002000000000000000000000000000000000d4a6f7365206e6f2d6e616d650d4a6f7365205261626173736f1868747470733a2f2f7777772e7261626173736f2e6e6574184073656e7469656e747275653a6d61747269782e6f7267116a6f7365407261626173736f2e6e6574000009407261626173736f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436805becc0cd7ecd46da7c288e4b28a5db64dbd221bbb75850708c556753300df83dd36b4c31c37a": "0x00000000000000000000000000000000000e50696e6b6b75726f736869726f054e656c6c00001c4e656c6d61727973676f6e7a616c657a406f75746c6f6f6b2e657300000f4070696e6b6b75726f736869726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714368ce1bdc40db94c34f589d251903b0ac5a22b1d13d54696fba34b77f5d21f5244de907171144763": "0x040100000002000000000000000000000000000000000850686f656e69780000001974616b65616e797768657265343540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143698794decef314ba1ada2749f3674b54120e643601edab41454b61285f7b1cbc38fa55f3f94ab5d": "0x04000000000200000000000000000000000000000000066a6f6e61730000001e676568726c65696e2e6a6f6e61734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436a17a0db79ef688c664fbde2dbcea2d4180fc9e285ac56ecb6f89a9b88cbee9b407bbceea7da912": "0x04000000000200000000000000000000000000000000084361626c652d58000012406361626c653a6d61747269782e6f72671e6379636c6f707373756d6d6572734070726f746f6e6d61696c2e636f6d00000f4073756d6d6572735f6361626c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436afe30a6f10936740d5602a0093ad63f7581091f78e184f8095d3796c36087d4b663b929dba6002": "0x00000000000000000000000000000000000d6b736d2077616c6c6574203100000014373337314070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436b6b4230572c15c9ef933abec7bfe3aeefa46b090f763be83a92b954ad2ffb6460dd0cf21279e22": "0x00000000000000000000000000000000000842616b686d616e0b566164696d2042616b6800001a62616b6874697961726f763139393240676d61696c2e636f6d00000b40566164696d42616b68000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436becd4b5e8bdbbe828618dad92559461b479508086bc781d88434e5372229cf66ffc887672e9b34": "0x000000000000000000000000000000000009636f6c646d6f6e6b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436d932ff657abe1ab25aad24c981efce7f02bb55dd5a4f1628f46162e297dca06eb78138ed10ba44": "0x00000000000000000000000000000000001942756666204368696d707a20436f756e74727920436c756200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436dfb954fb0e362388c0101e6310fd486b69ae18fae2985fea205d8a9c6de956070d71a69a8d3f66": "0x040000000002000000000000000000000000000000000a43525950544f4e594300001240626f6764693a6d61747269782e6f726717696e666f4063727970746f6e69632e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471436fa711136f55b2b60021c1dff88ff90ebd476b7bfc172d30c808f1629ef5df7685da36526e79a54": "0x00000000000000000000000000000000000f496c61696a61204d616b656e7a690f496c61696a61204d616b656e7a69000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143719f7536919e4c0b2b3d5e18f8226115c2327ded2029a6308b4e8274f0b5f529b3a6e58dec46176": "0x04000000000200000000000000000000000000000000086d65643076796a000014406d65643076796a3a6d61747269782e6f7267146d656430303076796a40676d61696c2e636f6d000009406d65643076796a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143721f074825b67fc14e5b21d2eee0865adfb8783ac900540d67f0a89eb6881e77dda91d509398809": "0x040000000002000000000000000000000000000000000b476f6e74614a6f6e657300001740676f6e74616a6f6e65733a6d61747269782e6f72671c6172747572676f6e74696a6f4070726f746f6e6d61696c2e636f6d00000e406172747572676f6e74696a6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714374fc4337ebaecf75651449de27895f5da18dff76cf3fa3f1b1cf468b873d7a3e16adf7fd5187d55": "0x04000000000200000000000000000000000000000000094c454d4f4e4f4445094c454d4f4e4f44451a68747470733a2f2f6c656d6f6e6f64652e66696e616e63652f000000000f404c656d6f6e6f646547726f7570000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143753decbc1ae388b6849627c337067117e864eff154c6125539fa6e4eaa980712e7594cf78447874": "0x040100000002000000000000000000000000000000000e416d696761205374616b696e6700001940616d6967617374616b696e673a6d61747269782e6f72671a6f70657261746f7240616d6967617374616b696e672e636f6d00000e40416d6967615374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714375546d9339430d36aa9e19b08ef554ef0b123940b685c0d64eabd9a1ec487e43bb7e1f3d981c062": "0x040100000002000000000000000000000000000000000e434f534d49432d474c4f42414c17436f736d696320476c6f62616c204e6574776f726b731668747470733a2f2f636f736d69632e676c6f62616c1840636f736d69635f746f6e793a6d61747269782e6f726716636f6e7461637440636f736d69632e676c6f62616c00000e40636f736d6963676c6f62616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714375605537adb7dfd3d6d2d20735ec00c7753d3e6071ad1e2280288a98d7d89c2a2b7fe08bf6d05bd": "0x0400000000020000000000000000000000000000000015506f6c6b617363616e20466f756e646174696f6e14537469636874696e6720506f6c6b617363616e1668747470733a2f2f706f6c6b617363616e2e6f72670013696e666f40706f6c6b617363616e2e6f726700000b40706f6c6b617363616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143757d549ae01bcfef051c7e4fd453fe6e12e042c745c19c8eac609babbb08cbc1c469a06d3aa9f31": "0x0000000000000000000000000000000000097370696e7a3830380000000000000b407370696e7a3830385f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437635025e9b9216a08323e67f700f051d8178b6c4d82c7b2b8c9c3972f44e6dc368eea43dbe9c723": "0x000000000000000000000000000000000012736861776565656ee5b8b8e794a8444f5409736861776565656e000017736861776565656e6368616e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714376fe373bcf08e5136b08600b83f68dae5db739d3102ef8c8f0534ed6739d2c2c9406bc5e0cd5614": "0x0000000000000000000000000000000000084d465f313333370c5375627371756964204f47107777772e73756273717569642e696f000000000a40495f313333375f49000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714378b219e43b8dedff0fd6298e6d06eefc52fb2f12dc1a6ff9e8958ac2a3efebc7f5673dc33808170": "0x040000000002000000000000000000000000000000000545646765000000176a61636b736f6e73656467654070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714378e64dbe1bafe2d68d2af8a0969437cbf470fcbc5ec5be7fc7c2acc6cd55f31e218b313fd1bbf7c": "0x0000000000000000000000000000000000134b7573616d6120706f6b6c61646f742e6a7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143797aae91cb5418606bc6642d5cf9a96b25c4509ea48bcd739b9526d223d03db0fae3782647a914d": "0x000000000000000000000000000000000009586f6c6169646572074b6972696c6c0101146b6972696c6c5f73683838406d61696c2e727500000a40786f6c6169646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437a030aa0334d1657a6d8b7ba3e9dc84d388f900d7a6d7eba875584a4230ba14e5923703d344ae59": "0x000000000000000000000000000000000007436f6c70746200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437c6690c1899a9f13208723ec642760b572b0ff8037d63d49f4d2e95875027fa85080cdff65df810": "0x00000000000000000000000000000000000d50726f6f666f664368616f7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437dd5e6545f30f91146ebb6c9c8a8953adc846bb66a7067792d2b79480f784b77da11f0556b05038": "0x0000000000000000000000000000000000055361626908536162696b61680000117361626f6f6368406c6976652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437ea3876caf984faa2a383db2910f8be8539704063de71c60aa9f4d2509eabc5ec04acd7d7601e4b": "0x000000000000000000000000000000000016496e666563746564205375627374726150756e6b73002168747470733a2f2f696e6665637465642e7375627374726170756e6b2e636f6d000000000f40496e66656374656450756e6b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437eabe2d897b2b72548da96d92f51656ca4932bec228b08d0a0d42a55ee6dfdf7d674bfab3509e4b": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32370f42696e616e63655f6b736d5f3237000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437f4c44a1802b5597a079b843efdcc1361e62bfe5767fd1f49ea2e255cc8b517675d8b33cf231d64": "0x00000000000000000000000000000000000c546865417274426f79797900000016746865617274626f79797940676d61696c2e636f6d00000d40746865617274626f797979000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471437fc013628a8c12f22fff76bb4a0a5d66cff0392dbc083abbac3b3046f6fcc328abf0ddd16ca0837": "0x040000000002000000000000000000000000000000000f53696d706c79205374616b696e67000000197374616b696e674073696d706c792d76632e636f6d2e6d7400000b4053696d706c795f5643000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714380d8f9827969150946e7b9165c3228654b593ea90a5130b0f137fef6f8af691990b4d4ac0b27076": "0x000000000000000000000000000000000007414c4144494e07444d5954524f010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143815dfeb687a9a1a2a951179aed88b7e507173ad199175237ae2c4861d242d441a77183975bbb453": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438172c8cfb5a713e5a718199b3c87bd8c24c35f027b2b4ba2789a85782a79cc6a924f9e4241c3005": "0x0c0000000002010000000100c8e6bc17040000000000000000000002000000010010a5d4e80000000000000000000000000000000000000000000000000000000b534b59534b49505045520b534b59534b49505045521768747470733a2f2f736b79736b69707065722e65752f1640762e7265697a7669683a6d61747269782e6f72671f736b79736b69707065722e76616c696461746f7240676d61696c2e636f6d00000d40536b79536b69707065725f001e68747470733a2f2f646973636f72642e67672f6d32794d41776276323300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714381b3821dcc0437820844fd0e3f22f42daca7eca80593433eb14ecb21dd12da7efd2ae70e2f7b977": "0x040500000002000000000000000000000000000000000954686520446f74731254686520446f7473204d6167617a696e650000157468652e646f7473406f75746c6f6f6b2e636f6d00001140546865446f74734d6167617a696e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143820161e5d657db05a63e35210da6bcf2d3ceb1720f65a7ea196cbb946768acaa184c732921c1f15": "0x00000000000000000000000000000000000f4d726973686f204c756b616d6261144d726973686f2048616a69204c756b616d626100000000000f404c756b616d62614d726973686f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143821f1ccdde80ab1e63e926f7d2f4b279925ff3eda433d1c619c315bcb690dd02392fc9cb5997e5c": "0x00000000000000000000000000000000000750726f7475730c44617669642050726f746f2168747470733a2f2f747769747465722e636f6d2f7374617267617a65725f7373000000000d40646176696470726f746f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714382e1e172c05a7dd7e7de858372bdac26ad50af6e76207a55fb089414348a70cd32926e8e9f4c76d": "0x00000000000000000000000000000000000d54594c45522044555244454e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714383198d18bf4db66169b1ca15010ef10b423afee4c0fca7e42f745b39e1fe4197436ec352b7f1708": "0x040000000002000000000000000000000000000000000b54525553545354414b4500001b406665726e616e646f2e726f73736f3a6d61747269782e6f72671f6665726e616e646f2e726f73736f2e6974616c7940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714383d396eac9d6d803aca2dd5f8e9ae8f6c34fdf662ccc8582f19712716ead453187133753461a717": "0x00000000000000000000000000000000000744454442554407446564627564000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143860568a1fbdad6c42b7d1cc48edb9374f8db31026a470a1ec19b7ccdaa262c341e6fce2375d022d": "0x000000000000000000000000000000000009546165546165383200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714386936040fec0a1e4499a095307a2c2c62cb6875915e9a9e2effbe99e2b3c5785dc46a4a57df7450": "0x00000000000000000000000000000000000542616b7500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438696a3c3a114b3a3661355b125f90d7764098692927e1b80a2a8609a90378ff6a7a6689e560a407": "0x00000000000000000000000000000000000474757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714386a2f35e87b835c78283798169eabf7cd6924745cb60df616354b36e53549fd8dd71e815386f525": "0x040100000002000000000000000000000000000000000d45524e2056454e5455524553001968747470733a2f2f65726e76656e74757265732e636f6d2f001c65726e63727970746f76656e747572657340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714388551d2e84f8ac29457c6d96254f5e60f77e53484319beda30e5b83868ee522ed88437a18cd4338": "0x0000000000000000000000000000000000034b4a000000000000114077726974656f6e746865626c6f636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438923e8a514e5d000ab0b61984dfcfe2fcb82147f0a2f00f992fa8a6b5ee81490387f8210a1ab678": "0x040100000002000000000000000000000000000000000b496275696c74726f6d6500001740696275696c74726f6d653a6d61747269782e6f7267176e65696c2e76657263686f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438986317de84f44a3aab02d159dca8d84bc9aea8c42341281111885ff6be86c075ac673b5bf4dc10": "0x0000000000000000000000000000000000134b6f6461446f745f657175697061626c6573084b6f6461446f741468747470733a2f2f6b6f6461646f742e78797a0000000009404b6f6461446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438d4ac73c1121041b656e5ed45717d0c904cd18e4cfa9295f360e1cfb2a6d0a17859d5354118330b": "0x000000000000000000000000000000000004526164000000197261646d656e6163654070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438e0f5c9b6d45fdea0fb0c1cb29f31d2efb81ae72ca3ae59b95bd082afa8c6046ac6ad5245a2ab0f": "0x040000000002000000000000000000000000000000000a417065205768616c650c4761727920436f6c746f6e00001667636f6c746f6e3139383740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471438e3b3fa872deb74a0c4801b6d9b3d5b3a26dae883117f4f56f96585431c9ecac4e1daebbf04c674": "0x00000000000000000000000000000000000b3432304b7573616d6120001e68747470733a2f2f646973636f72642e67672f41587250464a32564278001a4b7573616d61343230436c756240686f746d61696c2e636f6d00000c403432304b7573616d6120000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143904609620d47eabc0256994e3cb4d398c31d072de5bb876fe05d1b958e1d76c70483224c1849364": "0x0000000000000000000000000000000000124d69737465722046757a7a79204475636b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471439091716621f04866c5bab403571753ecc61af53a82d7bcc6fbf910c32bb7984a3d9cf92a9ee7353": "0x000000000000000000000000000000000012706f6c6b61646f742e6a7320286b736d2900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714390c74f4052dd71642a8f4af92bc51e83093eeecb73f2aab526a11c41735ff54d9fc7de54ace5c6d": "0x040000000002000000000000000000000000000000000d50617261636861696e626f790000001e6a6f686e72686f64656c626172746f6c6f6d6540676d61696c2e636f6d00000e4070617261636861696e626f7900106a6f686e72686f64656c233831363200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714391938c738248b0b3c8bfe3979861faf9f62122a79c84cb49ef9ea9e34299af5886f69fb14987446": "0x0000000000000000000000000000000000144d6f6f6e496e76616465724a696d6d79536b7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714393bf648d0b05f8554b568a6e42a8892eca1a8e5c88dd952dde7288d79d35c3b57553767a3987a1c": "0x040100000002000000000000000000000000000000000c656477617264736d6974680000001a736d6974686564776172643139383640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143940c3c215b77b75a45607c284ca4ff60763ec121d5818b4571092c29bb4cd52b33689c17a87d24e": "0x000000000000000000000000000000000008524f5353414e410e526f7373616e612043616e7475000018726f7373616e6140776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714394c7c89d577e2150875ac52744a4a4b13c7ffc879ea121886d94ce994b592f87df88e0943b19e3d": "0x040000000002000000000000000000000000000000000e4361726c6f732053696572726100001c407369657272616361726c6f7331392e3a6d61747269782e6f7267196361726c6f73313973696572726140676d61696c2e636f6d000010406361726c6f733139736965727261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143961067d72d621ce64f1ff58ecb85b5c7e3ed681eb7d40bb52f67d2b918159c277a436ba23aaf975": "0x00000000000000000000000000000000000650696f74720000001a70696f74722e647a69756265636b6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714396327fe5bb731ce1ac32f80dad23cb5f164f496f39291cddfc68ed41f9cb2d57953915c9ddd0622": "0x000000000000000000000000000000000007416973616d610000000000000c40616973616d615f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143977b398db792530b4d42c2aa38aeb839c157991447238edbf1a48f7fbaef96b30c733e769ee1f27": "0x0000000000000000000000000000000000074d61726c7561074d61726c75612168747470733a2f2f747769747465722e636f6d2f4d61726c75614b7573616d6100176d61726c75616b7573616d6140676d61696c2e636f6d00000e404d61726c75614b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714397f26eed6dc09cdae3abb16e30166db6c77a2f24b6e19cc63bd95fc08529bcb05bc71273a762b29": "0x040100000002000000000000000000000000000000000c746d64765f6b7573616d6119746563686d65646576207361726c202d20446176696420531968747470733a2f2f7777772e746563686d656465762e65750010647340746563686d656465762e65750000094062655f64617363000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714398ac470c132d05746cba586963ce742f0f17d705174df4317e773788ebdd7244df0a0ddedcc645c": "0x040000000002000000000000000000000000000000000c4162756a756c616962696210416264756c617a697a204b616d696c0018406162756a756c61696269623a6d61747269782e6f726714616b6461747469393440676d61696c2e636f6d00000b40616b64617474693934000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143992ed165a8d50830a7aadfd3b852856f9ed55fd5f9cac3b392e33d5aa9811376ede585177b14b1c": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f320e62696e616e63655f6b736d5f32000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714399bcc09e0ccb2081e808a04d4fc7cce9919d91092bae1466300cf9d5ffd53cee083b6fb9159b16b": "0x04010000000100fc8d0e800000000000000000000000000000000000000000000000000000000e45787472696e736963732e696f0e45787472696e736963732e696f1668747470733a2f2f65787472696e736963732e696f001468656c6c6f4065787472696e736963732e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714399dd3c4804b97eba095019831a2323d245f465af098b4341a7a1cf39bbc4314b2a78a9299f07146": "0x0000000000000000000000000000000000074f4e44494e34000000136f6e64696e37373740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471439a60ff17fca37777ec07e354ed4f92abdd5a1570470994410ad04181deb63229bd98ff39b73170a": "0x040000000002000000000000000000000000000000000e4b454241422d5354414b494e470000184066617469682e6f736b616e3a6d61747269782e6f72671966617469682e6f736b616e2e747240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471439cea59b0d3d75b0fcf9e23d0dbff2b47a4b7e9663399e393783b37c7f73aa42990494277bb43842": "0x000000000000000000000000000000000013506f2d4b7520436861726974792046756e640000000000000c40506f4b7550656f706c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471439d774c6a4bc08794a87d67106ab1314e759cf2a52c4a124011bfe5dd68d96d5d43cfbf3c2d9c06e": "0x00000000000000000000000000000000000852696164205a6700000014726961647a6770726f40676d61696c2e636f6d00000940526961645a675f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471439dbf6701a95ac8db4d7530c51ef3fd16db8e286712250830f98ad4ca9dc49eea4d8da21c810e509": "0x0000000000000000000000000000000000044b424c000000000000074031786b626c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a0d5ce7b9b42aa8680d49ff8449c4b9fec83868efb25e171d2982ff23af49f0815776cf3cddcb27": "0x00000000000000000000000000000000000a4d6f6f6e726976657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a10e49be7571c32fa2d14476ca490493ebdb00a5ad1c1217d02ed4e100bc74ccd99a9415043dc6c": "0x00000000000000000000000000000000000b656e646f6d617374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a29c46317f4f30b2a2ac2efa266a9b1dee45f418586a55232e8421ecf7f35ba47b3fc09743ba53d": "0x0400000000020000000000000000000000000000000008476f6c6f76696e00001740706170616e79797979793a6d61747269782e6f726711706170616e797979406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a304428675bf6f7e6247d2909686256b09006b07e758ecc128364a926f1223ef04b38628a5a3a5e": "0x040000000002000000000000000000000000000000000f5354414b452048554c4bf09f91bd00001a407374616b6568756c6b69736d653a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a415aff9769824852a7ee3e88746ce662cfc7d016f8ea5c54c90579963c7d43fb7c1e0ee75a7504": "0x0000000000000000000000000000000000096770657374616e6110476f6e63616c6f2050657374616e611568747470733a2f2f6770657374616e612e636f6d00186770657374616e6140686173686d61747465722e636f6d00000a406770657374616e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a4998c1a7d8244c6819b9b3dab3439825f9b076ff1be1f248fe246f6be57b131d7d10e38b08fd00": "0x00000000000000000000000000000000000b4761746f724b6f727073000000186761746f726b6f727073406374656d706c61722e636f6d00000a40676b31385f646f67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a575ad1c2d80a9bde691421928e0c701ea5599bcc8d42231da832509479317eff32f2f60fe4525c": "0x0000000000000000000000000000000000104d4143405a6f6d6269742e696e666f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a5afa2fc0fdc1a0b43edb96243d684d0e67b83708e4d62a75c5da73d14aaf3f40d1d1aa4693f531": "0x040100000002000000000000000000000000000000000764616d736b79000000176b6f736d6572694070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143a631a94e785087a961d31be46eed7329adf7b0fb0c9aab987fa9a7734311077033176b56b36f66f": "0x000000000000000000000000000000000012416c6c65732050617374204c61766f726f15557273756c6120616e642046616272697a696f201c68747470733a2f2f616c6c6573706173746c61766f726f2e636f6d0019696e666f40616c6c6573706173746c61766f726f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143aa2de3f651751e4f433983f54fbdb39a76c4b223c0dd127b57d3f82321fbded49efdefb28429b1d": "0x000000000000000000000000000000000005466579640000000000000b4045757269736b6f3139000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ab053dc6b6a71e1b4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747": "0x040100000002000000000000000000000000000000000f41757265766f69725861766965720b586176696572204c61752168747470733a2f2f6c696e6b74722e65652f61757265766f69727861766965721b4061757265766f69727861766965723a6d61747269782e6f72671078617669657240696e762e636166650000104041757265766f6972586176696572000f41757265766f697258617669657200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ab971e615fdc0ec048320335f4847b229ae3c6484ee07fa89fb804ec120545c3386a4a4d69aaf31": "0x00000000000000000000000000000000000c5374616c69616e6f5f323304504842000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ac96963acc241506a3cdc93de8298ac5521a3d59f0dee37394d4cebac305b27d07669c3a5713a0f": "0x00000000000000000000000000000000000d4b5553414d414e4fc38f444500000014726961647a6770726f40676d61696c2e636f6d00000940526961645a675f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ac99439d3775a97566784d696a177184eea3895409ad8a985b82b72d73881678018bb0a1152fb48": "0x00000000000000000000000000000000000c536572676579204c657267001c68747470733a2f2f626c6f636b636861696e61746f776e2e636f6d000000000f405365726765794c6572674e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ad0b73fd39c50f8202dc1d566cfa4d8a522c4a70f1a6d6361a103c582cbf4e6671b93f2ca081712": "0x040000000003000000000000000000000000000000001150617269747920426565722046756e6400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ae93558a338096bd02437b89f58ab571676fed672f8b53b35626f3c993ed7741985e9f0d7cd8704": "0x000000000000000000000000000000000005506965740b5069657420576f6c66661a68747470733a2f2f6769746875622e636f6d2f506965576f6c0015706965742e776f6c666640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b1b7d5d35c61682a5ce96b7e0f53b8401817a3e592f695c3c268ec05665ca0a4782fc26e5300fd6": "0x040100000002000000000000000000000000000000000b4b4d4c20426172646574084b4d204c6162730013406b656e6f6b6d3a6d61747269782e6f7267166b6d6c6162734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b405b9499dd096722bc38752db2ff96485019da63c5c56727f8e94e3075a20e588a4ac99598b731": "0x0000000000000000000000000000000000054f736f6900117777772e6b72616d65722e746f6f6c7300146f736f696f746f6b6f40676d61696c2e636f6d00000b406f736f696f746f6b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b44d8f3097ee1d8741080ece2c165fb6ed98470e4dcff506788f14a5375a9fc5d21f0f78f16c86e": "0x000000000000000000000000000000000005497679610000000000000b40497679615f446f6e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b484b0dc727b45354825d8d050d0ac046e52f333e820999ac3dacb75f29306eb8233c0caf8ef012": "0x00000000000000000000000000000000000c446f742e616c6572742829002168747470733a2f2f646f742d616c6572742e676974626f6f6b2e696f2f646f74000000000b40646f745f616c657274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b50129d36d8eb2532cd05ac28368e20a8a51527499f368aa8a7d1afa5029b69db39dae229e64673": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b5508ea0182d21940bace52337625d59fb2154473ff9eabedb24ab44499213ceb4eafd361da3b16": "0x00000000000000000000000000000000000d44616e6b527574616261676100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b591f4633ac60568479c8ea5480acca5a847133cd97a87801b6e698a98f2eab0e8e9d5c51b14a33": "0x040000000002000000000000000000000000000000000744725733524b0000000000000744725733524b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b5bb9c0955b82d2c633e77b0ac47351f93a639be30f4496597e4e85bbc90a2980ceb7529ffb9953": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b721e900ffa3873ce292ac31cdc1aba6bc5b19b53e3f294c5da9c70aae9d8525a1f441d3626c57d": "0x0000000000000000000000000000000000086d757269637931086d757269637931000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b79538f38d1f4776a2b8e4592ea3a046666ebfefa1874cd632161ab49fde244017c8cef9924f322": "0x00000000000000000000000000000000000d5368616e652046616c6c6f6e0d5368616e652046616c6c6f6e0000197368616e6574657866616c6c6f6e40676d61696c2e636f6d0000114063656c7469636c6567656e646e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b7dae00d6ad1b52b28d7556ad0d7e6a31273e2c0e81de552104382d675a2445af326525fc81b972": "0x08000000000100902f500900000000000000000000000100000002000000000000000000000000000000000e47524f55502054484552415059000018406167745f7374616b696e673a6d61747269782e6f7267126167745f7374616b696e6740706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b8d9ac488d992b7a4b959e2a5cedaf1e09a5436cc714f79819e5b5b1c67390cffb468ee81ffe479": "0x04000000000200000000000000000000000000000000104e6f7a6f6d692053746174696f6e73000015406e6f7a6f6d6968713a6d61747269782e6f72671373746174696f6e73406e6f7a6f6d692e616900000a406e6f7a6f6d696871000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143b8fa2e75a1b9c5bcea3dabe52b2a665b1e19bf8c6913a5d54e06d6413ca3ddbec8f9a22415ec477": "0x040000000003000000000000000000000000000000000644617669640c44617669642048617769671f68747470733a2f2f747769747465722e636f6d2f64617669646861776967174064617669643a776562332e666f756e646174696f6e00000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143bb0e8992b8df2807e0292c2df794e7aa37c54e9be9ae80026647fbf4449917e4aca2037c3b91660": "0x00000000000000000000000000000000000c436f736d6f7347796f7a610000000000000a404b6163756b69726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143bc4805f1dc5a0b3cc5ce9e629b6758532291eaefea2671334d175bed7c29c805a435857b287b212": "0x00000000000000000000000000000000000a506f6c6b61536166650a506f6c6b61536166651768747470733a2f2f706f6c6b61736166652e78797a2f00156973686974613730373740676d61696c2e636f6d00000b40506f6c6b6153616665000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143bdc67a5cfa44da7f64ff5fb243e83dfb26e2723797c47b9e6b31cac8fc2ef91990d5be45e5cb33a": "0x0000000000000000000000000000000000074b61726c6f730000000000000f404b61726c6f737363727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143c0edca73b5ecdd9f091ff4a3f0a8699289c47578c42557932e775cf7f9c7da0c199c730410ee872": "0x00000000000000000000000000000000000e526f78792773204175726f72610000000000000940526f78794e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143c2cb2eb0335d82a6291b0b86664408338b2fddc2ccc5bc718bc2f197d60ba32e44fd9c942e92501": "0x00000000000000000000000000000000000d417274204f66204d616a6f6e0b4d616a616e20416e69731d68747470733a2f2f6c696e6b74722e65652f6172746f666d616a6f6e00156172746f666d616a6f6e40676d61696c2e636f6d00000d40496d61706f7461746f6f65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143c5c102537d492632e44d899f1c95f9c968cd59399a21a4856d1b0d5d9fae07c1aeb7b4c2c61aa68": "0x04000000000200000000000000000000000000000000074f7261636c6500001440616c6d6172696f3a6d61747269782e6f72671c76616c696461746f72706f6c6b61646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143cb00158aad5ee6baec1abe6e31fe52e443783e67de24e7ee311c1506cbb215881eadc721f142e0f": "0x040000000002000000000000000000000000000000000e4272616e646f6e46696c74682b0000001a637261646c656f6666696c7468637240676d61696c2e636f6d00000e4046696c74684272616e646f6e000d6272616e646f6e66696c746800", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143cdada2ee46b071630d8e67d1a8b9c95fe14553b3fa63f32c8690fc9ae8fd0196f16489252300b2a": "0x0000000000000000000000000000000000054c45443200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143cdcc87649a2d33c3e18ff79478f0555885d9da3b482bbea5930b8b33b47df607855a05848c6073c": "0x00000000000000000000000000000000000848656e676973740000000000000e404d656469756d4d61726b3232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ce6197206f2905cac5e7ba2c1529f9e16e3a920f65a36f2f170522b92e6c37fe26e8a58384a7463": "0x00000000000000000000000000000000001446616e7461737920436c75622053747564696f1446616e7461737920436c75622053747564696f00001c46616e74617379436c756253747564696f40676d61696c2e636f6d0000104046616e74617379436c75624e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143cf08b9f8a98ed5bf88a4006c41081ce901e0a845e8607bce1c81a69897211b9db6e68a3c148eb1e": "0x00000000000000000000000000000000001c446f72696e672d4261657a2d476f6e7a616c657a2046616d696c790d4e69636f6c6173204261657a00001877306d38356b32374070726f746f6e6d61696c2e636f6d00000a406e69636b5f717376000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d1b2413f2986065923a8f80723b86c1305ace998cc4a1b500095196102f5a3889b68a6ba00e690b": "0x00000000000000000000000000000000000d476f6f6e6579205361696e740b4d4461766964204c6f770101146d64617669646c6f7740676d61696c2e636f6d00000b406d64617669646c6f77000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d2247c3cff243e448ed2e907e472b4db96ce361f8e1a346c5af739d6705843e1a48ee9f5eadd22a": "0x0000000000000000000000000000000000082e4368616f732e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d4a43e0b9eb6a1b4a86fd86fbce1384861712946d1aeb1ee810242dcd228026328335634af76f3e": "0x04040000000100902f50090000000000000000000000000000000000000000000000000000000e4175746973746963204170657300000000000011404175746973746963417065734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d54772322b9426d803112054b6f2127db5bf84fae280724596d801671e4de7d1cff4c8d56edd351": "0x000000000000000000000000000000000013e8909de88e89e4bf9de68aa4e58d8fe4bc9a076c696e79696e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d71181b8a809887c0848079910d67af0a8756c87a50adb5c9e5ff410277980ba737025adf71f323": "0x000000000000000000000000000000000009506172616365696e000000176665646961736368696f707540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d7b57c9bab601df742f10a2b57e5ec3247c0ae6da2a2fdb4a731324dc7a2edfe0f4fc761e1a4d3f": "0x04000000000200000000000000000000000000000000094d696368656c6c65000016406d696368656c6c65783a6d61747269782e6f726700000000001336303833373436343939373331313330313400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143d8d6284f9cd655d3ea8ab4d4cb7d18b6a0d8f2555955abfb182af4808dfe1e4418e3e104c9cd07a": "0x00000000000000000000000000000000000d6c656f2d616e646572736f6e0d4c656f20416e646572736f6e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143da0de343db242fb1c384604d84ecd79034f0c19b26752abe03a0db3bf62b5069df96692ff077b18": "0x0000000000000000000000000000000000064c7973796900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143dcc236c1c55df5e202ff21bfa05c35d59be949ddac77d03e49ca8b43ad1d169408b247b13332847": "0x00000000000000000000000000000000000f537765657473206f6620524d524b0f537765657473206f6620524d524b00000000000e407377656574736f66524d524b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143de3c64163d245c278c7e23425c0433a78c7f295bee57069c78743b4630161530af5e6e5ad5a7024": "0x04010000000200000000000000000000000000000000174265737476616c696461746f72207c205a75726963680e4265737476616c696461746f721a68747470733a2f2f6265737476616c696461746f722e636f6d14406d6f736f6e79693a6d61747269782e6f72671868656c6c6f406265737476616c696461746f722e636f6d000010406d6f736f6e79695f7a6f6c74616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143df5621b372fe9b952370afd8038d4fe339fe8ab84ed26748940a72ea12df5cc63bb5b0e3a6bc830": "0x00000000000000000000000000000000000b446965676f5374616b650e446965676f2050657265797261000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e1505ea3181f4d938b56e4773b73ad84537f2a6ceb8623781bc4fde11d5eaf672e88fc19c0f2c28": "0x040000000002000000000000000000000000000000000744656e5055420000134064656e7075623a6d61747269782e6f726715766164696b726976303140676d61696c2e636f6d00001140546c76787947713543427275316b7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e1fada5350d221c002ebf751ae1def13e95b2260485550d8c3dc41390313ca457a0062560483778": "0x00000000000000000000000000000000000e426c696e6b696e2e6368616f730000001f626c696e6b5f6e446f6573446546694070726f746f6e6d61696c2e636f6d00001140626c696e6b5f6e446f657344654669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e2ea95392d7cb335c23c32caa710e0758a3f1f55ec38b4a90b46631bdc96a2b9838c9a77fc1235e": "0x000000000000000000000000000000000007726f6e63686f10526f6e616b2043686f7661746979611668747470733a2f2f6f726e616c6162732e636f6d2f0013726f6e63686f716140676d61696c2e636f6d00001d68747470733a2f2f747769747465722e636f6d2f726f6e63686f7161000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e3e798a3a6296aaf8d542920fa20b0dd5e126de37f7c0142db98b51a6caa4968922467b42b95a74": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e512628d0f746aeb4652c8810763fc9c9e36f67c348508c6880d831885799456555a0316184ec2e": "0x000000000000000000000000000000000006536f4b656906536f4b6569000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e76497ef9205fafb2f0665e547b1ace9b2b87fdc59a2eb376e4f52a6b5776ac7bc879b8416f3863": "0x0402000000020000000000000000000000000000000011494f53472056616c696461746f72203111494f53472056616c696461746f7220311068747470733a2f2f696f73672e766311406a6f63793a6d61747269782e6f72670e68656c6c6f40696f73672e766300000840494f53475643000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143e82b21f8446b3af1eded961809a3f356553dc14f1e93b1cb7e6b7c828e340e10415c09cdb41f86e": "0x00000000000000000000000000000000000c4c616479204b7573616d610752616368656c00000000000c406c6164796b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ea0a0e4b3cccecf1a7d6f18e9791ea8872d8882642f1ef1a567f67d8f4ebbf0e12a5f3a619fef3e": "0x00000000000000000000000000000000000e4b6f6461446f745f706f617073001468747470733a2f2f6b6f6461646f742e78797a0000000009404b6f6461446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ec7ab919f5354868e675e5690eb2ade55d6690e6cbaaca81d24d34c805527c58d648183d74c7614": "0x00000000000000000000000000000000000c4d6f6d656e746f42756c6c0000000000000d404d6f6d656e746f42756c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143edca9b73dc0a5e4e06db2647e73f26d9b6b9d305ef921ae165215b4b7dc6f08b1ce295db0facd23": "0x00000000000000000000000000000000000953757266657273200630786864690101096d407375712e757300000d406d656864696a6169646933000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143edfdd48fc779cd5a80ea94af8a39eb7ba8d9afb913147e67eae84f48aad7b9ce6ee05094fe0394e": "0x0400000000020000000000000000000000000000000005416c6b6f00001340616c6b6f38393a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f15914969e7b002928d0d0ee5f4d524a2a8bf992de4fafb497112bc3498eccdcfc88866bde42c19": "0x00000000000000000000000000000000000756616c7461720e526f76616c20546172726f7a611c7777772e61727473746174696f6e2e636f6d2f746172726f7a61720013746172726f7a617240676d61696c2e636f6d000009405f76616c746172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f1c259322f2c75fc2d6907fd9c5c0a3bb5b8fa55153a9b8b798464f6ea3a540f0a7849f999ffc7a": "0x040000000002000000000000000000000000000000000b74616e7573686136303200000000000000001174616e757368615f363032233932353600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f238aa31c71d3336ca6452fdccbb00af0b245231dff434535cdc7f9a2f2712dbc740e662e9c596e": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34300f62696e616e63655f6b736d5f3430000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f4fdb82e13e4374aba289d29b3dd0dc2d56f7ab2c90a6776431a49723058a7050022fd81d237133": "0x0400000000020000000000000000000000000000000019706f6c6b61646f742d7361666172692d6d756c74697369670a53616661726944414f1768747470733a2f2f646f747361666172692e78797a2f0013696e666f40646f747361666172692e78797a00000e4054686553616661726944414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f67110821e73a29729da928a9148b8da4cdef9bc0f03326dac61d8c5aa0604059bee63df6273e4a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143f766dca042f5e70f69409a7b5a311894e73baf41c5554009645f8c4180a1993ad690721149d7939": "0x00000000000000000000000000000000000e50726f6f6620206f662041727404496f6e00001466657261726938333940676d61696c2e636f6d00000d4050756e6b324d6f6e6b6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143fc75114c6299d4af21febf4202d805c54fc3a74b6d8f2ab070f330fcbd64bf02e1276111baf3967": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34320f62696e616e63655f6b736d5f3432000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143fd042080b18e9fb0f4c5aaeacd001fcf32b29ad902a5dfc489af0dd8b263ea97117218103921ee5": "0x00000000000000000000000000000000000852455354414b45001468747470733a2f2f72657374616b652e6e657400000000104072657374616b657374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ff9e63960b2eb614e74b71c8f5bec8948037d4191173025162d8193d1c6773f7f5bca917ff10c5c": "0x0000000000000000000000000000000000086465766d6f6465086465766d6f6465010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047143ffe32ddffac26d1225c1cf2356a5a5cd7e13c8e5dbee6c4c89e1c5f610c1050131cc58b4d96e75a": "0x040100000002000000000000000000000000000000000943535f417869616c001b687474703a2f2f63727970746f73617069656e732e636c75622f15406c696c69616c756c3a6d61747269782e6f726714663474617469616e614079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714401eb02c77bc87680c6be896b338d1c81b5e1c1629cc6658754b34a7382efa1daf20c8d979004b39": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440211a7f8ab7a9a03c757ba7f937e877ce2171c04b729b5fcdf7bb4d9f11c46dfc50212664e5cd08": "0x00000000000000000000000000000000000f5a6869786920496e7465726c61790c5a68697869205a68616e670000127a6869786940696e7465726c61792e696f00000e406e696b6b695f73756e736574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714402a556db017fb3cf802d69508ee4778ba8e6d8406e28484017a27f50be26df185e2406fcb0b322c": "0x000000000000000000000000000000000007757a6172646100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440506c474710c680becff51276f84146717aee4ee4e9626ae7023246f8dc03548ee313351957a33c": "0x00000000000000000000000000000000000a616c6f74616e67686501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144066c167257e03db04b82783d5d3e2c81f48908d03fd43630deefd23fdb2b7f5c21e322fcf7b5613": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440675f145f08184fd03abd3df52537964270150786182ab41f565027d36f488215c86d5c92e1f329": "0x04000000000200000000000000000000000000000000056974736f000000136974736f3939343340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144076a041f4206619a03297fd2374d7d2f0d1ba272e89e77079b48b402d1dcf36bbec6c7114378136": "0x04010000000200000000000000000000000000000000076a6179736f6e00000021616c77617973636f727265637476616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714408289d96aa87d1172159b34e3f99ea3bb6d0c08bbff4d1d6ac30603b34811e222049cb39d8ff047": "0x000000000000000000000000000000000013e298952046696e616c4f6d697420f09f8dba0000001466696e616c6f6d697440676d61696c2e636f6d00000b4046696e616c4f6d6974000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440972e71eac65ab410c369c571d3b7fc6207371154eb81da418c21b4c96c4382131c09fa94165634": "0x00000000000000000000000000000000000b42696e676f20417274730000001762696e676f617274736e667440676d61696c2e636f6d00000e4042696e676f417274734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714409d3d5d3a1caccf4a2c3d9e33fd1f782dc354599c2f72b160e1d9293ca67e6e907b34061709bb6d": "0x00000000000000000000000000000000000b73616c746272696467650000000000000e405469646568756e7465723138000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440a080abf9c0d1738465abd5a02f5b42b23e323b73e52416514460b9a3e7c34c94ed8d9f986c3d6e": "0x000000000000000000000000000000000008536b616c6d616e001d68747470733a2f2f6769746875622e636f6d2f6472736b616c6d616e1440736b616c6d616e3a6d61747269782e6f726713736b616c6d616e407269736575702e6e657400001940736b616c6d616e406d6173746f646f6e2e736f6369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440a89f3abda82c85983347500922c79e9afb60da250d4dbdff3d8546f1b32f0239a5e8df8b02ea1a": "0x00000000000000000000000000000000000e42494e414e43455f4b534d5f380e42494e414e43455f4b534d5f38000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440d539e41516f26e565c9f20217f385dabb5e252dfcca7cbfcc0b4a260b331e82d39309b42c8e303": "0x0000000000000000000000000000000000074e697068616c0f416e647265772042656573746f6e2168747470733a2f2f676c697463682e616e6472657762656573746f6e2e636f6d0018616e6472657762656573746f6e40676d61696c2e636f6d00000f406e697068616c5f676c69746368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440d54556e8cd2d8b532092745cdf4f2b44e2e540322cd0c7a8a692b6fa5d177ddf17aeee823fb416": "0x04010000000200000000000000000000000000000000144b41424f43484120434f4c4c454354494f4e53144b41424f43484120434f4c4c454354494f4e531868747470733a2f2f6b61626f6368612e67616c6c65727901146e6674406b61626f6368612e67616c6c65727900000c406b7568626f7763687568000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471440ef7feca334f14c4a0eb541fc52db126c97ffd8cd041322b68e9c00b6d46b09d2c852c6f737e45a": "0x0000000000000000000000000000000000084772696e694d65084772696e694d65000015766772696e696d65657240676d61696c2e636f6d00000a406772696e695f6d65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714411a5418773a1a2568f8bfef657c69a5c34721cbaa618ae9eb2108566f9a2606cf5055578e0c2511": "0x040100000002000000000000000000000000000000000f436f6d707574652043727970746f001a68747470733a2f2f636f6d7075746563727970746f2e636f6d0018636f6d7075746563727970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714412792138d96bb58c2b264a56b5eaa7e1f4cf6db61445113e7df7cbfbaf77d7b23887088f629e657": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144140e165d0c0e9dab86111b2d7969eb7c651d4b1772388ca5e595860e6e82bccb903b46fba28c713": "0x00000000000000000000000000000000000c5768616c6520517565656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714415252cc5998dac14e516d9d6527c3bdcc45105195b8e23480bc0f257308b1f4fef03e06efbb1c5b": "0x04000000000200000000000000000000000000000000055245504500001140726570653a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471441681d40d088fef712df12dcbb5083fb5ae84c019e2b22922dd4e87647b0c5569955f40195cbb512": "0x0000000000000000000000000000000000095472656173757279104b7573616d612041706520436c75621b68747470733a2f2f7777772e6b7573616d612d6170652e636f6d001a6170652e636c75622e6b7573616d6140676d61696c2e636f6d00000b404b7573616d61417065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144177d8c48739d4b1602ae92f82bf4f711ac8534b73bc0959cf87cb691c42eb14bffd93d15da51f53": "0x0000000000000000000000000000000000145374616b655365656b65722062792042544353194254435320496e632e20284e61736461713a2042544353291b68747470733a2f2f7777772e7374616b657365656b65722e696f0018737570706f7274407374616b657365656b65722e636f6d00000c404e617364617142544353000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144184ba79c24cf9898ce7f9b6eb21ee076f759396cbac56c8417e38f5a5e93f354da84d6bf20bde62": "0x0000000000000000000000000000000000117374726f6d626f6c692d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471441b31d51b902bf81b44481905d25563efe49d16584345474c8b6127729b934e7b740a9f264d63457": "0x00000000000000000000000000000000000642696a616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471441ca7551fdd5198464bef580d4d5350d51b7aed6eedd24a2f14e9de9a4c438bb91f9d2b57ddc9026": "0x00000000000000000000000000000000000a73616b616d6963686900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471441e29c1629f394e1e4a77c09a5e7cca4340cd6ce8dd3cf6dfffacadaab7bd6581b7ca50959834271": "0x040100000001006c57c10b0100000000000000000000000000000000000000000000000000000d4b657920506963747572657300147777772e6b657970696374757265732e6f72670015696e666f406b657970696374757265732e6f726700000d404b65795069637475726573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144200a83649f12b6d9218a3abca6aaa7cda30f2493e57e5261b060f5f392f2d4cdd9aab3713e33d3c": "0x00000000000000000000000000000000000e4669676d656e7420416c706861001368747470733a2f2f6669676d656e742e696f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144207de929e0c2c7c20f322a0ce33a28f8e0d44accc268eaa77b9f80f421d8e0e1a96e10718dee164": "0x00000000000000000000000000000000000d46726f6e74696572736d616e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144229207fadf4b0c2366c1d734b33c714b0e0e9f164426e66e3bfa97b917b23e5d3674f4a2074f86f": "0x04000000000200000000000000000000000000000000094d6f6f6e6e6f64650000001174656368406d6f6f6e6e6f64652e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714424771d484adc6a72a6f412b15ba9a05e58871913e1db1c5e2ffaa7bc58e5211721e98a03045284a": "0x00000000000000000000000000000000000b4d616e6e696d4d6f6e640d4d616e4f6e5468654d6f6f6e00000000000d406d616e6e696d5f6d6f6e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714425d6aa15789f0c1507bf2acec7efcbdcf09e8ec2187bb87b07ee88825d4b840af4159a30012cf4b": "0x0000000000000000000000000000000000010101010100000a406361626c696e6531000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442661dc55caceeca42a60e286bf3ab5228cc24f47e4087436285f889a306a4542f3e97c50834ee51": "0x00000000000000000000000000000000000451766f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442846f3701313edf5e14105dd8e15633168123d30f93edbbcc5cccc3518791e53cdb9c541cbcd343": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f350e62696e616e63655f6b736d5f35000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714428cc1cacf21d843cc386a98ed8462dcd6df033f115fe1527867c49a2a898280691dc57ab5e63974": "0x00000000000000000000000000000000000d4672616e6b7920467265736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442946832d384cb2c5e1eb942e5f591bc1d902fc6a04dd7ecadf5f4916f2597df0505c6c521412c4b": "0x04000000000200000000000000000000000000000000084649474d454e5400000013636f6e74616374406669676d656e742e696f00000c404669676d656e745f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714429bcc7f376222a2d1bc4259aeb77874ee7ca72a9763d6385763068b56bf47fcabd0d854311ab7c1": "0x00000000000000000000000000000000000e524d524b204d756c7469736967001168747470733a2f2f726d726b2e617070000f68656c6c6f40726d726b2e61707000000940726d726b617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714429c4677f860fc0c88f9c19843d4503698a3cbdb00a6bcf115fd11c36d646f280da7822733a81f03": "0x0000000000000000000000000000000000084a52637265616d034a5200000000000a406a75616e69727566000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442a5466c1294dfdc0a7deeafeecde52fd2ef2749958d1b0e5094c629a355ab52c984116556e5f515": "0x00000000000000000000000000000000000f73696e67756c617274732e6f726706456e67696e1768747470733a2f2f73696e67756c617274732e6f72670111656573756c6140676d61696c2e636f6d00000840656573756c61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442ade399737c4384882a9309f1e5f87abb745dc51d5dcc338e3dbe7b818fd8a9768e27d97e57ec13": "0x04000000000200000000000000000000000000000000084469616d6f6e640000001776616c69646469616d6f6e644070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442b0e5e788b77418280221db3cd2515ba48cff6c400cf4624b9459eca62f30523972ee5b608e967b": "0x0800000000020100000002000000000000000000000000000000001c45535152204361706974616c204e65746865726c616e64732030311945535152204361706974616c204e65746865726c616e64731c68747470733a2f2f7777772e657371722d6361706974616c2e6e6c1940657371725f6361706974616c3a6d61747269782e6f726719706f6c6b61646f7440657371722d6361706974616c2e6e6c00000d40457371724361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442bd7fccd27172c3c0b457c25ea2f71dc18c12a6dfef5c32a1d663269787f2fe0b49b9ec041eba64": "0x040100000002000000000000000000000000000000000e566f75726865794b7573616d61001c68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b2f1b40766164696d2e6d616e61656e6b6f3a6d61747269782e6f726716766d40726f626f6e6f6d6963732e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442c610f7e050710e06b2570a6c00c6e0c418a2fef16ca9c55e7316c995265e99b1e5f15117ee3e3d": "0x00000000000000000000000000000000001553746174656d696e6520646576656c6f706572730f53746174656d696e65207465616d00001c626c6f636b636861696e627562626c653740676d61696c2e636f6d00000c406b6f7265616e5f67656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442d6dbf1184a5e27d45579ae86a4bb29d2440e48a9eed4790411a6a8e8d09413c827504c2088660c": "0x000000000000000000000000000000000007566f6f446f6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442eafc0ff257cf6b6a27e5f57753658d45a60fe2d7f5a2b9bc2e0202ed891a8fc80ad7c27882f448": "0x00000000000000000000000000000000000c4e465420496e766164657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442f7186af73e2c106edfd181c979c11a1d853c8fdef7b18e85ec39bb67ce723130b25fc24232c358": "0x04040000000200000000000000000000000000000000094769734c656d6f6e000000186769736c656d6f6e4070726f746f6e6d61696c2e636f6d00000a406769736c656d6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471442f901039d3431b5a0111975da4d8d0ae457ced7a3628c368ad8a7d089ebbed2a2f2561b0c144236": "0x00000000000000000000000000000000000d496d616464696e416d73696608496d616464696e01010100000e40696d616464696e416d736966000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443031ba174ef004f7e21ab0dcd65abbbf6f37cfde306ea29c7416a984ec5664cd553befbe3cf114b": "0x0000000000000000000000000000000000054d4a465301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144313f37cc5b7356c545b79d13047971ae5df6134fd0e034f99db6b174cf1046764861569f943514f": "0x0400000000020000000000000000000000000000000009726f636b6e6f646500001540726f636b6e6f64653a6d61747269782e6f726715726f636b6e6f6465687140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144315c981ebc9c224e49a94c01d7c0511480422e00ef7030ff64f314591b50d7057deadbd6411112e": "0x04000000000200000000000000000000000000000000074655545552450000124031667574753a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714431c4c64db68d8bc2211d6fce26d7140904357fce2aca5d1e63b362f1789bb6d7dbd848d3df79c65": "0x0000000000000000000000000000000000084d6172636f526f0d4d6172636f20526f6d616e6f137777772e73747564696f2d6967732e636f6d00196d6172636f726f6d616e6f77656240676d61696c2e636f6d000009404d61726330526f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714431fc37d4e65266372f0e8e7a0016e48feebb38705376825b84f27f82c8c108eb4301755293a5274": "0x040000000002000000000000000000000000000000001af09f90a420424952422e544543484e4f4c4f475920f09f90a400000013686940626972622e746563686e6f6c6f6779000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443219b832eb0cea63abe5f0e44b84bebe5b30889223938b97e535b6092c30915e40890f16edd51e1": "0x0400000000020000000000000000000000000000000016f09f9ba1204457454c4c4952204b534d20f09f9ba1001468747470733a2f2f6477656c6c69722e636f6d14406477656c6c69723a6d61747269782e6f726711696e666f406477656c6c69722e636f6d000011404477656c6c69724f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144322706aab5751605e9a8499b030780091dae032059aa6e38cc55ef49a68644a1cb272891b676760": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32310f42696e616e63655f6b736d5f3231000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144336ca0e09f590ffb45bcaffa67198b19865dce57baff03eff340df85c52e256631ec9c4b96ad275": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714433a39cb0e6f7bc112319b29cc9112a1be246421e75de0339021bfe1ed7b06541d969acc17a6de40": "0x000000000000000000000000000000000007736174656b7800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714433b1db524879af62af538e357eed0b3fe92c64dda50c356a3359a8c38940765e48c8a830279bc2e": "0x0000000000000000000000000000000000054b61727000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443496d81af6ed7735855f6f9634a68990a917f22cda160e53f14a0bab251926d946650b4df53412f": "0x0000000000000000000000000000000000217370617a636f696e5f4368616f7344414f5f496e74724b696e745661756c7473000000137370617a636f696e40676d61696c2e636f6d000008407370617a7674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144352c02456f8db9cda79564e50582d71b58582eee69b5eb4b01441d3e40edc2cd2eeaeef3f6d2963": "0x000000000000000000000000000000000007636872697a790000000000001040686579697473636872697a7a6c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714439dcb29ce5bd09bf622b449b4731ab216a7b8c8845323a004906934f028e2f16c5277b96e86c77f": "0x0000000000000000000000000000000000094d7255706f6e6c7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443a5a3e7bfd489c4deb05fb7623d20882b463209bd7e6a20a1ed0ec1929764ec119a616abe71e642": "0x00000000000000000000000000000000000b4b656c6c204e6f72616c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443bb1018fc2bff6592536c5469fd64b2adaee0a10c5936bb0d4c8e4c5e4d31185fbc0c9136e1f205": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443bb2518f5dd346208bfa1909b08831184ddb72b2bcd671adc761e4cfecc24b725be3f5a24cfe94d": "0x00000000000000000000000000000000000d4d722e2043616e64796d616e001b7777772e696e7374616772616d2e636f6d2f6368696c6c2e6d65000000000e406d725f5f63616e64796d616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443c19ff4a42bbd9874372fc06884fd5e1cee0831c88891f0e2941ee0017d3125724105d1b6b4f776": "0x0000000000000000000000000000000000074b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443c2329d3180137656c0b55c865aec0af22f6d39e01e0d943f3350933058f3b56807c89476e5125d": "0x00000000000000000000000000000000000864696c6c6f6e780101010100000a40584d696e676b6169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443d5af598339f8ef98796948d017243ad1b85af8cfc8bac2ef20e3b7e867bb096c5cb847e3562078": "0x0000000000000000000000000000000000074b75246b757301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443dd79f4e889aacc3c3ac3653a4bf9a728758393bbc9bdc5ca31e29aed46a1585fd3d4910257c821": "0x000000000000000000000000000000000007746f6d616b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443e9f94129b67458622984b619c81ee9a2a84c6ee36fa79b67b535ef31d7ee0b668d704b00c32f69": "0x0401000000020000000000000000000000000000000013526f626f6e6f6d6963732e6e6574776f726b001b68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b1723726f626f6e6f6d6963733a6d61747269782e6f72671961646d696e40726f626f6e6f6d6963732e6e6574776f726b00001140414952415f526f626f6e6f6d696373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471443f90c79a74ca36eecafd4305f2a5592eb1f819e05e7ed312282c5d86f284ed0dc5043e8715df14f": "0x0000000000000000000000000000000000084b7573616d613200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714441abecd8f673549225952e5bb10c80a33d25cdd180dfe6dddc0cd934560c8f6dbeb52edbccb054a": "0x04050000000200000000000000000000000000000000047377620d53657268616e20426168617200124073657268616e3a7061726974792e696f1173657268616e407061726974792e696f00000e4073657268616e776261686172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714441fb0b93c3c68999c036f0e22d9e0a68b1dc5018d743fb85f400f2e5e213561d03b4c966b131a64": "0x00000000000000000000000000000000000b4b7573616d61205a6f6f001e68747470733a2f2f747769747465722e636f6d2f4b7573616d615a6f6f001a6d616c696b62726f7468657273647240676d61696c2e636f6d00000b404b7573616d615a6f6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714442352000e64552148dd734e16f0815537f6bb9a491f1d76ecc83f46c6efe47243f6ac87ae88730c": "0x000000000000000000000000000000000008554d46204b7573000000116e6577756d6640676d61696c2e636f6d00000c40726f6f6d317a65726f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714443156d8215300f5028613450f87010f24fa491fc01aee1a9a00649bc3656cc95623caabfd99df6c": "0x0401000000020000000000000000000000000000000007316b4e6f6465001368747470733a2f2f316b6e6f64652e696f2f1740766c6164316b6e6f64653a6d61747269782e6f72671277656c636f6d6540316b6e6f64652e696f00000840316b6e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714443ad277a8dbe9aba845ea35913a0fbdec49687ebc5b1579bb632c080ce61b02919ba40bcf889276": "0x040100000002000000000000000000000000000000001056616c696461747269756d204b534d0c56616c696461747269756d00001656616c696461747269756d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444509eb7f7220ceaeebbde3ff2bb37ca11414154e92c0521ac8051ea48d0d84b39714b2347763648": "0x04000000000200000000000000000000000000000000094d4554415350414e00000013646572656b406d6574617370616e2e636f6d00000d406d6574617370616e5f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444555228869870c2e666c8204234e3e9dc671cc875c4f22316e6a7b67bb8b0538d8d77674468ed50": "0x04000000000200000000000000000000000000000000054178696100000019617869612e76616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144456b32654fe47f91a8ab26aba64d6176b6aa462a2a7ef6252ca1063cf978dcb6f6c64fec81e7861": "0x04010000000200000000000000000000000000000000074534592e696f001368747470733a2f2f7777772e6534792e696f13406534792e696f3a6d61747269782e6f72670f737570706f7274406534792e696f00000740496f453479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144458ae5cd71591333641233f6aa39d0515608c15dc001611a7c5fdf5f5f76fe72d8f8348b0596f09": "0x00000000000000000000000000000000000c5669636b79447265616d7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714445f24d9b88c5e2770086e7c9eb19ebdb3e7c492dce59dd3f895c2253e7a838d6dd746503bbdbe44": "0x0000000000000000000000000000000000074a617a7a75730d416e6472c3a920446962c3a9127777772e6b616d65616c6162732e636f6d000000000c40616e6472655f64696265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444687e96c8cb00dea2fca1a6c0cf0568cd25a13786689400f1a7dbc63ce2b16a5568b1e88576a307": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714446c9be06dc89e3a8c57b6eb2ab6d89e5822919b8d492d510e847f4d60c8380d0265ef7804774a03": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714446ced0dc56cc8bf082dfbe87772fa0f7d714b22e0f43cf978a8b588035950aac6f9d14561ddd831": "0x000000000000000000000000000000000017426c7565517565656e20f09f9191f09f9299f09fa68b0020687474703a2f2f6c696e6b74722e65652f42617374617264467269656e6473000000000d403078626c7565717565656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714446ecde49f31e64a2a3fa40b4085d8adf7dddf3e3073d45d43cc9e55de72822990fa2d84b18faf20": "0x00000000000000000000000000000000000479616f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444781ab96a799989aea86d60aba408d8d30ec708eb6e322d9c9eac484e957053efab66f1ee4e0f58": "0x04000000000200000000000000000000000000000000094252415f31362d4400000016637074636f7272656f6f6640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714447de9973eed816a0c4e7bbcd18257cff6e835218d6e035cfe29dfdda404abd34f0107379cc9b239": "0x00000000000000000000000000000000000b4d6567616e20536b796500001b40746865746f6b656e626c6f6e64653a6d61747269782e6f7267176d6567616e736b796570686f656e697840706d2e6d6500001140746865746f6b656e626c6f6e64655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714447e1613a9d973af08d48a00b01356b80f40e50f281c2cda9e858f45a1bc8e989b3eedfb27dfe044": "0x0000000000000000000000000000000000094252415f31362d4400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714448ea7872d496c7fe40898073d5ab4bfb056778a95be2d797fb929315d0a0e31ca415e9f37a1d726": "0x040000000002000000000000000000000000000000001447494c204655545552c38d56454c20f09fa496000000167a65726f406379626f72672e636f6d6d756e697479000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144499fd1a049d4b87923e75ccccb33e471161db9558583ef4668de361bdf471e674256e8fe0748706": "0x0403000000010010a5d4e80000000000000000000000000000000000000000000000000000000c4f50454e474f5642524f53000000166f70656e676f7662726f7340676d61696c2e636f6d00000d404f70656e476f7642726f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444a4a90b1106c3b5aed98e15e3ed392e38654215c3d1fa8143de53460386b60139fbb45c036c1b43": "0x040000000002000000000000000000000000000000000ff09f90a0207374616b6566697368000013406d34646269373a6d61747269782e6f72670e6869407374616b652e6669736800000b407374616b6566697368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444edfa80574ab9caa493de655d6a57c136e22828f46b8532e2d31cc6f2e7a5c7ba2a20e689f7540c": "0x00000000000000000000000000000000000b547269706c45696768740e44656e697320506973617265761e68747470733a2f2f6769746875622e636f6d2f747269706c65696768741a4064656e69735f703a6d61747269782e7061726974792e696f1864656e69732e70697361726576407061726974792e696f00000b4044656e69735f507374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444f07034c5b0cf0e041e9a27a03cc500b1953d21da30a299cd37b16dff34adc74960e58d747b6524": "0x0000000000000000000000000000000000085369737365726f0e4d696c6f204269636b666f72640000186d696c6f2e6269636b666f726440676d61696c2e636f6d00000a406379626572706171000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471444f53fc133ec6c80a0d32bc7ae5d421990bdb847fc38cade9b388ce8138ab4e4ae957fc7ca59bd2c": "0x0400000000020000000000000000000000000000000006506c7573560000000f706c75737640706c7573762e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144509291906f0088c76fea4c5f219d65cffa5fe38856023a2faca6f77682c6d6787ceeec403e6c461": "0x00000000000000000000000000000000000653746565621d42792e205374657068656e206f662046616d696c792050727963652000000000000d407374657665707279636533000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714450c8a71697e6a933a4100ce6c8cbffb10c34bbc2792d3c4e05e611f907038cb0b29af8a6ae0292c": "0x0000000000000000000000000000000000114b7573616d61487562204d696e74657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714453c05212d64d20f682eeef106c00e84e6c4ae91fbedae25dadb1a9acb8ffed3e0e90494c789d364": "0x00000000000000000000000000000000000e536b79627265616368204f5354001668747470733a2f2f736b796272656163682e617070000000000e40536b796272656163684e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714453efa586e0ab504d20f2ce6c2c876745bbb399c6290cf4e3ee75ce31bbc7ec11342fd5118b98e3c": "0x04000000000200000000000000000000000000000000105374616b65f09fa7b24d61676e6574001c68747470733a2f2f7777772e7374616b656d61676e65742e636f6d18407374616b656d61676e65743a6d61747269782e6f726715696e666f407374616b656d61676e65742e636f6d00000d407374616b656d61676e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714454451249bb2a28c9e7db7bbc0e608c8947bcb697f3a57cfe4586184d757267011ce0ed08fa14976": "0x0000000000000000000000000000000000074e4674657874000000156e66742e6e667465787440676d61696c2e636f6d00000a404e5f465f74657874000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445599a5d9a55b787b6448af583e707f5da901694a4d98471a3be7d6ed6fd76711bd28278987bae25": "0x00000000000000000000000000000000000a426c6f636b20446f6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714457458e4dcb0efd044ecac8b217db711304ba182b23eea8795d7d3163a0d4552bc2c0bd46d38b213": "0x00000000000000000000000000000000000b5374726f7744654154680b5374726f77446541546801010100000d405374726f77446541546831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714458263f3dd29a31aca42f0b5c7957571706f29d2828291b148b4b162100ddcac72c507fd8ab69b2e": "0x04000000000200000000000000000000000000000000084a6f6579e29ca8000000116f647364727140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714458370997cd94a3038eb1437e296afe15e68d2f76e911a3eaee426d061821343101c542b4e375253": "0x00000000000000000000000000000000000e447265616d204e6574776f726b0e44696d69747269204f6c6f636b00001b746865776f6e646572796561727340686f746d61696c2e636f6d00000f4044696d697472695f4f6c6f636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144586d84f22c954a18d34b38fc5c98e7e3ca205b60de22964fb8a6b81f9573ecd9f36fe5d50923927": "0x00000000000000000000000000000000000d504f4c4b414c4942524152590d504f4c4b414c49425241525900001a706f6c6b61646f746c69627261727940676d61696c2e636f6d00000e40706f6c6b614c696272617279000d706f6c6b616c69627261727900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144586d8be9824d3b1ae54b764b5092a89e9a47240f68fc77b20831a47d17cb26216f51b09a6ebf238": "0x000000000000000000000000000000000003425a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714459cc19119e455ad94b3d04ef219a8970ac5f76658fdee1005b4b7ffee3fc02355f60db1a778f826": "0x040000000002000000000000000000000000000000000b46494e5354414b494e4700001a4068616e6e736b6f72686f6e656e3a6d61747269782e6f72671868616e6e736b6f72686f6e656e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445a19fd11dfab9141672dd5646976a1e7970e4294e7c76108ceaecae9d451cd9114aa05e60d7ed15": "0x040000000002000000000000000000000000000000000c6c65736e696b5f75747361000018406c65736e696b5f757473613a6d61747269782e6f7267176c65736e696b3133757473614079616e6465782e727500000e406c65736e696b313375747361000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445ad914bf08ca65600401fa089dca21daddd06b7a240939cab69a9b322b1b5d97106814d915a941a": "0x00000000000000000000000000000000000565746e6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445b717dfcdb4e9d874b415e0035e3edc9f18063fc7e060ed66b35f6fff4b657ed0110fa3c0972b1f": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f340e62696e616e63655f6b736d5f34000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445be453e8a7bff0f1c7376c9f2afef25e542556d2af805dfa691a414efb9e0fc9a8e33f625294f67": "0x040000000002000000000000000000000000000000000a43617270656469656d000012406a6469656d3a6d61747269782e6f7267146a7361766f406d61696c66656e63652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445d43cb8401e3564f40cd7a2181289e32776625b9f3a193f749e33ce1bdeb76cfaabece606c7324c": "0x040000000002000000000000000000000000000000001768656c697873747265657420666f756e646174696f6e00001b4068656c69787374726565742e696f3a6d61747269782e6f726711744068656c69787374726565742e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445d464460dcc7a6cee757e08a886f0c05726f01a5896cca539d55f5f479aefb99065f7fb522f9857": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000014506f6c6b61646f742042656c2033617261627918506f6c6b61646f7420d8a8d8a7d984d8b9d8b1d8a8d98a1d68747470733a2f2f796f7574752e62652f4f7962346e753144324663001c506f6c6b61646f7442656c33617261627940736b6966662e636f6d00000e40446f7442656c336172616279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445d6cf8cdd42d9567e551c089af6a7a53e7644e2e1f0cae900ee599c7b093d8d84e0b260baef1e2f": "0x000000000000000000000000000000000003726f07526f6265727400000f726f40737570657264616f2e636f00000a40726e646d6b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471445ec95bcb8dd897248d5f568124b09fefe504a22bbce2ccee0fcae9262c639b6b2ebaf95b5c8fe77": "0x00000000000000000000000000000000000f5368616e6b617220576172616e6700001a407368616e6b6172776172616e673a6d61747269782e6f72670000000f40576172616e675368616e6b6172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144606c1e64c9b04ef089f89ddbc0f4ed98a10fb57963bbbb03c451dd3aa47ac578a0866ff36400274": "0x00000000000000000000000000000000001c5761674d6564696120426f756e7479203132204d756c7469736967001a687474703a2f2f646973636f72642e67672f595558716a5658001743687261776e6e61436f727040676d61696c2e636f6d00000e40746861744d65646961576167000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714460eeee95ee3957682947d9ddfb4825c6c07ea8c0259249142a42ae15548f32eed2f26dc995f8c44": "0x00000000000000000000000000000000000970696b612e61706501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144631dfe0f44bc9a172d92509f6cf730bcf490da19f09c2271c053d750155b314ec96a7b929ae0c1c": "0x00000000000000000000000000000000000943616c76696e20570000000000000c4043616c57616e675f4359000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446374d36cdcac1f68e28e91f200ae0e50fec4354a429a7e4e00f684f594a33437dff6e8c4ed18053": "0x080100000002040000000100902f50090000000000000000000000000000000000000000000000000000000b63696563686f6d2e6575001368747470733a2f2f63696563686f6d2e6575001c62617274656b2e63696563686f6d736b6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144642619111762c48be1c7627fbc96a38d3a3cf746ae545f60e2510ed80961537d9b4924421fbb562": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144642e4cbf75408a4e0b67671edec61aa1d5fbcf798d4a25beda1a5dd1e3526317509d2c2fd200127": "0x0000000000000000000000000000000000084b55574f524c44000000116b7577726c6440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714465ad8a5d19f9267c884cfb4aaa082d634dd1490b083e2484eb1ae869dc283bdd232e79076050f23": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714466fd64f62aa7900e0c3d50d8748046da1a6d4b266aa6272596357d2fd8505297750874fef54bb62": "0x00000000000000000000000000000000001044656570204d75736963204e465473001b6170702e737562736f6369616c2e6e6574776f726b2f36333332000000000f40646565706d757369634e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714469fd489f05874310eb3bf62c9a8af621503ff143b18cb35afbfdf56b274e6c6de571e7a12732200": "0x00000000000000000000000000000000000b426974537461636b2d30001568747470733a2f2f626974737461636b2e636f6d0010626440626974737461636b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446b931982fa83f40c009ab06d6b49cd62f2801c4b0029a5343c51747f6716c788780bfeb2730af66": "0x040000000002000000000000000000000000000000000e436861696e20736572766963650000000000001140636861696e736572766963656c6c63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446b9cd597eba686fe4a48b16cd6a6c6c44e4c9542e923726dc861077b6a4ff3df1969b13a6868b2f": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000d5061756c6b61646f74746572000013407061756c6b613a6d61747269782e6f7267177061756c6b61646f747465724070726f746f6e2e6d6500000e407061756c6b61646f74746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446c4669abf816fba10d77f8b691c95b2e7307a11e1ef18b68c26e000c3989a780bacc7349437bb50": "0x00000000000000000000000000000000000a616e657474204b534d0f416e65747420526f6c696b6f766100001a616e657474652e726f6c696b6f766140676d61696c2e636f6d00000f40416e657474526f6c696b6f7661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446cfb02d325485373adee633eaf6ebc53ac8f7aec7bef21463801b4034e0e83a49aaa5f143554a1b": "0x00000000000000000000000000000000001054696d4b207c20414a554e412e494f0c54696d204b72616d61727a00000d74696d40616a756e612e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446ed2c28a4803e5468f660000960b688950a3e61f27955ce98545c0039dce11d99e53d03dc4ceb76": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446f06f7d193327806c7bcff1709777857526bb52cb6216759a67ea7e56d1d3571c828902b5bff774": "0x00000000000000000000000000000000000945676f72205368610000000000000d40436f726e666c616b656e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446f13c2d0cde69066a89d6035d62de486ffa7832f579971d6ad69ae8cf9e1e8b284b075c06be7d38": "0x00000000000000000000000000000000000e5572616e7573204f7973746572011f68747470733a2f2f7572616e75736f79737465722e63617272642e636f2f010100000e404f79737465725572616e7573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446fa647d7b60b7824ef63a0f97791221290fd19207cbb23ec5783221b5016afa55161b01dbb0125d": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471446fb667c004eee811ae687e64fca4530b4fd2d2c1f55592a05e4957804177fab940dbeb5cbd00855": "0x0000000000000000000000000000000000094272616e64736f6e0e4272616e64736f6e20556d61720000176272616e64736f6e756d617240676d61696c2e636f6d00000c406272616e646930303230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447108ba2f686e08a84385f4dc4e864120c2648aafc704e395043dc4035e464a9b2a949b4bf0bd51f": "0x00000000000000000000000000000000000b726f6d616e6d65706c730e526f6d616e2042656c696165762068747470733a2f2f6472696262626c652e636f6d2f726f6d616e6d65706c730015726f6d616e6d65706c7340676d61696c2e636f6d00000f40526f6d616e42656c6961657645000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447298269749af4b4ae59eb4208247833e23d7fb08f26370152accd40170824923bcaab638039a104": "0x0400000000020000000000000000000000000000000012474f4245524e414e5a41204b5553414d410000001f676f6265726e616e7a61626c6f636b636861696e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144730d851b833f1c06eaf819ef043560115f737f51d3b07afa79fe8780373bd00070a2eae94015646": "0x0000000000000000000000000000000000046c6b6a0667686a6b6c0000186775616967756169306775616940676d61696c2e636f6d00000840477561693047000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714473db53267f4b4815c4a22915a8bf1866be4812ab49589348457618cebe48440fd7caa86b9b59e2e": "0x000000000000000000000000000000000012566f696365204d7920416d626974696f6e0000000000001140566f6963654d79416d626974696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144746bdebb15ec7155ee8c2936d7a2680fcce49b83f26983593b56a7d7ed33a261bcfdabdda639e2c": "0x00000000000000000000000000000000000e4d617465726961205072696d610e4d617465726961205072696d61187777772e6d6174657269617072696d616e66742e636f6d001c636f6e74616374406d6174657269617072696d616e66742e636f6d000011404d6174657269615072696d614e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447584c2d31e2e9c26ecda2dbfae5750cd7a01702757efade022460d7c30fce208e0e2f850c2aa93f": "0x00000000000000000000000000000000000d43727970746f5f4c6967687400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714475aa077ca585da3a65d8a5050f324ebffc0acbe4405923615e0d76c0c6665050b888337833de927": "0x000000000000000000000000000000000015416b726f6d6d756e6974792054726561737572790000000000000940416b726f5f4456000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714476c17eecfb55ebeba2a4bd4f5273adae499968adab8b397e60270db6dd18a85d69180b385a57a3a": "0x0400000000020000000000000000000000000000000006696c6f6e6100001440696c6f6e6131313a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714476f6754a2671256884bfab0d164daf8d9820db39bb87b170e21e75abadeae41fa148e853254d17b": "0x00000000000000000000000000000000000a4d616e6672656461730000000000000d406d616e6672656461736d69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447785781ee7fbf17b8bfec3d3aba4cacf54940cc35e865b8ab6d8a856894f6401c4a653031a92e42": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33350f62696e616e63655f6b736d5f3335000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144788a63a68d46b3e90eeff9c04b03b3893aa1b545ce5e271bec4de02dee3ac259867733d65e4636e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447a11575d19da5016c32ae0601494f734050511609799c3e1e9c5be224bac231a5e083aefa3a5d61": "0x00000000000000000000000000000000000754495a49524901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447a1a560bf1b7d81546b0e2808b74dd556d18a6438df5b5b3afd038785afb34e8e1457a1dd1e9009": "0x0000000000000000000000000000000000074272616e6368126f6620746865204461726b205369646520000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447a838aa9114c0a2d29656902ad531e8326517cef640e70eb793c712b6329633dee3da0599c88e79": "0x00000000000000000000000000000000001446757475726520566973696f6e204669727374074a6172726f640000127261656a70756b40676d61696c2e636f6d00000f404a6172726f64436172656c7365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447b2d7bf40bf9bbc24beb92b2450897df40f8df93e348c583d972d1b6d4f661a49961acc2b88101c": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31390f42494e414e43455f4b534d5f3139000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447bedb9f0d77b46d6883b9f834076b9c1368e7692ec0a01ae97a52c5cdca957b5d31103423cfbe45": "0x04010000000200000000000000000000000000000000074c55534e45540d4272756e6f206c757373616e1268747470733a2f2f6c75736e65742e696f13406c75736e65743a6d61747269782e6f7267116272756e6f406c757373616e2e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447d0dac62a754c76dc74b64f14d50dfb713f914714ac6adc34d806466858fe9289687aa0decaf762": "0x00000000000000000000000000000000000b4b7573616d614d696b650000000000000c404b7573616d614d696b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471447ea99c6c537b3af1e65015f1fcf3b5f0dad80efb6213321b2fbace6b1662722d574d9641bbfa072": "0x00000000000000000000000000000000000b436174686557616c6c730e4361746865205061726564657300001763617468657061726564657340676d61696c2e636f6d00000c40436174686557616c6c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714481d0bcc9fe1394af6bf18ddf629a634fe0dc352b4f82084c67135cb235f1a7caf05e7b70bd1d128": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714481f4f2839a459d644a41e55054618d207431192696d5a5505935c9a8c7257e1067797c8484fcf47": "0x000000000000000000000000000000000007486f6773737308686f6773696869010117686f67736968694070726f746f6e6d61696c2e636f6d00000c40486f486f486f486f6734000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448240b28222befe0c820f33cbfd5179274cc09289203fd06d9bf02fee2c2ddb01202b6588fde2d23": "0x00000000000000000000000000000000000a42525542414b45525a0000001562727562616b6572697840676d61696c2e636f6d00000c4042525542414b45525a31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448289f8a612ecf7a008963f0b205fdfab299aefe8f86eac63a6c8418b081c3333c2ab9da1767d825": "0x00000000000000000000000000000000000b524d524b2042554c4c530000000000000b40524d524b42756c6c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714484f9e39f4f0e8475cce1eed57740222d643b9c92a594bec58f9b9968bfd4d63d495a7fe5237ab1e": "0x0400000000020000000000000000000000000000000007686972697368000013406869726973683a6d61747269782e6f7267166869726973684070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144851b9f7dac59c8088b775aecc56294102b3c3b55732f7355d69d629b7b3f75415134ae16fed8c49": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144871b57949825f03065cd01d8f8ad376ee4306bc8da85235688b7ef486eaa8efb7ef16228a32c317": "0x00000000000000000000000000000000000b626c75207072696e636501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714489667186afa0e91ca5bc1915da74aba3aadd7ce7b809045d5eb5b73559259755fdcd85a40a5dc6e": "0x00000000000000000000000000000000000f4a414d20e298a0efb88ff09f908d001968747470733a2f2f73686f6b756e696e2e6e6574776f726b00156a616d4073686f6b756e696e2e6e6574776f726b0000114053686f6b756e696e4e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714489b5689523a93fdf4f5911143092b1788c3a91f96d192b35e4fb201f05658f47b677e7dc9a1fd5d": "0x00000000000000000000000000000000001f52686565207c20444f5420456173742041736961204865616420416d622e055248454500001472686565756e696f6e40676d61696c2e636f6d00000c40524845455f554e494f4e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448a5df45177101a6780c9d8ff3121bf764b263a23d7913b4822df102bff190f70ea63effb2672d70": "0x00000000000000000000000000000000000c4b7573616d6163616e676100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448a936aa7fb7ee3630e0edcf2e2340535e12db18dc82636cc2398a3e51bc3c8652f738e3130f6c43": "0x00000000000000000000000000000000000773616e34657305416c657800001766756e70726573656e74373340676d61696c2e636f6d00000a4072796261345f6f6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448b0b934213b6e967cdf18faef23f25dc98b3c1b43e11f334ff5df943dc922e8f24ffdd726bb3733": "0x000000000000000000000000000000000009504f4c4b41444f5400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448b805c30833f34f66f193bc93e18f77ec6e9b26ab283adb6b5e58cc43c6cb81a22264525bfcda57": "0x00000000000000000000000000000000000c4d6f6f6e2d4265617265720000000000000f405468654d6f6f6e426561726572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448c23fd18bd08932827463efe7300e6a0f8839aaae0278895c8bdb087088da4583402898e4174478": "0x00000000000000000000000000000000000f506f6c6b61646f744c752e444f540000000000000c406c7578696e7a68656e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448cdedeb02681e28ac891d5a6e2f56c923dcff8c05d0a535c6695a118bf3de7ed3bab92ff7db641f": "0x0000000000000000000000000000000000144a6f6e617468616e207c2054616c69736d616e000016406a6f6e7064756e6e653a6d61747269782e6f72670000000b404a6f6e5044756e6e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448da0b535190e8951a734819deec3876010a3867c2ac97785e17624a30d8f51d3ab4e93f0d0d9816": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448ec723cf1e5db8eb6886973c891bf20892bfe376d58c89e42f42163a47816c2b064ac7e78528f25": "0x0401000000020000000000000000000000000000000016e29aa1efb88f457665726c69676874e29880efb88f0d736572676579706574726f76000017706574726f7640736f72616d697473752e636f2e6a7000000a405361676553503739000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471448f55d60a49f7e0a2119e372adc7757021cc9e11304519ed6f8f0ef24a3a61dcc5c5e983b2d7171a": "0x040100000002000000000000000000000000000000000d4b4d4c204a616c6162657274084b4d204c6162730013406b656e6f6b6d3a6d61747269782e6f7267166b6d6c6162734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144900c2cf5eb1d4d5dce117ad72d855b586a1c7ab1e2e1400b00418037000a81a26d131eff8486b77": "0x040100000002000000000000000000000000000000001af09f949273746174656c6573735f6d6f6e65792d32f09f9492001d68747470733a2f2f7777772e73746174656c6573732e6d6f6e65792f19406161726f6e7363687761727a3a6d61747269782e6f7267194161726f6e2e416e746f6e6f706f756c6f7340706d2e6d6500000f4042656e57686974654a616d696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714490d06ea3a7f6662a4bfd8243876621936043198841c6226dd58bb5183f2581182ccbbf1f0804607": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714494a0eac89f0ff78c63b6d81d7d307b9f4464304330a840f5159c78a804dd344c5fcbfb3da9aad11": "0x040000000002000000000000000000000000000000000c445241474f4e4c414e43450000154074616e69735f33373a6d61747269782e6f72671b74616e69732e737461636b4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449577d51da67dbbadc86d7e1dba377a90f087a942c0c2777851b447a16af68cfac09c2e58ecf7e1d": "0x040100000002000000000000000000000000000000000b4e6f727468776f6f6473001768747470733a2f2f6e6f727468776f6f64732e636f2f0016737570706f7274406e6f727468776f6f64732e636f00000d404e6f6178656e6565646564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449699ba492f6ca67be2153373520551c1a92b9a2f47ee66c0de25eb1e1c09a4b73af2fdf819c1464": "0x0000000000000000000000000000000000164172636869766572736520466f756e646174696f6e00137777772e617263686976657273652e61727400186172636869766572736538383840676d61696c2e636f6d00000f4061726368697665727365383838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714496fd3c0ebe3acf5b2479a4c5a314be896da932acd7d770361daf76a8c0795afcbb09137ce83d545": "0x0400000000020000000000000000000000000000000012416d697220456b626174616e696661726400001740616d69726b68616e65663a6d61747269782e6f726719616d6972656b626174616e69373540676d61696c2e636f6d0000000005414d495200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714497b07aaeca4b31138f65ffa021ed80b8111b27929180c5ebb79e279810b521adaa2bbc22c343b7a": "0x04000000000200000000000000000000000000000000076b61766b617a000018406d7978616c6574697368653a6d61747269782e6f7267116974656b31393834406d61696c2e727500000d406d7978616c657469736865000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714497f7f7e0d825e942084ed6e5d7bbd49c8bcbf018d5aec40e9e62ef105729b7dcb83007e3ac5c911": "0x00000000000000000000000000000000000a4368616b726172696e0a4368616b726172696e0016406368616b726172696e3a6d61747269782e6f72671a6368616b726172696e2e7361726e7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714498d5c402783eb13d4da6bd9b592cffa69e19e3758d8984704c2335bf4c6474ad93e442f16b71556": "0x00000000000000000000000000000000000b736f6c6f6d6f6e3232360a50657465722053756e1868747470733a2f2f706574657273756e6465762e636f6d001375676c793032323640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144997fd81d8f83eff7294d22dea735215a7ac4a2aee260eb25d1beaad4b02bd8dacf87bd611a96c3f": "0x000000000000000000000000000000000006416c656e610e416c656e61204c656f6e6f766100001b616c656e616c656f6e6f76613139393740676d61696c2e636f6d00001040416c656e614c656f6e6f76613134000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449d8d1014a0c6d168029a7ce3dc02d90888bf05e8fe3ce278e7a8bf499cdb24c432315dace83176e": "0x0000000000000000000000000000000000054b796c650b4b796c652057696c65730000176b796c6577696c657361727440676d61696c2e636f6d000011404b796c6557696c657353747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449e133447b19f12b84d282e5fd1797757dfd0075cdc362493994ae63d980d941081baf72ea395e41": "0x00000000000000000000000000000000000956616c696572616d000000000000104050726564696363696f6e73436174000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449e3956212fb445c6e184bf933cc4cdd61b28f8609c1de672bcd1177bc284c479d184b1e9578d152": "0x00000000000000000000000000000000000c546865204e6f7468696e6700000000000009406865657a697573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449e898b75f9afd0d882faabfb49658b912fa7020be5bc8eaed5fba952a353359447d4406a1a24260": "0x00000000000000000000000000000000000c4e6f626c65204561676c650c4e6f626c65204561676c6500000000000e406e6f626c655f6561676c6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471449f010e5122c00e6fc71e57767a5284519f6f586a093a59bb6148d5b8a62ed7d65ebdd0e56c96a50": "0x00000000000000000000000000000000000d4775797346726f6d4d6172730d4775797346726f6d4d6172730000194775797366726f6d6d617273737340676d61696c2e636f6d000010406775797366726f6d6d6172737373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a0028d535eaa15c36bfed4710cf084c43f5c119f46111b46d7d3c7ad9fc54745e04283a64cef16a": "0x0000000000000000000000000000000000076461696167690f42617275636820466973686d616e00001164616961676940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a0f7a54a1ff58eebceeeed23997617c15d2ccbf5f14196f88c4765152956458ec73b13716ab6b4c": "0x04010000000200000000000000000000000000000000075a6f6f657973001968747470733a2f2f7777772e676d6f726469652e636f6d2f13407a6f6f6579733a6d61747269782e6f726717706978656c747269706e667440676d61696c2e636f6d00000c40706978656c7472697070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a15805a80c56a9eeee55cfb505663c2f6ca145bfd1942cf28f9c416db4d893b787a96feadee1066": "0x0400000000020000000000000000000000000000000011546967657250726f204361706974616c00001540746967657270726f3a6d61747269782e6f72671a746967657270726f6361706974616c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a1cf1abc24f3e10d215f8486a8ae2ec99783c371eb0a270a5e7a4b6e2eabe42270ad46a90d28523": "0x00000000000000000000000000000000000a536269726f76736b690101010100000b40736269726f76736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a2cd9d6d0b8021feaf06fd1666c41a9f0879bbe0928041cc4bc5dfd31f1d36ab4abdb643228584e": "0x040000000002000000000000000000000000000000000c63796265726f6d616e6f760000184063796265726f6d616e6f763a6d61747269782e6f72670000000d4063796265726f6d616e6f76001163796265726f6d616e6f76233739383500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a30177d9940d3d8dec1aa82291268cf854ddc3ed0a0869ed1da026b4e5df758ad4f6a380ecc052b": "0x04000000000200000000000000000000000000000000086753616e373143000000136773616e6a37316340676d61696c2e636f6d000009406753616e373143000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a46ea11348a56200a66532a23c418cca12183fee5f6afece770a0bb8725f459d7d1b1b598f91c49": "0x00000000000000000000000000000000000d44617277696e69612044657600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144a539d4f2d822bce28aff3e47f38d52ef86e186b3d0e5935e813fce1f3ed67c3cd2237171c9f2048": "0x000000000000000000000000000000000009386269746c6966650101011564656461756e756b696e40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ab3116558524fc28ef755e985c62930b3c452073aef9336f78ba7bd0d48b2a19f3aaf430dd2d573": "0x000000000000000000000000000000000005646f2c6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ab82d82d397c8860874d8217aef5c084de244fbc3778345f11abe840071962ae16bc3709def6f57": "0x00000000000000000000000000000000000973616d65206f6c6401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144abab00f092058545487b54dc747fcbe6747dea2ce277caa6f70b21ec7031c20560b693c4b8f9066": "0x000000000000000000000000000000000009506f6c6b614d6178000000196d6178696d652e6d697261746f6e40676d61696c2e636f6d000011405468654672656e63684d6178696d65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ac339d82839fc62b8076afe0f3dd1a5b76b65ed4b34f0fca26a4bcae1e98ff052836ecdad1cd955": "0x000000000000000000000000000000000006596f7563650000000000000a40796f756365617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ad035c90c4d684092084338b54489d20ae38de6e2e3014504d49e8c69da585a7994f5cf1d3a0e06": "0x04010000000200000000000000000000000000000000175375706572636f6d707574696e672053797374656d731a5375706572636f6d707574696e672053797374656d732041471368747470733a2f2f7777772e7363732e6368000c696e666f407363732e6368000008405343535f4147000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144adf867ad6d86f6e22ecf13716f735f9b2fdfc69032bf3fbc35b9b0f11fdb7e1885ba24da2f96c32": "0x0000000000000000000000000000000000074b696d50726f00000000000009404b696d70723030000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ae112a6269c8ee59e10cc56a3e2852932123da5f88edcc0e81fc797ea65ea4225d0720efa7fb764": "0x00000000000000000000000000000000000d506f6c6b6157617272696f720000000000000e40506f6c6b6157617272696f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144afda37d0066d26344a9b7448162343250ddebb4d5eca9cf18c0fd710c01f65c20ef5a7a2b08c160": "0x00000000000000000000000000000000000a4c7567616e6f646573001668747470733a2f2f6c7567616e6f6465732e636f6d0013696e666f406c7567616e6f6465732e636f6d00000b406c7567616e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b11c09379596e080ac8aad77582e035ce510d01d6bdfa7d8eef2445bcb492123120d3ee940aa16e": "0x04010000000500000000000000000000000000000000094b7573616d61203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b290c17b4e25a4a36e132f4b16bd325ddb6a3c63562f23c18dfd20bb2c785d391f625f481097c1f": "0x040000000002000000000000000000000000000000000a6c6574735f6e6f6465000016406c6574735f6e6f64653a6d61747269782e6f72671a7465616d2e6c65747363727970746f40676d61696c2e636f6d00000b404c6574735f6e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b3956c26b2adb6f2c47a26841623e7a55aecd35d0d8972fe0a05b7a9f65ad36e2fe47f465d6ea4e": "0x0000000000000000000000000000000000054b59544500000000000008404b7974655f30000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b3d0a4ac99549aef4e2e84d81b6dc5b195f0e03e36c1810af34eb2c64d2570d0ed343473d846b7a": "0x00000000000000000000000000000000000850616e646173730850616e646173730c70616e646173732e6172740000000010406b7573616d615f70616e64617373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b3db0fa2b7c5e1502a095fe039e07658c9fa559d0919e4f4e288b383882a2262d322a71007f5704": "0x040000000002000000000000000000000000000000000d5669727475616c4261636f6e0000001864656e6e6973407669727475616c6261636f6e2e636f6d00000f407669727475616c6261636f6e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b425fef2474f0f6e08407ceab678c192cb8605649dd4eb488d8f3611ccb496c83ef856b3e1a430c": "0x0000000000000000000000000000000000115468652053696e67756c617220424f54010101010000104054686553696e67756c6172424f54000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b5632672e4e08b2e2fec50feac8a6c83a3e9f869ce04ab800420b2c80c4310f2de2e9f0adfa301d": "0x040400000002000000000000000000000000000000000c50726f666974206c696e6b0000001b67617263696170726f6475636572393140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b5a0926bf96567c4230c50bb60625c3db7e0446f4528301691ccb07fa5572cee0444f86c9d30511": "0x0400000000020000000000000000000000000000000009636c616e67656e6200001240636c616e673a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b610455a917d0af0422941b0c99c8add13283a6b1d5e62e55d9e634ffa427591031f7a4fd8fb16c": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000066b6f6d62690000001463656e776164696b6540676d61696c2e636f6d00000d4069616d5f636f6d62693136000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b7fd70c8f696bc35842bb6c3f854a1bb2243b20069f088f306eb9101ad40f8b120d268578d8f547": "0x00000000000000000000000000000000000944696d73756d31330000000000000b4064696d73756d313331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b9d785f0afee887423e5d0451428d77e1f81f6f20c87427e355468da3ac8eea9eee7f041871a733": "0x040000000002000000000000000000000000000000000c646f746265726b656c65790000000000000d40646f746265726b656c6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144b9d8be32324ecea4466b2edfa709b581c84f0b55deabcb93de767955a37c6513d18dbca4d261069": "0x0000000000000000000000000000000000076d6164346f780a4e757273756c74616e00000000000b406d6164346f78617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bb93cb3dc92785e3e6f301b0a1e1a9c7bf69be3b0bd221a150319c3465bb42e2e7820cc0b1a0e4e": "0x000000000000000000000000000000000009534659204c61627309534659204c6162731e68747470733a2f2f7777772e737469636b79666163746f72792e69742f00167366792e7374617274757040676d61696c2e636f6d00000a405346595f4c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bbbcb9ded8c9980f69287204245020e54f703c5f12edc826ceac6c514a4e947ba402d9c32615e37": "0x00000000000000000000000000000000000e54776974636879547769746368105374657068656e204c696e6473657900001373706f646e65737340676d61696c2e636f6d00000c404875654368726f6e6963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bbd9731b8ad75407894adb5327cf29867bc6eb3d212dc96760f511ee3503d3f3ba1fbccb190434e": "0x040100000002000000000000000000000000000000000e4b7573616d612057616c6c65740d57696c6c69616d2054616d7300001774616e752e63727970746f3340676d61696c2e636f6d00000b4074616e755f74616d73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bbfbd1503dacab9f01c087c4a752cbf56ae4672f910acad4b234a830818356b8378afcd8e042360": "0x08010000000202000000010010a5d4e80000000000000000000000000000000000000000000000000000000a534158454d42455247001768747470733a2f2f736178656d626572672e636f6d2f1840735f736178656d626572673a6d61747269782e6f72671468656c6c6f40736178656d626572672e636f6d00000b40736178656d62657267000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bc05de7e42ebb50ceeccdb6802df2253998f9d4f928b120d51110d1d2afd969b95232bc16768702": "0x04000000000200000000000000000000000000000000096b6f6b656e616b69000015406b6f6b656e616b693a6d61747269782e6f72671c6b6f6b6564616d612e736167616e616b694070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bc1483b442cf7e9662fb31b7c1853748f43f46de1b1d0ef23ea62165357c098e72621ac6b54347f": "0x0000000000000000000000000000000000084a617276696578084a6172766965781a7777772e61727473746174696f6e2e636f6d2f617669726d7a0018696e666f2e6a61727669726d7a40676d61696c2e636f6d00000a406a6172766965785f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bc16c907ee6cbf1eef5d9e432937a9eb75c3ff77eed7fcd5f737899ed8f430fc0cf973ec61bf308": "0x0000000000000000000000000000000000044e494e000000166e696e2e6672656e63687940676d61696c2e636f6d00000d406e696e5f6672656e636879000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bc4e6ae3f5f5afdc470d4501fc73c4bdfb5c4a2faf683657785a8714fd9c4b8ebb6ff3835950f4e": "0x00000000000000000000000000000000000557617361055761736100000000000d4043727970746f5f57617361000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144bc589ab602f6840aaf5b22b19bd3ea8d77cffcd9cf1d1fe284bab4d8af41577edb4d8266c8add58": "0x000000000000000000000000000000000006504f4e494f0000000000000c40506f6e696f6d6f6e696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144be3d4c5b2fe50ebeac4895a2fbabcb267962c7f717455d5c77cd3104c71b943c04ced35a6cdcb0d": "0x000000000000000000000000000000000010204b4f4441444f545f737572766579001468747470733a2f2f6b6f6461646f742e78797a0000000009404b6f6461446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c058945adfbac44402589207ea3e9ba42e801aa4c708c414b804a5309216ccd01b5b6717646301a": "0x0401000000020000000000000000000000000000000013444154414d494e452e4641524d204e4f4445001668747470733a2f2f646174616d696e652e6661726d1940646174616d696e656e6f64653a6d61747269782e6f72671876616c696461746f7240646174616d696e652e6661726d00000b4056446174616d696e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c13d695515297086609300c61120adaba3301fe939f37a0c68915b8e998234283f800e7eb16e224": "0x000000000000000000000000000000000017e1b485ca8020e1b484ca80ca8fe1b498e1b49be1b48f001a6c696e6b74722e65652f63727970746f756e706c7567676564000000000c40447243727970746f3437000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c1956d8be560280b4ec21e13380c9be78fd373b4f73bfd4b21d8ae43274220f1de50c8d8eb9b329": "0x0000000000000000000000000000000000064a67756c68075275736c616e0000144a67756c682e656e6740676d61696c2e636f6d000007404a67756c68000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c28b62f4c20a085a223f906156407224304ef1353300b63d3fb6a4f3cffbb117239149c0884917b": "0x04000000000200000000000000000000000000000000114b5553414d4170706c69636174696f6e0000001e636972696269666572612e70696574726f393940676d61696c2e636f6d0000104050696574726f3337343230333730000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c3a92bfc0327de1b8fdf4d6648e1e72dd1ebd3d2acac4c85e1d6b17b3c657153a94db2e0c2aa356": "0x00000000000000000000000000000000001076696b695f7468655f77697a6172640956696b692056616c1c68747470733a2f2f6769746875622e636f6d2f76696b696976616c000000000a4076696b696976616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c4ff33745201ef57c04de8781bd329a979004519d2e6b02ddc140af6a548b3b59008053d5459537": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c530bbe085c5f6b608bbdc4a6f918146da541013750078357a37afc7c397d7a0fd3c4c7e528b23a": "0x0000000000000000000000000000000000125241482d44455349474e2d4e4c204e465408526963686172640000000000104052414844455349474e4e4c4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c5546659ce31189d0075cd9bb3988e0b5e05b124b20127e93531bc80c40ac0e4a1f22006815285d": "0x0000000000000000000000000000000000065375736861011f687474703a2f2f7777772e73757368617368656c656e612e636f2e756b2f010100000b4073757368615f736865000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c6fb887a199d035466f0fac5092dbe66d2402fde1bd7255483f087deabeddbaab26142d5a3db71a": "0x00000000000000000000000000000000001754686520436c616e61727920436f6c6c656374696f6e00000015746865636c616e61727940676d61696c2e636f6d00000c40546865436c616e617279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c89c93c5a9d60f348cb77bc66938feb608aaf2ddc62faa8cfa2b9c7c9576fb5f69ca8913b41f713": "0x040100000002000000000000000000000000000000000641726a616e1141726a616e205a696a64657276656c641a68747470733a2f2f6769746875622e636f6d2f61726a616e7a134061726a616e7a3a6d61747269782e6f72672161726a616e7a696a64657276656c642b6b7573616d6140676d61696c2e636f6d0000114061726a616e7a696a64657276656c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c8f1e30e595b6bb7c4039fa473c4bbdfb7d175ddbef8407fda3e32ea0df0536c806bd4a64c6f35a": "0x000000000000000000000000000000000006666f6f677900000000000008406d667567616a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144c9165b3ec94f3b1c602f98da395c5bf3804e86851c5bf2a30db39848d62f6c14fea1a300946ca00": "0x0000000000000000000000000000000000096b736d726f636b73010d6b736d726f636b732e636f6d010100000d406b736d726f636b736f6663000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ca13e1b44c9d065a63e6b2499f54c2be949deb97b030010274cef1d88c2af220b1c6013096e4e44": "0x0000000000000000000000000000000000056675636b0000001365706f6361383440686f746d61696c2e6974000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ca2592175bb1cc4a09af83b3d2e115f1aca50377618b28b8891101b1f9d06a36889499676427b27": "0x0000000000000000000000000000000000086b616b61726f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ca775588b3d2ef060b8d7880b3110a1609b771f10f2ecff15a345059368867bdae4c6884c888210": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30310e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ca8b26602d73427e46675e622c45de390f070b175f99ea56d47537b076a3fc9ac0bc07c38e01005": "0x000000000000000000000000000000000006464f58585800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144cce5213f083cefe724cf673d804e34e23743be0969e9606c64b7ccf64a82b498c77a3195ad6214c": "0x000000000000000000000000000000000011416e61656c6c65207c2050617269747900001340616e61656c6c653a7061726974792e696f00000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144cd9322609738faf34a6cda09ad0388dd406269c050889d0fe64d996c3ff3571e26802ecdefedc51": "0x000000000000000000000000000000000006546961676f00000018636f6e7461746f646c746e657440676d61696c2e636f6d00000c40646c7461636164656d79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d0e40b01504aed30c0a7bb6b17a969c1c076cb422eb08c0185f932f494086f4d37abedd18af487e": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32360f42696e616e63655f6b736d5f3236000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d1691d80588b205382d4a2c2b6eee702dc19705f86d9113e79b860306c1b672db9adb4da9d5631a": "0x000000000000000000000000000000000017524d524b20527074696c69616e732043726561746f7217524d524b20527074696c69616e732043726561746f7200001d74686572657074696c69616e732e726d726b40676d61696c2e636f6d00001040524d524b72657074696c69616e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d35c327c115f99b08745476e8a2fb16504c77a75b2dd20b6f56cfb71c87125f1707a702753af24e": "0x00000000000000000000000000000000000642726561640e4272657474204b6f6c6f646e792168747470733a2f2f6769746875622e636f6d2f62726574746b6f6c6f646e792f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d3e0d4f24d59fa98ce6c79ffe1d5f06f89eb2ec7653c8c9c33cc32506aaa8ba0d4e0b63b43a5d67": "0x00000000000000000000000000000000000c6261696c65796e6f6c6665124a6f686e204261696c6579204e6f6c66650f6e6f6c66656d656469612e636f6d0101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d4b24b1bbf7bc3bd0b1cf79e7be19b7cf96bd4e625f4d5002278802fc0542a42535770798869b2f": "0x0400000000020000000000000000000000000000000014506f2d4b752050656f706c6520e29da4efb88f00001640706f6b755f6e6f64653a6d61747269782e6f72670000000c40506f4b7550656f706c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d585451a689512eae088990b08a6e0e8c06a9234cc06125677742fb1307bf70a2775ed19427dc09": "0x00000000000000000000000000000000000c65746e612d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d6200fed0714c63987ebea45bea8a2676cd896c6e01460290bdd56a6dcb27e9648fb33ac2b7fe66": "0x0000000000000000000000000000000000084e65656b43757801010101000009404375784e65656b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d699313bc760a036a81f13352076dce1dfe8f357fd805bbece6ec16efabad52a2c24e6824e16315": "0x0400000000020000000000000000000000000000000008494e4748415a4900001440696e6768617a693a6d61747269782e6f7267147374616b696e6740696e6768617a692e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d9a1147d1ed82c8b00eba4acb0f53ac420d73857bfba1ac2df6e3a4fd8001fd4bc1691e9a8da44e": "0x0000000000000000000000000000000000076e667465657a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d9dcf234fbee40ff6f2366ea3f3a900ae6b42a85e4860ca95bd5f42ae8e42b9ca30bfd975f7006d": "0x0000000000000000000000000000000000064d617474610f4365736172204d617274696e657a00000000000e4043657361724d747a4d617461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144d9e54521ff7e843ce3f66e4350864006ec5174657fea7729c83aa847e1949ca8256686e07c98123": "0x00000000000000000000000000000000000d4961726f7661796120415254094b61746572696e61207777772e696e7374616772616d2e636f6d2f6961726f766179615f6b617465001963727970746f6b6174653139383840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144da1eb2472c6e636a0802cb1cc2721239d717a1b2aaf59febe8995bb5c374272b7f7d346e8b7b923": "0x040000000002000000000000000000000000000000000e4c61626164616261646170746100001b406c6162615f6461626164617074613a6d61747269782e6f7267186c61626164616261646170746140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144db2a789d942dda53e3c2bc736c233d8d77544e74987ceb03bcac1ba7904b1a98f377883d4b1733f": "0x00000000000000000000000000000000000e4d616e7461204e6574776f726b0e4d616e7461204e6574776f726b127777772e6d616e74612e6e6574776f726b010100000e406d616e74616e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144db321631814cd32ace82546c558ba2ec9e42f805a65c2f16f011216b01b0bbcb32d6b68ffdf8c6b": "0x0000000000000000000000000000000000065269676f300101010100000c40416c65785269676f3930000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144db4fe1336b5ba5a06dc4e63396771cc7d4e36c3fc749db4b0f367c9c9edfd37badf8aa31efea960": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31300f42494e414e43455f4b534d5f3130000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144db8c074b305156e12fbc6f6f8379674458d237fa3a42ad300923a6721841c373dc2a168c83e0479": "0x00000000000000000000000000000000001bf09faaac2054616c69736d616e20476f762044656c6567617465001568747470733a2f2f74616c69736d616e2e78797a000000000f40776561726574616c69736d616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144dc9b342edef30bb0404127e6dee3322530e94ae97f3c9d21f0549b5140d9d004cadf94a66a2b730": "0x00000000000000000000000000000000000d524d524b53746f69634465760753746576656e1b68747470733a2f2f736e616b65736f6c64696572732e636f6d2f000000000b4073746f696364657630000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144dcd3691e5f659d55e0e72cb881993bf61241e60224f1e6bf2b9acf201c84cc5c6cd05fa6e0c591a": "0x000000000000000000000000000000000009616264756c6c616800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144de1efce0c5d7d9ff807dd354eec53082fa68580d6240ca57bb0f02afd6697c6f35b3fc11f0da402": "0x00000000000000000000000000000000000e50756e6b205661756c7420233700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144e066e19d4ddf8f19eba94f67453eeded0e6c8ce2932269f57b7227f6873b782a3a0aa0cad95b40f": "0x040000000002000000000000000000000000000000000e4e65756b696e6420546f6b796f0000001168656c6c6f406e65756b696e642e6a7000000c406e65756b696e64696e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144e0979985c355367e080d3f0de7be8f9edc6d90d8bc337aac66844025f3e9da7129356eda0f04256": "0x0000000000000000000000000000000000114e6163696f6e43727970746f2045787407416c657820470000174e6163696f6e63727970746f40676d61696c2e636f6d00000f406e6163696f6e5f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144e0e08d8f728b4dd32068fb3b800c5df40df16619761b3418e40d9455784b6a293d2425e35ef2c27": "0x04000000000200000000000000000000000000000000054c554341000000176d6172726f6c754070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144e3ffaf4570f18710a3289a760e8155e8894b96d8a319d43588281ef4f69c1bd0a0daaeb845d980c": "0x0000000000000000000000000000000000027600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144e6523a4af508944f2311ebbe228b955638ea3a3d58a8c73ffe0b98b2ea8214617c397bc98f3dd37": "0x00000000000000000000000000000000000753656557687900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ea5d0f641dc611c309d30ed1f41373d0abb1b8dfec4055e93312d73e9e7279f776e662fe306a00c": "0x000000000000000000000000000000000010546f6d61737a205761737a637a796b10546f6d61737a205761737a637a796b1568747470733a2f2f7761737a637a796b2e636f6d1b40746f6d61737a7761737a637a796b3a6d61747269782e6f726714746f6d61737a407761737a637a796b2e636f6d00001040746f6d61737a7761737a637a796b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ea6923b31b03243e0b9bdcc45111c7c23b354318607f4cbda8e7f017d500aa15402b1a16a36497a": "0x00000000000000000000000000000000000e524d524b206f6666696369616c0009726d726b2e6170700011636f6e7461637440726d726b2e61707000000940526d726b417070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144eb1abadf357251052c4cde966f7c4088d60cbf459a665660d36ae1f664cf65a86ced132b645c833": "0x00000000000000000000000000000000001353697874792d466f75722053717561726564001e68747470733a2f2f6d656469756d2e636f6d2f403634737175617265640015737175617265646e667440676d61696c2e636f6d00000c4036345f53717561726564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ebc48c63a5dc09fa4ac69b3ea42acebe4f70767ee894eeef5eef1f011f0dca45097a2e6c40c5366": "0x04000000000200000000000000000000000000000000036635000017406b7573616d61323233333a6d61747269782e6f72671e6b7573616d616b6f736d6f73696c613232333340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ec6dcb09516ac9cae463a6613cae63a77d1c391bb1e00a974ccd178ebd91e00268608f3a570f84f": "0x040100000002000000000000000000000000000000000d5061736861426f7563686572000000177061736861626f756368657240676d61696c2e636f6d00000e405061736861426f7563686572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ed0bc7ef1112e6f2ee6766c1a3679e5638966ec23c25dc094b99c082151f913704f439cb1e07636": "0x0000000000000000000000000000000000084b7573616d616e0442656e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ed12f7f95496d053674aa73951219dbd27b3e3fc5847b806c68c1de38fd4f22f9493a461c80e903": "0x040000000002000000000000000000000000000000000b472d646f742e74656368001368747470733a2f2f672d646f742e746563681740672d646f742e746563683a6d61747269782e6f72671467646f742d746563684070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ef34c27d4dfe709f615fbe2b5b19fd70abc2d71709e5a8efda335fc4ec06d25ac1105d7eaa92663": "0x00000000000000000000000000000000000b466f726572756e6e657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144ef6058a4c93b2fc18e2ab095c1838261df21f7474602c520288bbb6b328728417d5b6189591a054": "0x0000000000000000000000000000000000094a6f686e566173650d4a6f686e6e7920566173656c0015406a6f686e766173653a6d61747269782e6f726716656e61656e6169736f6e3240676d61696c2e636f6d00000b406a6f686e5f76617365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f0201a59b9849e4541e0539e47fdc4222ab09d8b19ae6ae612de8088ce5e73afd2e1b926ada255b": "0x00000000000000000000000000000000000b446f7473616d616b696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f08661e9ff1a0dca2faef0d22feb488024378daeefdc612f34713c17425c5fb5c1ee5ecca7f3908": "0x0401000000020000000000000000000000000000000009417272697665657200000013617269657665657240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f0effdbba5ecc713aecc4a1d9f8b782b08d7468da4753da690d55c26f9bd1fd1ca09dbc60bd4a1e": "0x00000000000000000000000000000000000b54686555464f437265770953414e544941474f00001654686555464f437265773140676d61696c2e636f6d00000c4054686555464f43726577000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f105dc4d6865f85da54f55778dd9d3ccc434d0000bc254788d7e0a9c766b8f6dde51e335a28305c": "0x0000000000000000000000000000000000084d69726167657a114a616b726170616e204d6565636861690000124a616b6170616e40676d61696c2e636f6d00000a406a616b726170616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f133aa79b057d66fef5977196fe3fe5c456a767e6b06013ca62762b282de97040add4ad2c53db61": "0x040000000002000000000000000000000000000000001350726f5374616b6572732e636f6df09f928e001768747470733a2f2f70726f7374616b6572732e636f6d1b4070726f7374616b6572732e636f6d3a6d61747269782e6f726718706f6c6b61646f744070726f7374616b6572732e636f6d00000f4050726f5374616b657273436f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f1e36622dd2acb4fcc2b373ac96c11d293ab0565d243750874cd8d060b66d1d908761ac1d616d79": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f2ae4ec939743a590bdd91c993e87db3f250c0d9276d9b122e8cd571cfc0d5d6c54066f2a225a32": "0x000000000000000000000000000000000008427269636b737a00001440627269636b737a3a6d61747269782e6f7267176461627269636b737a37303040676d61696c2e636f6d00000b406461627269636b737a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f2c0ec81395af615055fbad57aeb372174b99b9dc3723e1bd0f28febc74008251d7102e5ba631eb": "0x00000000000000000000000000000000000a4d6f6f6e7374616b6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f3ddf57e13a6e9f5cd992745ac97a51f7535709b288163895baa3b70f2620c3141f9a16b8ec8714": "0x0000000000000000000000000000000000134c69666542616e206f6e20547769747465720d426f6220446f62616c696e6101011c43727970746f57616c6c65744e616d657340676d61696c2e636f6d00000e4062756b7368756b616c616b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f3e6ee6ff9d1b948244b130639897c7f76d7838eb1c530786b0c1e15e65f0c09c0a6a3ec35f9d68": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a79656c6c6f776265650000194079656c6c6f776265653236373a6d61747269782e6f72671779656c6c6f7762656532363740676d61696c2e636f6d000010407962656539313238303835353036000f79656c6c6f77626565233733303700", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f487a423739a66d8e27005a0b559b40d16613abc2804aef92cd137692b2eb228820e20aabdda27d": "0x000000000000000000000000000000000007704d725f4e4c0000000000000840704d725f4e4c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f4f5169450cef7530b0e3fc5407fa802e7988b2d86f8eb9d13784e230668e74cd90eab4d48d145b": "0x00000000000000000000000000000000000f4275726e6572204163636f756e7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f5fac645183a09c2ab937c4061cfa1059fbab2252518119f1f4f18a1f0155ee42732ae263c4510a": "0x0401000000020000000000000000000000000000000012454c454d454e54204352454154555245531042656e6a616d696e204e6971756574000021456c656d656e745f4372656174757265734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f96a77cdf9bb4b12ee187e3230395e417650558d1362b6dc594a481134ff29b3d63db53b8597d09": "0x00000000000000000000000000000000000b414c4c434841494e4d4a154d61726369616c2053204465204c656f6e204a7200001a6d61726369616c64656c656f6e333040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f99ab6629a5af0254007a3d6d00fa2d2c2e8f8b24c88def5120d3b168e003b7d15a405a5c105d67": "0x040100000002000000000000000000000000000000000c4d696368616c4a657373650d4d696368616c2056616c636f0000176d696368616c2e76616c636f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144f9f5cdc4b4279e04ad1d3ce2898b3b78ac9df34af660eefd167222e9efdb07467a0c82160903f7a": "0x000000000000000000000000000000000009526f6d616c6f727414526f6d616e204c6f72746b6970616e69647a65000017726f6d676c6164696f6c797340676d61696c2e636f6d00000a40726f6d616c6f7274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144fb1c11ebf76bf856c70f422fbca28c1e03e79bc42594c5bd8588a7c23454842f169b1b8c57db47e": "0x0000000000000000000000000000000000096f6e616e61736f7500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144fbb681dafad845da0f491d92cddc77c2487a3fba73ac3008e418a146631a742407b1af5e107c568": "0x00000000000000000000000000000000000b4d616e7361204d7573610000000000000c4069736861726c65653932000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144fc324df3bb6d99258bb56063a47ee6e4a4d0bfe444682394a1e4657fa39f4622f2a0285689c1b3c": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144fd5ef0c5bb8d4b6aef764dd5f7e23556b143bc80e0ae0b4835b469dbad3b0dbea4b8275e91e5256": "0x000000000000000000000000000000000006566172757301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047144fd7f55b4df090d0ca1b43ab297c7745ad2f6b3b5b201df66cf98723c3029230ffe61057084a8425": "0x0000000000000000000000000000000000094b6f6d61696e7558000000166b6f6d61696e75786e667440676d61696c2e636f6d00000b40785f6b6f6d61696e75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450004b04910a1297929aa2bfe7b52500b288c943b7c24a90928cd8a6f7ec8eec44763d9f74198401": "0x040000000002000000000000000000000000000000000f43727970746f2d6275696c64657200001b40616e746f6e696f2e63727970746f3a6d61747269782e6f72671b616e746f6e696f6b61726170757a7a6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450045aaecb66d5cace6fb186ae3769b7bbee62c3ea178cf730754413b26bfe540eda5ccce590d444": "0x0000000000000000000000000000000000096b75727572614c5000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450079469344a3846844f55022b2b8667129c167068a9c2a6bc292f2d312336bd98339d686b575a1b": "0x040000000002000000000000000000000000000000000b416c6c34486f646c657200001740616c6c34686f646c65723a6d61747269782e6f726717636f6e7461637440616c6c34686f646c65722e636f6d00001040616c6c34686f646c65725f636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714501e18a682931984145bf48774f53c991d99038301e44c30a2de38d805016bc6ea1a95d74b2a7f4e": "0x00000000000000000000000000000000000d73696c6c79736865726d616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714501f97beba27688eba2c0d2631820207e6461b85177854a6cb019fd8b7f689c9a255457b346ead78": "0x000000000000000000000000000000000006437261696700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450233fe85fbce46c6ee137ac7e0f2103c00e787b5ba39ea7ce81c245e4ac64718041272d8218c748": "0x000000000000000000000000000000000009437269737469616e17437269737469616e2d417572656c2047616e657363750c69616e637532312e636f6d01196372697374692e67616e6573637540676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450417bc6d24f055d92200a0fa4244b13cf0277ce222a51979033d35e0cef4c692b27b4871d748b06": "0x0000000000000000000000000000000000114a6f686e314d6163206f66506865656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145045ef62591a03255a26d9a7c3642c9bac25a08bf77ddf394916fa48fd714e61e8b5088fe8f58872": "0x0000000000000000000000000000000000074b3273616d61084b3273616d616e0000146b3273616d616e696140676d61696c2e636f6d000009404b3273616d616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450494b773f99187c086b3cff28537011ee3cdb33556a85d93cb1d836c7bb2c8e9a000a339d887136": "0x0000000000000000000000000000000000154d722e20426c61636b2057686974652047726579064d72425747000016726176656e32303139303940676d61696c2e636f6d00000d40726176656e323031393039000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450541acb5b3adfcb783677be3528d7c562df11a31317f6138279cd39ef96abba3dd1f38e9896a37f": "0x0000000000000000000000000000000000127733662d7374616b696e672d6d696e657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714505689aea117f4b4d03671180d2ac566d1ed507709b08be083bdb86d29d36a654f899c8c9e624874": "0x0000000000000000000000000000000000044f746407416e647265791a7777772e696e7374616772616d2e636f6d2f6f74642e696c6c00126f74646e6e6f7640676d61696c2e636f6d000008404f7464496c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714505fb34a37127f8a58e8959d0add94c9171e095082f1a476fe16fff8fd01a0e51401135f4801d844": "0x0000000000000000000000000000000000046d726200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714505ff16b5338dbbc26b65a62591e46572822dd9b2e5866b150fc2a10196ccc8ff71303d3e2713e69": "0x00000000000000000000000000000000000a4d61726b20524d524b00000000000011406d61726b5f656d6265725f7279616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145082507ad8dcff7f3cfd8876d11ad724df41e20f43f3bdedabc6d83620a029b9d7c28f54ebc47501": "0x00000000000000000000000000000000000358430f5869756361695f66696e616e63650000127975727569717540676d61696c2e636f6d00000d407368756169676579757973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450841acc86ed6f0be071272e72b49c948d9b4013d7563b649cb1730b0a52de303155dcb44c9e497d": "0x00000000000000000000000000000000000a4d6f6f6e62756d3364024a00000000000b404d6f6f6e62756d3364000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714508509c16c555d079458bb073e69511e772b1608cff07add7f5240cb1c89cabde012d5b29504e72b": "0x00000000000000000000000000000000000a7874755f63757272790c43727970746f52616269741568747470733a2f2f383735372e6574682e78797a001a636f6e666964656e63652e6d6f766540676d61696c2e636f6d00000b406a6961736875323131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450c343c18df87d20fe565d8fcf8fdb44c9a61cc16a70649519a2acda598ee64d5b664e09a76d1c1d": "0x00000000000000000000000000000000000a646f6f6d73617965720000000000000d40646f6f6d73617965725f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450c3b90207ca02d3d2dc9a9f85e3c523f1da8ee7e3e116f520ed49a53a48aea229147880736b906f": "0x0000000000000000000000000000000000000000000000000e4063727970745f6d6164646f67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450e0223a7f06f4edee2804a63951212e1342a2c01ea12f20153f27b6a5a649ef2e6c7b20d7859f68": "0x00000000000000000000000000000000000a696b68616c656432380000000000000b40696b68616c65643238000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471450fc5019aa653ecf50c91b0b82bff9b1b93145633214a08d5fd25d12e6c78a3b369cd7e539b92e26": "0x040000000002000000000000000000000000000000000853616368696b6f0000144073616368696b303a6d61747269782e6f72671c73616368696b6f2e76616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714510331c48413f98ff85f04ed2bce67d0b51550754bdd4da9f8800f83ad39390c5925429f3cc47d47": "0x00000000000000000000000000000000000a5472756f6e674b6169064865726f330101010000114050686d566e54723038323236353134000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714511c6af03bd0bb3e6abb62dcdf9839bcee6a1686d8bba50e66959c2b5f23bcbb353eaa2522e62520": "0x000000000000000000000000000000000016496e697469616c576f726c6443726561746f72303116496e697469616c576f726c6443726561746f723031000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145126d11d32941450dc41188d0dcd6722402508e1eb7601ac5d225c923114ff63aa085f20756fc371": "0x0800000000020100000002000000000000000000000000000000000f564c41445950524f4d4f5445414d00001740766c6164796c696d65733a6d61747269782e6f726715766c6164796c696d657340676d61696c2e636f6d00000c40766c6164796c696d6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714514824a3c36d4d80d22cf3de263e508136506b6e9b7b06bb8c7abb53a5a55f7772229273fe43a41f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145151486ca217f604d23f678af47c89d76031edc91e43784bcf9991b131f957d312fced2c5187fb47": "0x0800000000020100000002000000000000000000000000000000000b5354414b4543524146540b5354414b4543524146541768747470733a2f2f7374616b6563726166742e636f6d15406e3174726f67336e3a6d61747269782e6f726717737570706f7274407374616b6563726166742e636f6d00000c407374616b656372616674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714515c9ae1e485544e02b666dc3f8a627302f02c719cd1179cf2b762bfd23d97c79fcfa515283bc23e": "0x00000000000000000000000000000000000844205765657a7906446572656b000018646572656b6e65616c7765737440676d61696c2e636f6d00000a40645f7765657a7935000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714519b117a3f97578bf416788bc4684010deb2f452fad6136990e23fab94d7a6ea03a212d22dad1461": "0x00000000000000000000000000000000000e444f5453414d4120444547454e0253000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451af1b7470f237d6dcb36abb644c739ee8ccf5b2ed810bf1bdc860a8082b43885c3c04db9befc011": "0x000000000000000000000000000000000010416e656b646f74652053747564696f00167777772e616e656b646f746573747564696f2e646b001a6e69636f6c616940616e656b646f746573747564696f2e646b00001040616e656b646f746573747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451affb7adda940b6380329063444b0d709fe60a6bd0ee966c85ee1da8d62faf0bf33c58d8a15f93a": "0x000000000000000000000000000000000005546f6e690000001d746f6e692e696e66616e746563617361646f40676d61696c2e636f6d00000e40546f6e695f426974636f696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451b32c5fc205cb3dc8d71df73e465b4a8872ab23bd7a7a6556ac05f3146f5b08f77e0b6ea437d051": "0x00000000000000000000000000000000000962656e6a617348750101010100000a4062656e6a61734875000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451bca9b0989e2a50c096244f429cc3c9a56de9dfd07cb0dca6c15a42e701acac26d1ea108d8cb91e": "0x000000000000000000000000000000000009737578696e78697500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451c349b821056bc4dcf8dc909c5afd9755dd3c322b6f06b32dcfcc36755bb73e7ee5ae0722f4477e": "0x00000000000000000000000000000000001c54686520706c6179206f66206c6967687420616e6420636f6c6f721c54686520706c6179206f66206c6967687420616e6420636f6c6f7200000000000e403139353931566974616c6969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451db8a617be61c665e0a4ca74bbb4da39c79954e7875519fa67049795c02a360412f3ee41a020506": "0x0400000000020000000000000000000000000000000006416c6e74630000001d63687269737469616e6f7272656c6c38373840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451eafd8385d1936b5812d714528fe379fe7ddc1381d3608149064486d4b95266072df8dba9539a22": "0x00000000000000000000000000000000001073735f70726f64756363696f6e657300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451ed17e92838fdaefe73b0dae6be10617b258eb5f9a3a6a8eb62ac48d8815c159149a267d616cf27": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471451fe2259dc584cad041148d9102c91506d9e3e75297536084c9e3c3259ff78e4651ef4c464a04377": "0x04000000000200000000000000000000000000000000064e6f646c650000000000000e404e6f646c654e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452003ea86a3405e150a9915a75f39429595debcf987a1ce8aa34937de24d2356f31fab6192acd032": "0x0000000000000000000000000000000000053147616200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714520f291562f43512506732d16ab06c1d33cae04a14f0aa43c2de8a3971d419c6db3fa03a6a047131": "0x00000000000000000000000000000000000962616c73616d69630000000000000c40307842616c73616d6963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452212743bf9486034a6b7fe6b1506b1a58b5e6e4b5635fdb17797ce19fc34786e3c1520c21bc024e": "0x040000000002000000000000000000000000000000000e446f6e6174656c6c6f204b534d00000017646f6e6174656c6c6f6c707a40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714524d4c9a4edf7068ae7469e454ccb99c9086f96135f5aa2b32b44652c9d739a2e4f80aadef463600": "0x00000000000000000000000000000000000b487970657263756265200dc3967a676520546f70c3a775177777772e68797065726375626573706163652e6f7267002068797065726375626570726f6a656374737061636540676d61696c2e636f6d00000d407a67653432323232393433000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714526acd0240c524a4b01af838437b50496eed9bc64de023cfbb1afdd633b0999537bdf0e5030f6e6c": "0x00000000000000000000000000000000000f504f432044454c45474154494f4e001e68747470733a2f2f7777772e70726f6f666f666368616f732e6170702f0021676f7665726e616e6365696e63656e746976697a657240676d61696c2e636f6d00000f40476f76506172745265774b534d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714527b633bf5bcbf6fc8d5ea648c1881e3cc19179ce0aca0b0b13f9f8bbda137472a91864b93514667": "0x00000000000000000000000000000000000f4d757368726f6f6d20546f706961001a747769747465722e636f6d2f6d757368726f6f6d746f706961000000000f406d757368726f6f6d746f706961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452864ab8b7555a13f24cb6d3f22ce3f4f7a7d553f2d53defdc6cfb346115bc7c81fb34b2579a0c58": "0x000000000000000000000000000000000005686b6465000000136b756e693633323240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145296f5f3e605a0e3e8b2603f6baee5bc32a9b9e4eee9168499fa553d35edb56aef0035ff7e1f165e": "0x040000000003000000000000000000000000000000000850617261646f78001568747470733a2f2f506172614e6f6465732e696f164070617261646f7878783a6d61747269782e6f72671470617261646f78787840676d61696c2e636f6d00000b40506172614e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714529f9f0efcc4d1fef4a187600e4026679cd65074ea9a9bdf2e807d7df8160b1ffbbc8032c97b1c03": "0x040100000002000000000000000000000000000000000970756e6b726f636b0018687474703a2f2f696e666f2e70756e6b726f636b2e6d65154070756e6b726f636b3a6d61747269782e6f726715706f6c6b61646f744070756e6b726f636b2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452a0abbda8b43f37b8e21e9844672e363cb73cb15c0b5e8bab835962d2f60baeaa6035ed31245f48": "0x0000000000000000000000000000000000144b534d204d41494e20434f4e54524f4c4c455200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452ac2d872feb1e6aae19bf487c9effca2fe23d3601d330da0a0b82462f340b84ef49676810e58c44": "0x00000000000000000000000000000000001256616c656e74696e73204976616e6f767300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452c8ca65b329df6b02f87ce6d066323c92f56d284faaa856ce083f9ba81635464f04fabec453c822": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000001fe298af4368616f7344414fe298af204e6f6d696e6174696f6e20506f6f6c094368616f7344414f00000000000a404368616f7344414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452ef0ce1f0943599a092ee7d51b6ba1268db2c00f3037cd198fd31f14343bcdc966cb23d7ad90816": "0x040100000002000000000000000000000000000000000c3238446179734f66446f74001c68747470733a2f2f7777772e3238646179736f66646f742e636f6d001a6368616c6c656e6765403238646179736f66646f742e636f6d00000d403238646179736f66646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452f06c1cd27b99a6fe276fe53bf4d1a7589d977a91c8cc990d58ec79654f9560bdcf4e06ea7c2b39": "0x000000000000000000000000000000000006642e67656e0c64617665646f7473616d6100144064676e726174643a6d61747269782e6f7267000000094064676e72617464000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471452f7789aca5beb4f4eaba2222455fc5cddf28b131f3f6317f2c22de7976eecf12ad8d3865d453418": "0x04000000000200000000000000000000000000000000074e585858494f00000000000008404e585858494f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145311d7c5ed4d76a10e82ed0d7d2e0f86a12c9f4276c1da60ac75cbba94789514736664d15514fd5b": "0x00000000000000000000000000000000000f42616462756e6e696573204e4654000000186e667462616462756e6e69657340676d61696c2e636f6d00000a404169746f725f6c7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145322d4c9d96b74a14a07b12f3c8a1cbf139a46d05f52acae666ffe15f97e2e19d6def5831d101166": "0x0000000000000000000000000000000000093342616b5f6172740e4572696320547265736261636b1a7777772e6c796e6b666972652e636f6d2f3362616b5f61727400133362616b2e61727440676d61696c2e636f6d00000a403362616b5f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145326dd1bd53284ff3c2dd5a18ca096521bdf0adfd35e358ba6b89ce8931c87144f80998c5f6a0a48": "0x040000000002000000000000000000000000000000000a43414e445953484f5000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453274014bd0b9f664274f5c7b6be61ea3dcce96b80af40f4ff7b53e46c598986411fdfae942a7955": "0x00000000000000000000000000000000000d4372656174697665204c616208526f626572742000000000000e40437265617469763936393634000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714533d19de9dfcc61206d1b911e582c3c8c372135076ef9570fa2a48ef4ce5a71d53d9e1dbc9e70e2d": "0x000000000000000000000000000000000009736d6f6c6265616e000d6d6f6f6e6265616e732e696f0013736d6f6c73406d6f6f6e6265616e732e696f00000c40736d6f6d656c65747465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714533d284f329fd8fc9e13e5a0517ed028b4f44c593efb7caa0f82ddb90e95b8cc1c68122d0b03c319": "0x00000000000000000000000000000000000a417274206f6620424d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714535df4fc4871fff79c0495d70ded39e5fe05f1d41b05db162a52cbfd4441ebf81a50132070ad1d09": "0x000000000000000000000000000000000000002168747470733a2f2f706f6c6b6176657273652e636f6d2f6163636f756e74732f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145361b1ae059eb11e0650a2e41ea97b60bbd3f87aa30d605562069075deaaf79559959230928a2487": "0x04000000000200000000000000000000000000000000124d722048617276657920537461636b657200001a40686172766579737461636b65723a6d61747269782e6f726718737461636b657268617276657940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453798c7023fb40ea3629a3ff4589c42f2239861dc182184b176845a6bc350b9d72aa592a8d113e25": "0x00000000000000000000000000000000000b524d524b2050756e6b73001768747470733a2f2f63616e6172796e6573742e696f2f001652656d61726b50756e6b7340676d61696c2e636f6d00000d4052656d61726b50756e6b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453860ac0c7c038f0f84edf06c02ea2f2216867fbd39f86329f2558741c17f78643d052bb8eb83008": "0x00000000000000000000000000000000000a4b757361746f706961000000146b757361746f70696140676d61696c2e636f6d00000b404b757361746f706961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714538812c43fb3e37faa55a7d8768b4fac73f8c942e3639d378464730219023c5df0d4b2634b7db07c": "0x00000000000000000000000000000000000b56672042756c6c69736801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453b266b24dcdb964c81deb9f19b615125e4e4f316d5ffdcf2e24eb250126a1a4e60b3ac1eb0a2f6f": "0x040100000002000000000000000000000000000000000e57454233445241474f4e434f4d001768747470733a2f2f77656233647261676f6e2e636f6d001561646d696e4077656233647261676f6e2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453c8b0719674d5ad2ac4ff01309437984822f0b78beb305aa015cb11b01b993468b64a744216cc1c": "0x00000000000000000000000000000000000553756d6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453db9f22b39bbf09f8d7db5169156459bbdee84a522da4bc2110027b602154ca5b363abfff5e527e": "0x00000000000000000000000000000000000f4b7573616d612047686f6f73747a0000000000000f404b7573616d6147686f6f73747a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453e4f85431a5b93d464a24ea583d3b746841db2aa9af933ff6c1239ed2fc83d1aa424bcfbbd66b1e": "0x0000000000000000000000000000000000095342486f646c65720553616964000019736169645f626f737331303040686f746d61696c2e636f6d00000a405362686f646c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453efe4a2559eb48e920b814b0381e982418dcc9a71ff4248b63308d015b77acb31977ee72543de0e": "0x000000000000000000000000000000000009426f6b726f6e697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453f12a00f2f2c920388038a2455e863b7a51a8c6c2015c3c1001583db6c1068f0362eb73c6f9f804": "0x040000000002000000000000000000000000000000000f4b5553414d412047656e657269630000184073656e7469656e747275653a6d61747269782e6f7267116a6f7365407261626173736f2e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471453fdbf79c2885f07749f37b4b1d74040e735d5d6d683415de3c084e069409d863a7ff876c307a031": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145400dfd4fa6501fb4ee051c50b5c51b147d939e25ce61aa7e05af10ced2ed62ce7051509009ddf54": "0x00000000000000000000000000000000000d506f70707970697820417274001668747470733a2f2f706f7070797069782e6172742f0015636f6e7461637440706f7070797069782e61727400000b40706f70707970697831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454265aa0109191e386863b1e54bacf60ffc0a50e063b1bea72f2b1b1e9334173777e045f4c2ad618": "0x00000000000000000000000000000000000d4d61726174646a616c696c69064d617261740000176d61726174646a616c696c694079616e6465782e727500000e406d61726174646a616c696c69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714542d07047e260805305a014d7c8a0804316d2b4eb9e2e3cd6c1a021d60f1c6402c3c3103f2abf20a": "0x00000000000000000000000000000000000c5452554d5059204e46545300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145439cf6aa71671f74608fc7527698d3f4d4cfcc6074f01c2ed59112ad670dd5206b3658bbb62a073": "0x040000000002000000000000000000000000000000000b6f70656e6269746c6162000018406f70656e6269746c61625f3a6d61747269782e6f72671c6461766964652e6f70656e6269746c616240676d61696c2e636f6d00000c404f70656e4269744c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145460e0b925bf21dedef46db9b4a4808a39f261919782eb5530a835a5454e31ad95e1ead1bb67076d": "0x00000000000000000000000000000000000542544e5101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145486e9127d5c6ea83e6cdd1a5f9be051d4f9bde07d864b9a2d963d3ea06efd1ea6ce3ec73280f34d": "0x0401000000020000000000000000000000000000000008556e69636f726e0000000000000d407472696e69747931363132000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714549a808861f1a51754a244c98779e1b91c46999aa8713fc01b8fc589002d302fe54e264247228705": "0x0000000000000000000000000000000000075368657272790e536865727279204e677579656e010101000011405368657272794e3039353033353131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454a75c3f1924b5a8f4eba0e62e3993df8992425026148f7f818a9140343439eda6de9b85cf80d74c": "0x00000000000000000000000000000000000946656c6972616d69000d66656c6972616d692e636f6d000000000a4046656c6972616d69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454bcedbc59ca5b64fa3c3e2de0340ce354980a87c50a75447114c521bbf11d3366528e0e5507bc36": "0x0000000000000000000000000000000000074bc3b2c3b36200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454d7e633409fc98ca61cffec64bd3d89d7195fd423998178d8a4e6a0593ea5ced602f43d2e5ca346": "0x000000000000000000000000000000000009437361696e74303200000014637361696e746e303240676d61696c2e636f6d00000a40637361696e743032000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454e846fe38b60f59dccf45d8f5333a3cda7b160d6f930e1e3a97a84b752365745bb0f133af36027b": "0x000000000000000000000000000000000008574368656573650000000000000f40576973636f6e736f6e62726564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471454ec0e7f694e04f5fcf0c2ab943cebb940962bfb3cf3c29b9f3031ffe3257dfb57c87865e1c3817d": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714550a7f6530adfd1672f1cd51a567fdf672b0f622cac26b6b4b2b777f062d72b1278cd30f1f909a0b": "0x0401000000060000000000000000000000000000000014636f6c6c65637469766576616c7565732e696f001b687474703a2f2f636f6c6c65637469766576616c7565732e696f0019696e666f40636f6c6c65637469766576616c7565732e696f00001140436f6c6c65637469766556414c696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714550eb3eebb9a802e905a70f40069da23d88524866c0386eac29894ed423cf9f5c2715a375694c82c": "0x00000000000000000000000000000000000442424600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714554194451846f3f4140ba7452170aa67c1de4d8315d861cedbbd398ed74664d3c78397b0e10dea23": "0x000000000000000000000000000000000018546865204b696c7465642041706520416c6c69616e63650000000000000b404b696c746564417065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145548f72303df99a6dc926438eb65dfa069c73774ffafcba13d1519c0132d14a8537323feb356467e": "0x040000000002000000000000000000000000000000000d4e6963636f6c6f2047616c740000000000000d404e6963636f6c6f47616c74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714554d8e14cb2e6c614c909beaee469132767ebae5cc49961b19237150c0e983b4ae7ac64f23d83519": "0x040000000002000000000000000000000000000000000b626c6f636b7a696c6c6100001c40626c6f636b7a696c6c612e7465616d3a6d61747269782e6f72671a626c6f636b7a696c6c612e7465616d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455538dd590c80f13507c2d0784ffc68240a395784f16cd29f99f974a58876fa9e948fe4ffcb70334": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000001d4c75636b792046726964617920476f7665726e616e636520f09f8d80000000147279616e406c75636b796672696461792e696f000011404c75636b794672696461794c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455596bc6a00ad8cb92d11958f5d22465a5c44d5c4411437e57ca8bc73b0d61e332a6c4f698381d7a": "0x00000000000000000000000000000000000b53776973735374616b6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714556c80301dcc6c9cb22a4babf3715c5f87721f51b3c81da94e30982ff1208676559eb41cfee4a96f": "0x00000000000000000000000000000000002143726561746976656d616b65722020284461766964204172616b656c79616e29104461766964204172616b656c79616e00001d64617669642e6172616b656c79616e37373740676d61696c2e636f6d00000a40645f6172616b656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145579d397caf9629d608aa0febae80d8c228709183cf997bc87b0aa219cda0928408df22ac7ffef39": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455968c29c82cacff564ee20cf557d9908995750ee210fb123037816ada2d4a702bb54068100a8767": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455b22415a61f9221bcf7fa68ff79818686ee0a26bcff740a8b3c2930251fd15a49c6ccc64faa7508": "0x040400000002000000000000000000000000000000000948616e205a68616f0000124068616e7a683a6d61747269782e6f7267157a68616f68616e406c6974656e7472792e636f6d00000b4048616e5f5a68616f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455c8a048a9a0dce1d6ae958d7ee48f421e3e5c4adf7448c8ca260e9deb824e62ef108e7e25758d78": "0x00000000000000000000000000000000000c4c75636b7920426972647301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471455f668eb0e022b6af4f8d7504c181954de142fa5dc2dd3d7e79ce9b4f19b89cce879eb7f60bb5721": "0x0000000000000000000000000000000000055a69676100167777772e6d69636861656c7a6967612e636f6d2f7a0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714560e4606f61ab63ebe1f786c654c20757527b840d1d4a4ea6fc3b355d5791110ab8f8f0724b9404f": "0x0000000000000000000000000000000000114c69736120576c6164696d69726f7761114c69736120576c6164696d69726f776100001a6c697a612e766c6164696d69726f766131406d61696c2e7275000011404c697361576c6164696d69726f7761000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714562122059d1dbce57ca460cc927a04fbc91f4ddda54149556d1a85196bc753d054aca1fb7621e349": "0x04040000000200000000000000000000000000000000055649585900000017736175726162686772696e6440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145629138aa7fc2439fc079f0aaf5e36f2d2ad13f54b81924eb303eb0b47e3af372ded43049bc64910": "0x000000000000000000000000000000000008437572696f757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456437782aa58550c3801e22f05e304a3fff7124b7e1830b112e3466db9d8fb6cf1e8e9e79051662c": "0x04010000000200000000000000000000000000000000144c616d626f6d6f6f6e204d6574617665727365144c616d626f6d6f6f6e204d65746176657273651668747470733a2f2f6c616d626f6d6f6f6e2e78797a011779756475732e76616c6c657940676d61696c2e636f6d000011406c616d626f6d6f6f6e5f7665727365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145667d4d8a497c0945a2b916f6525c0639e089c5b221b61ff495cccbb4fb82fd4dbd6034a8ec4c008": "0x0405000000020000000000000000000000000000000009506172616d6269720f506172616d6269722053696e6768000019706172616d62697240706f6c6b617373656d626c792e696f00000c506172616d6269725f3137000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714567dc72806fd2ef9d453b6e497b6a89979fb34eea715720d37c2381c8c51458be04296fd059dcc3a": "0x04000000000200000000000000000000000000000000044a4a4200000000000008404a4263727970000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456842ac04118f270ecbab750f5f7563a45e30f4b4ce064248400b90c5f8d06158944dc94bc6d5236": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145687eed0089938017caa8fe3fab162b7508198c9ad5b37c7af8b02cb70ac48da4a5f98c505c7155d": "0x00000000000000000000000000000000001052616b73686173612053747564696f0000001972616b736861736173747564696f40676d61696c2e636f6d0000104052616b736861736153747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456a1c5009025aa2bb6c090fcf1675617fdd8ced70d7567c5dc707782d10d9570430ef02194c75067": "0x0000000000000000000000000000000000154c6f6b6f20506f6c6b61646f742077616c6c65740e4d696775656c20426f7267657300001b6d696775656c626f726765733739313340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456b436eb439d2e4862586fe7c5d0173262986d66edceb58dfa24f4ba4f35aed0f37228ee9ffa4f00": "0x000000000000000000000000000000000005416c657800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456cebd3283e0ea933a3884dbc6806e8b4cccbf2c407d800c12141c3d7cacde442a649a6a2822ac17": "0x040000000002000000000000000000000000000000000c53454b4f5941204c41425300000013746f6d4073656b6f79616c6162732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456d57c08aef106735ecb86012e4c9df3676d3ba24512ff0c5b3509a4282b4290f095da42de17eb56": "0x0000000000000000000000000000000000064261626172064261626172000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456ec9fbeed402237beb4f57329d674153ba91c3d1a21f744e48d79e8879f1213bc2099a3eb241429": "0x000000000000000000000000000000000009524742416e6b7379001d68747470733a2f2f6269742e6c792f524742416e6b73795370616365000000000a40416e6b7379524742000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456fcf1e5447565198ac9fad47064fa58342aea6727b9e45076283c71a6447534c444f163eb426813": "0x00000000000000000000000000000000000c50616e6f707469637573200000000000000d4070616e6f70746963757376000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471456ff64b33828b8d02a3a79d6cb82c0f1fff14cbb78d3b7fa64b5a9a3fd9c54fd4e78a5cbfbade710": "0x00000000000000000000000000000000000648616e697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714570905ee38b668978c7da506845d451b9510e7ac2e7d30c36e72a5f39e05d427f9e79719724a5a3e": "0x0000000000000000000000000000000000115468652042756c6c697368204f776c7301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457130fa04591b33060283de9f5beb93ac69b24ca8c62f60f39b8c80758d807aa244532c66b67bc3c": "0x040000000002000000000000000000000000000000002153616e746961676f5f47757a6d616e28656c63726970746f7061726365726f290000001d6469726563746f724063726970746f6c6174696e666573742e636f6d00001140656c63726970746f7061726365726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145721ebba28d18ffd9c84f75e0b1b92f6b003bde6212a8b2c9b776f3720f942b33fed8709f103a268": "0x0400000000020000000000000000000000000000000006616e6472650d416e6472c3a92053696c7661001140616e6472653a7061726974792e696f000000000b616e64726573696c76610000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457303e92e8fb25ab9a83298c34e9c1f3f325afee086ab423e88645861ad8c9e380e4bc3ef7046e07": "0x0400000000020000000000000000000000000000000006526567686f00001340726567686f5f3a6d61747269782e6f726710726567686f4079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714574f6106315eb5517418571179b97e88a57328ecffa64c08abd0dfb5ff50be36e00582e56c5b8955": "0x00000000000000000000000000000000000c706f6c6b61646f74626f6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145771ae952ce319e894390dfcf349f8a5e73597a2e96ce1344cf8272e990489a08c24ac30d9027953": "0x0000000000000000000000000000000000074b757261726106446172696100000000000b406b75726172614e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457845cd05536c32e9c6ba1325d8dc7cec809ce61640c9ed92d18f0d818a4c102c2c0ea4f29820136": "0x000000000000000000000000000000000004546f6d09546f6d20686f6c64000017636f64656861636b3737373740676d61696c2e636f6d000009404b534d50554e4b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145786fc402111e82d5202845d849d9eb6a7e5a414492a86d205be4a374ede34e98fc2440de4809a3e": "0x040000000002000000000000000000000000000000000c556e6f205374616b696e6700001740756e6f7374616b696e673a6d61747269782e6f7267186f70657261746f7240756e6f7374616b696e672e636f6d00000c40556e6f5374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457903c6184bae82f5a090c88f0438b46b451026597cee760a7bac9d396c9c7b529b68fb78aec5f43": "0x00000000000000000000000000000000000d5365756e204c616e6c6567650000000000000d407365756e6c616e6c656765000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457a1aae68bb3807a7ae8740550b3d4de49d50fb4e83354786a6ffc5c166d7b876c31baae7388ea51": "0x04000000000200000000000000000000000000000000054d414473000015406e6f626c656d616e3a6d61747269782e6f726715676f6d6164736e6f646540676d61696c2e636f6d00000f4053657267654e4d617263656c31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457a5cae663c515ca00ecaacb451648a3660fe122ccc2c32cfd9459ca6dac9f10cbf7a0ab60c61318": "0x040000000002000000000000000000000000000000000d4a414d4553204147454e4441000019406a616d65735f6167656e64613a6d61747269782e6f7267176a616d657340686f6c64706f6c6b61646f742e636f6d00000e406a616d65735f6167656e6461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457a97c250c6d982f788f24f65de10ed710c10f5daf367e9ca57d8a998cf6bd13d7cdaf6937e16d68": "0x04010000000200000000000000000000000000000000184c696768746d616765204b534d2076616c696461746f720c53616d20456e672053756e00001473616d65733230323040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457b1a86eeaa2582dda1a090ac84e6183dc9e7e3369cbab0ca51afcc7133b1324634093753a483e11": "0x00000000000000000000000000000000000f52757368696e672053747564696f0f52757368696e672053747564696f1a6d656469756d2e636f6d2f4072757368696e6773747564696f001872757368696e6773747564696f40676d61696c2e636f6d00000f4052757368696e6753747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457b1fed518565181aaa635f88e75ad58af28925d0c21a804d87a449469e45970c3a52f57aba7b366": "0x0404000000020000000000000000000000000000000008486f646c6f6e690000001874656d70696568616573736c7940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457c41eaef46fdefb2ca8e96b721f074e95a3f7d994c370dab688fc85134de7e2e7d4589d0a306c51": "0x040000000002000000000000000000000000000000000842696754756e610000144074756e616269673a6d61747269782e6f72671574756e6162696776616c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457ce53ed6bf695bad6266aeeea11e5bcbf8d5a1b7255a363aa2635083e0e0aee6ab434fdc3f1b511": "0x00000000000000000000000000000000000848414d5a4941530e48414d5a4920412053414b455200001a68616d7a69616264616c6c6168393640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457e0f36f0fe2bdee54efb33a98824d6330a8f074481df98b5123305473559bef960180791f849252": "0x0400000000020000000000000000000000000000000008426572657a6b610000154074696b74616b33343a6d61747269782e6f726715696b617a616b6f766e6e40676d61696c2e636f6d00000f4063726970746f637468756c6875000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457ef873d5dca9de5ac09149a298fb86b4ecb5c648a2d37e8dbd6da2ad3f265179eb5daa903c3f73f": "0x0000000000000000000000000000000000046b736d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471457f4780677cf709b4ec0381e4427ed6567f7a5c328288ced36c33becea6ececd8145001f4230ac1b": "0x04020000000300000000000000000000000000000000185869616f207c20e586b0e993bee7a791e68a802d4742430f44722e205869616f205a68616e670f7777772e676263746563682e636e1340787a68616e673a6d61747269782e6f7267127a68616e677840676263746563682e636e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145805cd76b5154e33e6b0690ac14357ff8a2228b2dca5e221badf5d252d94ab08dbcefb2004d5214e": "0x00000000000000000000000000000000000000000013736f6b6f6e66747340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714580dd48e484c5f2972a45f5688398a40b4bebab307d097de95cda8220d74e053fa0b7b77f0c36e14": "0x00000000000000000000000000000000000d5761746172754b6f73616b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458138ec91336832cb4dd8fc49aa15538543007347b1df3f4bf948ed60474105c19819a311fdced43": "0x00000000000000000000000000000000000c416e61726368792041706500000016616e61726368796170657340676d61696c2e636f6d00000d40416e617263687941706573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145839ea98689b2889bc6e12d7ab70abea4c08db7055e84f16bab817b5fb359088ad5190422df9dd1d": "0x040000000002000000000000000000000000000000000e416c657850726f6d6f5465616d00001340616c65782d6d3a6d61747269782e6f72670000001040416c65785f50726f6d6f5465616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714584010d60675c6289a8cba76944a9dd66c20b150c5821f2b6c3fb5c7896b9a3e889d574f48d3d50c": "0x0402000000020000000000000000000000000000000011494f53472056616c696461746f72203211494f53472056616c696461746f7220321068747470733a2f2f696f73672e766311406a6f63793a6d61747269782e6f72670e68656c6c6f40696f73672e766300000840494f53475643000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145853e7deee1e01320c3e1db6b821c4e5dd8d3199aee048377eeb692392743d43e7196d4f8d52e212": "0x040100000002000000000000000000000000000000001344455720436f6d6d616e642043656e746572001a68747470733a2f2f7777772e6465772d7374616b652e636f6d1440646577706f6f6c3a6d61747269782e6f726716646577706f6f6c406d61696c66656e63652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458554ac760f837f7d8f7fd9ee2b808717305d4bbc06e1ed5aa519e75c398f6dad27e1c1c026c593c": "0x00000000000000000000000000000000000b45736b696d6f204a6f6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714585c0f93d15e98cb42f3c525c66f2a4eacfa88479f7537670d2e1f45f4ec25703a111f5f003ba15d": "0x04000000000200000000000000000000000000000000145374616b696e67204c616e64207c20457269630000001265636f7637373340676d61696c2e636f6d000009406572636f373733000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714585dc428f7abc0d304b28d3651a60f46affd3f6b3b5631bf8e1181a53911bc83872183ed80f92641": "0x0000000000000000000000000000000000033838000000113932343131373533384071712e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145879c1214022b88dc8566f6d3669729e877cd5e453d59f6be01ae6f31b7a9c9925160e70072f7242": "0x04000000000200000000000000000000000000000000084d555348494b410000134062726f776b613a6d61747269782e6f72671069726f6e406875626361702e70726f000000000a49726f6e233933323600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714587c6bbae1bb420cf2d0eed0f21b82d4b15802153cde2a229f257f01d003694b2973ef785a734766": "0x040100000002000000000000000000000000000000000a416e6f6e7374616b65001668747470733a2f2f616e6f6e7374616b652e636f6d0016737570706f727440616e6f6e7374616b652e636f6d00000b40616e6f6e7374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714587c6d66c4c89f37ce8bb3daa399b23c4c37885a945461ca1e15579969152bd06ad91aa42a901c45": "0x0000000000000000000000000000000000095261626269747373000000186461696c79726162626974737340676d61696c2e636f6d00000f404461696c797261626269747373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458929df6c9d6b10576a95bd9907b8b23244d8d127f6218e662a8098b03338c02b70926cff7215812": "0x00000000000000000000000000000000000849736c616e6473054c696e6100001749736c616e64732e726d726b4079616e6465782e727500000b404c6567696f6e383837000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145894bbb4b58b7f2a267bb3686448c8f8e75390a649826f7b524f9a9768817678333e405f03b2330e": "0x0000000000000000000000000000000000036b790273010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458b1d929f632e2bf305941b16193089ecff9efaea02756aa01cca8a54406d6cdc44f7d4b3ec7fd37": "0x00000000000000000000000000000000001d4c696e646f204a6f736f6e202850656163685f6e5f506561726c732900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458b50dea3d326a26e61e809e1d333966b27b8a6ad71850881f0a7f534caeff85ddf6c9cec0b3763b": "0x00000000000000000000000000000000000e50756e6b205661756c7420233500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458d6ba7bdbadef08f05f73ff22478af897ca6ff58c5152c641fe41bfbb168ec437b1e699c18ced5d": "0x040400000002000000000000000000000000000000000b5169756861692047756f000013407169756861693a6d61747269782e6f7267157169756861692e67756f40676d61696c2e636f6d00000b4047756f516975686169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458d8557741d41ae44e4ac8070fea95496b63cdcb6987de88f63dc75a295eace6ce5079149169300c": "0x04000000000200000000000000000000000000000000044b594200001a406b6f73747961796573696b6f763a6d61747269782e6f7267196b6f737479616573696b6f76393040676d61696c2e636f6d00000a404b596573696b6f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458dec35f4d8ac0dd708b394ff79e4dcdd95357d1f6f5eb4db7314ea5bddad55e9b1507e58059cc3f": "0x00000000000000000000000000000000000c53565941544f534c4156310c53767961746f736c61764e0000177a6164616a616e697930317940676d61696c2e636f6d00000d404d5370656b756c79616e74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458f0e1d56d9c06ae72cf375dbf960070e09942d1eb553973beac2e3d410a30a87e1271c53d1c4b13": "0x0000000000000000000000000000000000084b6f646569737400000000000009406b6f6465697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471458f78aab94d3b05202ecd7386aa07e755cb458b790699dbcf09458279ec393f5384ff7729da38d10": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714590171a64e0cbc98e6482c69539ce311c0cd1b067d98be8f177fcd9620f938a48f3e61353bbd0367": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714591121c7e29722e2043fef4609e750d25d21d9fac3f3144e2cacf1f758e70dc4a23dc848e140850f": "0x00000000000000000000000000000000000943656b697264656b000000000000104063656b697264656b5f6d65647961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714591a0dfab85943a49e28e10189b8bdd0e4980086b6c36728d840932128ea4bce3db2f26032c15114": "0x0000000000000000000000000000000000074a787264786e074a6f7264616e00000000000a406269746d656d6578000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459212f1c3da6903f24172a563943291c97d252def71e17abf467a1626bca358728a90a82b3de3118": "0x040100000002000000000000000000000000000000000e5a4b43484e2e52594142494e41001368747470733a2f2f72796162696e612e696f12407a6b63686e3a6d61747269782e6f72670d7a4072796162696e612e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459368261611b8625ee3f7f4c2dbe3c27e5e524c226ef9e65b827498e0f53b5c3592d4b6b884e6d55": "0x0400000000020000000000000000000000000000000004707467000000137465616d7079617440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714593a90e3bf5c060f765a97770360b61055ecfbe9f3790d29fe8dcac870716c5464cd4ce27c3f4744": "0x0000000000000000000000000000000000084472616e6b73790f4472616e6b73792041727469737400000000000f404472616e6b7379417274697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714593b2319048c7897fc6b29e92d65b645a56a0d44e3f4879eb82f3c5b50341cfa61aad9edeb7cbe0e": "0x000000000000000000000000000000000003656600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145943caacae6ad2f25aae17b541f38373368901648429badf112a0dcefd9a8976dc5b8d6acebf7425": "0x04050000000200000000000000000000000000000000096a616b6b796f6e650661726d656e0000136a616b6b796f6e6540676d61696c2e636f6d0000104043727970746f61726b657469706f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145964965cb7d831cc9e819e2426df687c803ee2abc546c68bb0267ea7652029e7e242ac75a83ded24": "0x00000000000000000000000000000000000944616d69656e4d6b00137777772e617263686976657273652e6172740016736175636564616d69656e40676d61696c2e636f6d00000e4044616d69656e5f5361756365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714597947638d09aa7a7a5b71ff1acdfd938cac1b6b115ca5479c392d1fa5d9d78c1770f0042a9db811": "0x000000000000000000000000000000000013506170696a656d20706170696b697263686508426f7961726b6100000000000d40506c6179657248656c6c61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714597991a0ac94c2410af5599c203182b0859805283944d9a8df0d788a52a37423ef002cc5889f5764": "0x00000000000000000000000000000000000c6d757461626f726174756d104665646f72204e696b69666f726f760000126665643232323240676d61696c2e636f6d000011406e696b69666f726f765f6665646f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714597a2e1f5ab12e08025741e5e3fa614b7a17855d223f48d4ac98bdaf45c11e67963cd0b4fbe0081f": "0x04000000000200000000000000000000000000000000104261657a61204b534d2053746173680000001373676261657a613140676d61696c2e636f6d0000114053656261737469616e474261657a61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714599ea05228cbabc6429a9eb3c6a1f14b291fbd2c10ae3b6dc3fd95fab0ab0072122a90c2f6529057": "0x00000000000000000000000000000000000f5461626f6f2047616c6c6572792011436f6e74616374203420636f6c6c616201010100000d4079616d696e617274697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459a857c5ae03b5a7ece6a4bff0a206e9739e9f05b36e23cafe0e59d2c5fc1adf3d00069160ec6319": "0x00000000000000000000000000000000000b4a6176696572204e46540000000000000b404a61766965724e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459c0a69a8bc9cd0c3e89f6d3fe88c432363723082d6d6cc6e5b3c09a1b4087dd409bf8804b1f7d57": "0x000000000000000000000000000000000010506172616c6c656c2063757a64616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459d3ac6be2fd0312ce6ac62a23361838caf62d10c11a08b4ef6048cd2d8819abbe0399f2da40da68": "0x00000000000000000000000000000000000e43727970746f4f7665725553440000000000000f4043727970746f4f766572555344000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471459fb49563ab8f0448629b0221568837ac8c93a4534c77b40e4f07dc7dca8e7ab9062914c6d5cd64e": "0x0000000000000000000000000000000000204b494c542043524f57444c4f414e2046554e44494e47204b52414b454e204900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a20e5cb7fcd59317e4d3937a8778981c0365ad2faff4ca846c9d910ec1196e66f9fa0ae5a469c2f": "0x000000000000000000000000000000000006354e344b3300000000000008406a6f63323430000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a322d41358015c5820e859e96c107c3dc5e0b110d8e5a7fd2bf312b511b00a5a45e59eeec47d741": "0x000000000000000000000000000000000009436872697342434b0000000000000a4042636b4368726973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a53642bcce8d5192055808c210d863dfc372ec85beafa8fd3a8ff497f8eaee401ef05bf27d3065b": "0x00000000000000000000000000000000001f4a696d6d7954756465736b69202d204b7573616d61205265736964656e740000001b6a696d6d7974756465736b69407374616b656e6f64652e64657600000f407374616b656e6f64655f646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a5afe08a0a9de9ed6aadb9a7f66a45224f6f83011f854c0b5758c626b213f97cbffded94830507d": "0x000000000000000000000000000000000005f09f909c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a5f25d1ebffdf66facdca5effe8072173c4c12f7bce4d0e693e5feb83f7926bf1a8c7ffd1caf14a": "0x000000000000000000000000000000000008536576616b3438000000144374696c657236303640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a69592e77fa7ad2d8dd47918c70f35b60c098e90f3ddb7aaab24082cb7043be071bf323f10b3928": "0x000000000000000000000000000000000007454e31474d30000000196672656e6b656e737465696e373740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a6c990eb5706de2f6d5d7a1f11d32d33bff1d878db5eff7462b104818a869e89f47034210c88812": "0x040000000002000000000000000000000000000000000763727968656c0000134063727968656c3a6d61747269782e6f72671163727968656c40736b6966662e636f6d00000f4063727970746f68656c656e6b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a84a36862a690700210f894089a5fd3e91bcc8f6848717c556f002438cd902c40af4d031e9d5e21": "0x040100000002000000000000000000000000000000000c46656e6e656c204c6162731046656e6e656c204c616273204c4c431768747470733a2f2f66656e6e656c6c6162732e636f6d1b40726f6d756c757331303a66656e6e656c2e656d732e686f737414696e666f4066656e6e656c6c6162732e636f6d00000c4046656e6e656c4c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a8a8fc110b069894a0ac27d662bb3987c4f0568f1d048d57dc25a1479fdee48cae7b7cf6eaa8d42": "0x0000000000000000000000000000000000084472617468696e0000000000000e40616c696d617277616e693130000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a8e89c3cf824328d0962c02edc80c0e947917fbb8b18e5811c1f3be76938130208f71aa07f0f909": "0x000000000000000000000000000000000011436f6c6f7265642050617261646973650854617469616e6100001374616e7961626f796172406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a8ebd7db5efcab1de575b9b9da6c9296693e2c37ac5f38c1d84f64a7749a5c59edd1951fb5dff12": "0x00000000000000000000000000000000000654455452410000000000000c4074657472615f636c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a951ea190277ac2de78f9ebf672082a2ed1e9d5b00430dbf6d0284fe3bbc4176f140e934d3b3b2d": "0x00000000000000000000000000000000000942657253746576651053746570616e204265726c697a6f76166c796e6b666972652e636f6d2f6265727374657665154062657273746576653a6d61747269782e6f7267156265617273746576656b40676d61696c2e636f6d000010404265726c697a6f7653746570616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145a95852911b4bab1a41f73a80d77cb1ca2a8ced7f20a74c1677edb562b37e8a16310b89187cef94e": "0x00000000000000000000000000000000000853747573616d610b53747520426973686f700000177374752e702e626973686f7040676d61696c2e636f6d00000c40737475626973686f7033000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145aa8315fde207d41183982ce80e4b52f2e80aaf36d18b1eba1a32005ffbefd952962227f2f4db309": "0x00000000000000000000000000000000000f477561726469616e7320f09faaac00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ab174fa9e055d169cfe0b920dc749dada372dd02f2b5d60cbf9081a05ed65c7df35e4e47c593c01": "0x040000000002000000000000000000000000000000000a4b7573207374616b65000016406e696b735f67656e6e3a6d61747269782e6f7267157472656964636f6e323140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ac78869847a814046d41e304d6e7344c6509ee4cd56eb032090b86436ae5fca4ea3a357018a0659": "0x00000000000000000000000000000000000000000016736572676f35363534353640676d61696c2e636f6d00000a405365726730373136000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145acf1d24617d25ba6a88b4d1ab30ab4708521d6c6d480a858d92692c0b0cff67e1a6904e23b84112": "0x040000000002000000000000000000000000000000000a68617070796d65616c0000164068617070796d65616c3a6d61747269782e6f7267146d617276657238333340676d61696c2e636f6d00000d4068617070796d65616c6368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ae21247553af3c4f683b2e8b27985776e127615b3dd6362db1d252d4136112efb7451838cc62e4a": "0x000000000000000000000000000000000012426f68656d69612047616c6c65726965730d426f68656d69612046616972147777772e626f68656d69612e67616c6c6572790015426f68656d696144414f40676d61696c2e636f6d00000c40426f68656d696146616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ae3d02694d32b74b4154f12cdef88338edfa85cbdd64b61c410187e4f7971057aef32cdafdfb702": "0x0400000000020000000000000000000000000000000016f09f9bb8205a6f6f70657220436f727020f09f9bb8001868747470733a2f2f636f72702e7a6f6f7065722e6f726717406a6f686e756f70696e693a6d61747269782e6f726710636f7270407a6f6f7065722e6f726700000c407a6f6f706572636f7270000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145af116176166f3dcdc891490870515c71014938641e9b09cfbfadeb502b16d67d2cff9145aaa9a75": "0x0405000000020000000000000000000000000000000009426c6f636b41544c09426c6f636b41544c1a68747470733a2f2f7777772e626c6f636b61746c2e636f6d2f0015636f6e7461637440626c6f636b61746c2e636f6d00000b40426c6f636b5f41544c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145af3c641a81d6a63eaacc14e67deba7935dc28c86bb8b6bdb64239065b718fed6b8691ce14163350": "0x040000000002000000000000000000000000000000000853494c49434f4e000018406b6f6e74692e6b6f6e74693a6d61747269782e6f72671b6b6f6e74692e6c696b652e6b6f6e746940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b03e1028650b87eb4ef79231816c3f685dbf10c86eacea23af48909a856957b41dfbd75ac36524b": "0x00000000000000000000000000000000000a506c617965724f6e65000000146c6175726f2e6b656e40676d61696c2e636f6d00000a406c6175726f6b6966000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b0f569c80b1ef944889a8a8910ca711d463b40c9216c7007638c77f4f62fa37ad1f05b5fc386e0c": "0x00000000000000000000000000000000000f4a757374526f636b657443617368011a68747470733a2f2f6f70656e7365612e696f2f446f6e4a5243010100000a406a72636173686868000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b174056fc3b6e14dc9163ea2d0bf58ceaf597668ac362d5723f061642ef6dbd498e5088f11b2225": "0x00000000000000000000000000000000000a446973727570746f7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b2364935bdfff38fa27cbf66115a030147d7e427273ca01ced9332ac5ca8883927d41f121f60651": "0x00000000000000000000000000000000000e736b6574636879206a61776e73012168747470733a2f2f7777772e6162616e646f6e656463656e7472616c2e636f6d0113637874726f6e636f40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b2d54fd29af31b28691026aa386df1bde178237fd99072af73d9fba71b0a350dff42db8bd2a4279": "0x00000000000000000000000000000000000447616201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b3a26a81f77f16fd623d05214a4c208f0dc52cf4eef865afccd55bfedd175856129aa3048d38174": "0x00000000000000000000000000000000000e4e465420436f6c6c6563746f7201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b3e4fda94e65239bdde527f50b491568aa2085ee12c5535d7ce765e180399a038eac99654a31ad5": "0x00000000000000000000000000000000001b53595354454d20434f4c4c41544f5220505552452050524f585900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b48f080beb98586a8ca45025561ad23d3000cef010fb14901ba322283898e08c3d0a7fcdd03ce5a": "0x000000000000000000000000000000000007446542616e6b001368747470733a2f2f646562616e6b2e636f6d0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b4c4e58d29949859a2cb674ea2f4866664769a1663fd6aa321d9cfb89b67c402c881891700c0f57": "0x04000000000200000000000000000000000000000000084c6962657274790000001c6d657461706172616469676d4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b55dc011bdbdd6c4c50e314596f61c5d9d8d93121d1fb03734be5b91e7f4d89eb5fddf130148274": "0x00000000000000000000000000000000000b4e696b75737961363636054e696b611e7777772e696e7374616772616d2e636f6d2f6e696b757379612e36363600156e696b756c696e39313140676d61696c2e636f6d00000d404e696b757379615f363636000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b63e90199fb6234a42f4d0ef9a0113223ed286071390af15142d1ca267cb1683a5bf6e8f492de75": "0x00000000000000000000000000000000000a47726f6f645f696e6b094e7572696464696e2168747470733a2f2f696e7374616772616d2e636f6d2f67726f6f645f696e6b2f001367726f6f6472617740676d61696c2e636f6d00000b4047726f6f645f696e6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b71d956514a077d9ee54da7df7f0e7ca7a874fa03f8094681e9db42994f0b21cd215fed704c3b37": "0x000000000000000000000000000000000009796f726e6161746809596f726e616174681f68747470733a2f2f6769746875622e636f6d2f676f72696c6c6174726f6e00126a6f726e407a65697467656973742e706d00000a40796f726e61617468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b8f8631883ea6dd1e568033ec5a6695a6f27b6e2cb4a2b6dbdcf497c0837fa0272e31019a69ea29": "0x04010000000100c8e6bc170400000000000000000000000000000000000000000000000000000d61726e6f6c64736d616e676f0000194061726e6f6c64736d616e676f3a6d61747269782e6f72671376616963756c697340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b908e9c38f784a922592d747d00fa956a6388eccfd7c7684191178e62a1e6e2b12758ff447fc402": "0x000000000000000000000000000000000007506f62626c650000000000000b40506f62626c65417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145b959c6eb8b10f975ae160771e1bffc404bfedafe29a049e2804721a4932258c8a89e7a9cd5a2632": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145bab0f6894110edcd06077d6ae735ec4a8fc88f424db70b0dec1e9bae95e39d2737a105296af462f": "0x0000000000000000000000000000000000094b534d204d61696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145bc7aeaa278c7e8dda0ab7aa04417272602b517a5e25b783a5aac2a251495eb12d5a4d64ea0d7f7d": "0x0000000000000000000000000000000000074a454550455200000000000009406a656570736f37000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145be3d49d6a02aa76663628177efedc10b4ffa4c6765b525575ed6a6128b945d93c02b45d56358255": "0x00000000000000000000000000000000000b426561722054686965660b426561722054686965661c68747470733a2f2f6c696e6b74722e65652f62656172746869656600186265617274686965662e6e667440676d61696c2e636f6d00000e406265617274686965664e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145be620e3757932d22e0299102b6e06b617097dcc0380612e6d3ee0692721d984a3e92b5520d5095e": "0x00000000000000000000000000000000000f52657475726e65642056616c756500167777772e72657475726e656476616c75652e636f6d000000000f4072657475726e656476616c7565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145be79f90404ad9e0e4a66ee66171e3238670377bc9ffbd7cb4bda47baf25e6ed80c2070942ee3f72": "0x040100000002000000000000000000000000000000001070617468726f636b6e6574776f726b135061747269636b20486f666d6569737465721d68747470733a2f2f70617468726f636b6e6574776f726b2e6f72672f154070617468726f636b3a6d61747269782e6f72671f70617468726f636b6e6574776f726b4070726f746f6e6d61696c2e636f6d00000b4070617468726f636b32000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c0211d083cd891e2594a69ff79c03f8cf57c80cff2d29d4a62d07787e70838463232e42b694a260": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c35b09fcd09a3c258fd2bfc348cd72f4b516fa5d07dbae2f170724947cac5a578a0cd43d30bce38": "0x00000000000000000000000000000000000e526f636b585f4b7573616d613406526f636b581268747470733a2f2f726f636b782e636f6d0012737570706f727440726f636b782e636f6d00001040726f636b785f6f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c435ff0076da260aa4370d01e3beef9dd9b535ed1c7957cc66685f15cc203189f1245013f92f14a": "0x040000000002000000000000000000000000000000000c56657261636974792e6669001868747470733a2f2f7777772e76657261636974792e66691c40646f75626c655f6f5f74686576656e3a6d61747269782e6f726711696e666f4076657261636974792e66690000114056657261636974795374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c5ab5d3c9934ab83e8b471e99fa0edd1730046ef2d4e82f66364dc513f52dbd0fb1ab561cc33e17": "0x00000000000000000000000000000000000b4672616374616e617279000000156672616374616e61727940676d61696c2e636f6d00000c404672616374616e617279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c6592b134c699ba187444691216a55e3455ee1ed462d54ce0b635a1b2b37d0eb7625faa31218877": "0x0000000000000000000000000000000000074f56c2b9c2b9154f6c656720567973686e6576736b7979c2b9c2b91e68747470733a2f2f767973686e6576736b79792e636f6d2f6c696e6b7300156f6c656740767973686e6576736b79792e636f6d00000d40767973686e6576736b7979000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c6b1c34b6431f3840b9259dde4ecf577907b60e73ac636e896ac881e1f44c1bab1062fce8edef10": "0x08000000000100902f5009000000000000000000000002000000010010a5d4e80000000000000000000000000000000000000000000000000000001942414a554e204e4554574f524b207c20616a756e612e696f0e416a756e61204e6574776f726b1268747470733a2f2f616a756e612e696f2f1540726f786f6e746f783a6d61747269782e6f72670f68656c6c6f40616a756e612e696f00000e40416a756e614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145c7a1f1f152d77a7e61ccc992fa2dcd65b95d4f77ce0f63db60e2bdb19cbfec36d300f44069c751f": "0x00000000000000000000000000000000000d42696c626f42616767696e7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145cb77214d79cb5a2fac0b420b2c0787c18368b8685cf54606b59fd34f941ce2f31fdb91534c6bd53": "0x00000000000000000000000000000000000f496e7370697265207820524d524b0101010100000a406363776461766964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145cc468a5aba1dfd7cc0460228b1d0c8cb99d0b025dcffabfad0f11c8b61297a9dec7d7a2f72c744d": "0x00000000000000000000000000000000000e43616e2d417269732044656e740000000000000b404154726f7531393835000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145cc5698ecc3af260fe2c90d31ad2500e8b1358efa80aa7170e5887de4687081c24def3fcdcc43d07": "0x0000000000000000000000000000000000037879037879000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145cdaddbf5de66df5623470253bd540d69edadc8a758e8dbeb532a66c9eb39311e7daf3ed2466d25d": "0x00000000000000000000000000000000000a686f70657361696e740a686f70657361696e740101176e696365726973653133333740676d61696c2e636f6d00000b4074776974706f746170000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d07888ff9ed46fc58994e72c04b7c36de2b08b119e7abc2870c51f2315a4980e544197e706e7874": "0x04000000000200000000000000000000000000000000074a656b736f6e00000016657667656e6d617373383440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d12ddd9ba6fb6ca0cb2d216a8ad7864f222d92dd6636ae1ff0fd9151ca3b60e0bcd2d55ec25ab4e": "0x00000000000000000000000000000000000a5b41525453414d415d0000001661727473616d612e6e667440676d61696c2e636f6d00000d4061727473616d615f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d3dec38e02e37251c6d8b40be9990c19e993d238e6e3613cfc6cbc51979d5fa61dd6ea259385609": "0x0400000000020000000000000000000000000000000007416d666f72630a416d666f72632041471368747470733a2f2f616d666f72632e636f6d00137374616b696e6740616d666f72632e636f6d00000a40616d666f72636167000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d42f9745219ed50b6b86c53a0db7f8b293e164a22bc0c47d4cd554e3ab2f1f8c4dde73f2227c574": "0x000000000000000000000000000000000010636173746c652f524d454b61626c6510636173746c652f524d524b61626c6500000000000c40636173746c6532353331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d6c6374575f1684f47abec3c5269249303575bb90c763d420fb6148e567841105815cd63152c121": "0x00000000000000000000000000000000000d4368616f73204b696420763200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d9004d360afe69f265dc7b1a304621252fdbb2e64751d958a3ca006f359f4987fd9a77f9b22124d": "0x00000000000000000000000000000000000b636170656c696e686f7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d9e8b6d1aaa8f64e8e5969ab8c6f6f4d63b090863923fc834b24583c0f2363e00edbd7b7b296011": "0x0401000000020000000000000000000000000000000008766f6c3474696d001c68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b2f1440766f6c3474696d3a6d61747269782e6f72671773617340726f626f6e6f6d6963732e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145d9e956221876f960a49a73df6ad2c6b41b8a01c54e34488b27cf010c22af4ad2b46baf013c75303": "0x00000000000000000000000000000000000d5469676572e2938874796c6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145da16a0301baa67d9e1e5d3c3e1a8f1018f081a7d998ea6684e823165a3bf8f18d0838c0ab9fc531": "0x00000000000000000000000000000000000e47396536207c2043797068657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dac9d84545257d0e49291d5619f4363858a3528f102f0270fb36e1eb3283e3c1f6478a4e48c8f35": "0x000000000000000000000000000000000013446f745363616e6e65722046756e64696e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145db29c27869ebe6dc20d53e9595db5afba8fd5320b11f3fa6970ab4335c7517f86fbbc7560bbbb5b": "0x04000000000200000000000000000000000000000000134d696d69204c65742069742068617070656e0000001a6d2e6661727265732e72696d62617540676d61696c2e636f6d00000c406d696d69666172726573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dbe0f77941d0faafa383fb921b3c46f10d51250fbf855bf1de45709fb43db76534a8bdfd072e479": "0x000000000000000000000000000000000005676c736b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dc126cfaa025d1aac2139e2876b295c93ed453f5de79048754ed32e3ecdd7991584200e822c4532": "0x000000000000000000000000000000000006417274656d06417274656d000015617274656d6b7574726140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dcfddbf8eff24b40c1b579fe2da2803945658be583be68ae72980152018d8dff7d8a83f27f37d73": "0x00000000000000000000000000000000000a43656c657374696e6f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dd8f42acc19bd83d2c5ddbad0ff443692047d533ca5d92693fb03f15c740757264643133eb5d542": "0x00000000000000000000000000000000000a4b7573616d614875620a4b7573616d614875620016406b7573616d616875623a6d61747269782e6f7267146b7573616d6168756240676d61696c2e636f6d00000b404b7573616d61487562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145de66fa01fb4c2d708b3b1930f36bf7fa336c7abc044e75fea45cf1c903081e7e0bfbd664a80093a": "0x0401000000020000000000000000000000000000000008434f534d4f4f4e001568747470733a2f2f636f736d6f6f6e2e6f72672f1540677265676f7273743a6d61747269782e6f726715636f736d6f6f6e40677265676f7273742e6f7267000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145dea83f53bc9588fa6e49f5e4ba8e10080d8f963dc77cc2a1bd11c0426542a26ac8a0200bbd03c3d": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e09b43fe9323929ec586c840ae4772a0c0068d8202ce6baa96408294fb32e03bf3e44984307ff1f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e0b461bbe90623fec95ed93ac7c2ef8f9eeec8e072f236841214fa59bad12f4d6d2072490922753": "0x00000000000000000000000000000000000a44697a536572676569001c7777772e696e7374616772616d2e636f6d2f64697a7365726765690000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e12dc698b4a5bd2d01ec8518f4e2a34834d5d62d8091e8aee663e4446bf8c1ad1d9b02e58a22568": "0x040000000002000000000000000000000000000000000d6b7573616d6178692e636f6d001568747470733a2f2f6b7573616d6178692e636f6d15406b7573616d6178693a6d61747269782e6f726715737570706f7274406b7573616d6178692e636f6d00000a406b7573616d617869000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e238672304420f9c80539b93608621c583bed3c25caa9b9862d27ad2d5c36e40a00986b92a5747e": "0x00000000000000000000000000000000000e41746f6d6963546967726573730000001861746f6d696374696772657373407961686f6f2e636f6d00000f4041746f6d696354696772657373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e25f5c22e4254863073c378b0833da59cda1d49d711f37c9ae20ed30dc3dbb842ead63dde578331": "0x040400000002000000000000000000000000000000000a4359424552574156450000001a637962657277617665304070726f746f6e6d61696c2e636f6d00000d404379626572776176653134000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e2b059303130f519ad0a56ae39a6237f9eb5c1929d8cb87ecdcc6a31b053e1a37b06d3bfb885943": "0x00000000000000000000000000000000000c4b7573616d61205061706900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e38d1015309414f0ce9186972074fee3e851ea1c8b6d97a0a4fd631a98be1996b14448936bd8e36": "0x000000000000000000000000000000000005594e6f74000000177768796e6f747265636f726440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e3a90dd26f050973a8c8c37aeeed30fcb32ee7e4ddeb5e633eaa8f2c0c46a64ba5864f63a0c3970": "0x00000000000000000000000000000000000d4d61676963204672616e6b79001d68747470733a2f2f33347a672e73686f72742e67792f43686f726473001a6672616e6b792e757262616e696b6140676d61696c2e636f6d00000d404d616769634672616e6b79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e5d6dae2517ec4656a5e2491de262ad111c767a3ef398f0b19b6fb4ec7794af4939231abeca073f": "0x000000000000000000000000000000000005576562330557656233000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e647d848a1c0e61baae5cc25103ed6b8f136972b3582f23e0e524783c6da4357becaf258a6c837c": "0x0000000000000000000000000000000000094173636f6c646678000000136173636f6c64667840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e76a25c3b19eea73e9ff161410bcc8358a7016fcb249cf8e841a5b8d4417db5e1e578efc8e45522": "0x00000000000000000000000000000000000a53494c56412e4d415200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145e83c43ea150b4deaee71703931ed8f0437b28ca920a0054c723c9c3e099e6822f58ca0f5620325f": "0x0000000000000000000000000000000000154d6173686f7665727365203420556b7261696e650b4d6173686f76657273651d7777772e6d6173686f76657273652e636f6d2f342d756b7261696e65000000000c406d6173686f7665727365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ead7e317a7b15bc802c869bef7c9ee9696b34b72df675e6d2c0767f1ee15cf38f396a8a06099f70": "0x0000000000000000000000000000000000064d4152494f000000196d6172696f70696e6f4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145eb64e243ca273fba80c7347e64d19e137abd5258ae78a835ed01d65787a2f4aea106e8122254577": "0x00000000000000000000000000000000000c5452455f4e46545f4152540454726500000000000d407472655f6e66745f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ec8ab4f526b5c792c227f6cb71a18ace22f7e126b230d765c53bb168753b3d33f12582baea65658": "0x040000000002000000000000000000000000000000000c4465657054686f756768740000000000000a407761726d616e6a6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ed5968b3088d1332e1f318e20b782989f8d4f0db439d9d5a29bf0d52552f5c7941292213d16b315": "0x0000000000000000000000000000000000054840736100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ed84a25925e6b15cef26871166ae1372e4e1b7c59cc227a75ba9e857548a063f3d9ae602710674c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ee8405cff42241194339db8b404ea216d60433f00ed67b0cdcd9e29d21355615d967161db0cb04c": "0x040000000002000000000000000000000000000000001f5354414b454e4f4445207c2056414c494441544f5220414c4c49414e4345000016407374616b656e6f64653a6d61747269782e6f72671b6a696d6d7974756465736b69407374616b656e6f64652e64657600000c407374616b656e6f64655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f0d8890ee3f281f94237cdf8ab6530170cf7256c211e15b3a53100bd495cd668bbe4de875741450": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32380f42696e616e63655f6b736d5f3238000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f151dc76721212cf68991c22752cfedfc52627d3fea5b6e138260c09a7bd3941a9bc27b0379dc72": "0x00000000000000000000000000000000000a7761666120736162650573616265000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f188f90ed9c0ccc0e2cf389e3f53bc3ab0777b1678b1fa13b9c6a8e428695928275ba1cc029bf7a": "0x00000000000000000000000000000000000c4976616e2052204d6174680000000000000b406d6174685f6976616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f1b8b6e45fb190ccca9cb5657907dcb0bb01d335b17564e77994536edd05ddd50524a9355c2221e": "0x040400000002000000000000000000000000000000000b5072696d61204c616273000000167269656765726a6179333840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f3e0959896bb537d25b05b9887ec97dc7b078d84d04a619575bbc450478c6d97d0772aba1865b77": "0x000000000000000000000000000000000009584361737469656c01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f3f48a63730ca8508a514f13e955ec5401a19e0b64d325cb87a4ff62e50416ef73a834c99493b2a": "0x000000000000000000000000000000000009446f7473616d61780000000000000a40446f7473616d6178000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f4d5cce600e2badf85068f05bb04fc1d830745102b649680d7dd589524792942e24232ddbcff40d": "0x040000000002000000000000000000000000000000000b4541524e535441534832001668747470733a2f2f6561726e73746173682e636f6d001367726f77406561726e73746173682e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f5c79ebd9a8464fb49d5777c5b6aebd9aa9a597ec5cc2e160c9657dfb261ef76752ff7b51781a16": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f656b807ac9334d44d80863e2464a745a3eaa65cb6a7a336d86bd0390f75981c8e4735038a2d974": "0x0000000000000000000000000000000000074372696d656100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f690a20b95f47ba3e892614b6c645f4f0d3d757b5300777b6d6730f024a8181925e9cd56376c86a": "0x000000000000000000000000000000000008476176486f6f6408476176486f6f6401010100000b406761766f66686f6f64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f79e21c0cc427bbac2b14d62dc0c216e459037f76d0dc6f788f48976db1357ed97bf2dbf48a991e": "0x0000000000000000000000000000000000104d6f6465726e2e4d616e64616c61731343616d65726f6e20452e20476572686f6c641f68747470733a2f2f7777772e63616d65726f6e676572686f6c642e636f6d011343616d65726f6e406365676172742e636f6d000011404d6f6465726e5f4d616e64616c6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145f86b540db6a05d1d635393a4855e718ea723244ecd115bfbf129fd71e44384f107bcc6905069f7b": "0x00000000000000000000000000000000000574616c6a07496b61726173000f494b4152415320564142414c41531450686f746f74616c6a40676d61696c2e636f6d0000074074616c6a33000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145fb6a4114e90fbedc87dd7c321ad3dca39e53d05541bf9d17306d681ab556029b0f172156e12b603": "0x0400000000020000000000000000000000000000000009636172676f6b736d00001740636172676f6c6576696e3a6d61747269782e6f726715636172676f6c6576696e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145fb8bcd13578776d68fc7e1c641c663f8507e074bc989b520ec2c33b0733bd377ff67ccea372a035": "0x0000000000000000000000000000000000084a43727970746f0000000000000c404a43727970746f474d49000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145fbfaa2a1a2510a7525c7a721c51b453cd55ceba8c86d183b45cdeb531c582159f21a05bb1122270": "0x00000000000000000000000000000000000f7370656e63657220766f74696e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145fe706d242d60b74f2fe5db865ff1f5e647cdacecea78d89979dc8b00c22d10cf52692937e948c28": "0x0000000000000000000000000000000000134d697363686965766f75732052616e6765720000001c6d697363686965766f75736d61726b657440676d61696c2e636f6d000011406d697363686965766f75736d726b74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145fe9709101b5cdf4e4d04514ed98bdef66d61cb7d50504a675095499e3a08b6f70e55e136af1654d": "0x000000000000000000000000000000000008424f524f42494c0b4a4f4e20414e444f4e49010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047145ff08099f8e90061ba99d08e1e0ba1738bd68e07bcfdea7f486400921abd04b9e1dd1ee6b8cea322": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714601c869e08b51af7b04b58ffedd058a81a625819d437d7a35485c63cfac9fc9f0907c16b3e3e9d6c": "0x00000000000000000000000000000000000930784b68656f70730000000000000e404b68656f707343727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146023f967e8019e7b344cb1cfad3f1924dfc180169cb9bded8af74e5f457f6528272093398f46fe62": "0x00000000000000000000000000000000000d4361745f4361746f77736b6912456b61746572696e612053686972696e6100001463616465747377617940676d61696c2e636f6d00000e406361745f6361746f77736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714603d476d63191d24744b0a7d18985d2a3527d9d2498822644667f042af46231f51eee5bdbbf2b75d": "0x0000000000000000000000000000000000096d617276654c6574001d68747470733a2f2f706f7274616c2e61737461722e6e6574776f726b000000000c4072756461797275646179000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146041d27bd4e9040932abc1ad7749a511ed7b24f535f0908561cd2f8d550e7f9689ddcf285bfcc845": "0x00000000000000000000000000000000000c54686520466f756e64657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146046b114806eb5a2b4dc5c71e24bd3c05768294b875060b54e8b7663ae9658eec8b9f99568bb6e60": "0x00000000000000000000000000000000001341727420696e206d7920756e6976657273651341727420696e206d7920756e69766572736500001361696d756e66747340676d61696c2e636f6d0000094041696d754e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714604a48dc92e39be9fa9d24f035ebf90c61da552b2317dd1703f5a216e4b02786af26f8b41f211e35": "0x00000000000000000000000000000000001043727970746f53706163654d616e58010101010000114043727970746f53706163654d616e58000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714604c2e1bdbd6e3e66aac0cfe2a889556f28599f18da991a0a352b26f3d59c81961385eaf6f037c3b": "0x00000000000000000000000000000000000b417274486175734e465401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460672f43cee923df4a4c04c002c7c58fd79b886d649cc5ed9367d5c1ec17e8946fafeadd9f17067c": "0x0000000000000000000000000000000000054b617465054b6174651b68747470733a2f2f6c696e6b74722e65652f626f6c696b617465000000000a40626f6c696b617465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146067f41bd57795d6945e90a1afc83f0c74a3ffe96b40c4ebb5397af04126bc2db23036c043be4a63": "0x04010000000200000000000000000000000000000000134361706974616c5374616b696e672e636f6d001b68747470733a2f2f6361706974616c7374616b696e672e636f6d1c406361706974616c5f7374616b696e673a6d61747269782e6f72671b737570706f7274406361706974616c7374616b696e672e636f6d000010404361706974616c5374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460707c14d6e8780e128e3b8a2d3b98071ba399c17206f84350e65653537dbbd646cb5908efff9d49": "0x040000000002000000000000000000000000000000000f5a6564617a69204361706974616c001368747470733a2f2f7a6564617a692e636f6d13407a6564617a693a6d61747269782e6f726713636f6e74616374407a6564617a692e636f6d00000f407a6564617a696361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714607fa85c571cb935f0dbc94eb3d3fde9a2fa187c0ed37d158bdcbd48374ecc306373f222e19a860b": "0x000000000000000000000000000000000008465249454e445311636f736d696320706f72747261697473000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460b67be86271e2f36e99996cc6c41e39696f7c3bc4248e548473b68fe2ba26567771be07b7eb5b19": "0x00000000000000000000000000000000000a43415354414b494e470101011963617374616b696e674070726f746f6e6d61696c2e636f6d00000e40436173745f466f726b4e6174000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460b684ec999e7b776c064ffd60471f3c2adf674a02e6ea11ce28f1981dca3394b86062f94aec3112": "0x00000000000000000000000000000000001242494c4c494f4e414952452020f093858201010121626974636f696e2e62696c6c696f6e6169726537383640676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460c583d95c1213880a72a8935ecfe766b95282b1902fb185171bb302d78bbc27dc5c89c25ef6c37d": "0x0000000000000000000000000000000000094e61726973657469000000196368616e752e6e6172697365746940676d61696c2e636f6d00000f404368616e753436313836313331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471460cdf0b66deac356a06c780ffc2b9de1aae95dbcc7571e99639a5bd0a4646a9ccee387964be8837f": "0x00000000000000000000000000000000000a6f7a63616e20646f740c62696e616e6365206b736d000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146114e2b6ec2830667a196ebccf96edb47307cda78135c6b89259a9f4a747320a379c6fd81127b367": "0x0000000000000000000000000000000000034d4a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714612039a711b36f21e810732f068b79d01edcc9aed808c3bf25efa395f8dd89ecf8f282cbebe3092d": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f343600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146138eb274d27f0c5a4ce39d360532d50a6c69d07829c49cd7e6578a426f2e99f2b09cdd287cb9805": "0x0000000000000000000000000000000000137a62632d776f726b65724f70657261746f7213e4b8ade69cace881aae5b7a5e4bd9ce5aea40000113439303539333632374071712e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714613da82c3ef33267be14004eaae54231bada9111a86e3fa2fec1e94229b2d716bc90311cd75f1a65": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34350f62696e616e63655f6b736d5f3435000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146159604e6072a968e4f7e1546f461407d77e0147cfd55b204c151c6f6f5c3d121d93619bb208e576": "0x04040000000200000000000000000000000000000000096364626169626169000000136a69616e69406c6974656e7472792e636f6d00000a404364626169626169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146162ae27b1f4959cd2658699891fdc5afeea90415ba58333034b6e831e5c9f14c5a72a1abf10bc7d": "0x040000000002000000000000000000000000000000000c44656e697320476f6d657a00001a4064656e6973676f6d657a2e686e3a6d61747269782e6f72671c64656e69732e676f6d657a31373139393740676d61696c2e636f6d00000e4044656e6973676f6d657a3937000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146163414a2df709441a5eac9a90f7102af1e06c3c94890e49e1fddad6086afe119f3477a34a098255": "0x00000000000000000000000000000000000c6b7573616d61206c616273000000166b7573616d612e6c61627340676d61696c2e636f6d00000c406b7573616d615f6c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714617838b6d37dd7945ef462a72d35939b5584e9a29b33af86b356ce709bf022029f075991de1cdc4c": "0x00000000000000000000000000000000000944414f20495043490944414f20495043491168747470733a2f2f697063692e696f2f000d696e666f40697063692e696f00000a4064616f5f69706369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714617d0fda1940698d00834960bbbc5d62f484f8dac939fed0d34781de56ca24596cd29728962d1f17": "0x04010000000200000000000000000000000000000000044253441342617264757220536f6e6e692044696d6f6e0000126d7264696d6f6e407072697661742e646b0000114044696d6f6e536f6e6e693431303730000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471461811f3dd86470107a377b96be092a5ef4e78cba0b9d33be2206d0ab6d31ebf6b9026f9bdbb84f51": "0x00000000000000000000000000000000000745626c616e630101011d6361737065727363686e61757a65722e313740676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714618fd93a58f35389e2680e2c991a18cf7ba4710a51ba147b6856879a3047a03f8c647c69b953d630": "0x040300000002000000000000000000000000000000000751696e77656e0751696e77656e00184071696e77656e3a776562332e666f756e646174696f6e1771696e77656e40776562332e666f756e646174696f6e00000d4051696e77656e5f57616e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714619bd5898686aa365c4c4cb973301ccba822fd2d525c9ada03e8ded3a3c396e4bbf0e2107101e558": "0x04000000000200000000000000000000000000000000074c75646d696c000000146c7564646f6236373140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471461be688e5e7a221af444917451425779e3e5d876f510ff63599e80cefd31b596fd03d2a0fdf8a658": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471461ec8191fc5989284252e6ae566173032638ceba452106c90dd62a83b9f56f32d87a8a5cf7156a7c": "0x0401000000020000000000000000000000000000000014f09f8c9f20616c6578616e64726120f09f8c9f001c68747470733a2f2f616c6578616e64726168656c6c65722e636f6d0019616c657840616c6578616e64726168656c6c65722e636f6d00000b40616c7868656c6c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471461f27b90121cc03394243fe719e35099e11473b7e357af29ba960e0c0dc92ec37a04278e2760df1f": "0x00000000000000000000000000000000000b57616e67646f6f646c650450617400000000000f4077616e67646f6f646c65746677000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146202f221c7d24475766f18a6eba78487bc0e570108e8c80d864be67c5bb6f8242420c0f43c955c1c": "0x040000000002000000000000000000000000000000000f43726561646f72657320576562330000001863726561646f7265737765623340676d61696c2e636f6d00000f4063726561646f72657377656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714620f714edca8297ae21e94b7c05630c70ab2867d6f30ec737042ed4525baf9b920b8df5b3161aa2c": "0x00000000000000000000000000000000000b4a75616e204541476c650000000000000e4077336e6a75616e6561676c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146244e474aa91e041ae9749dfdee466ed67835efa51f04d74db27d75e919d7050e4f5b7f481f77a14": "0x0400000000020000000000000000000000000000000006535052494e00000019646f7473616d61646f626c616a6540676d61696c2e636f6d00000b40736172615f74726d73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146269f1c102c0bcd962088931a549261141670f3076ea53eb7fb0af2d5717fefbca6d16ca48eeca32": "0x040000000002000000000000000000000000000000000751756f72756d0000164071756f72756d6c6c633a6d61747269782e6f72671971756f72756d6c6c634070726f746f6e6d61696c2e636f6d00000b404c6c6351756f72756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714628acd4748784be3a2da2913d7db19baf0a41dc40a73d75bc6001ce1691c3ded78e4e86387881b4c": "0x040100000002000000000000000000000000000000000b43686f727573204f6e65000000126b7573616d614063686f7275732e6f6e65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714628be056de9c8868da02ca3758e9d65bfa5ad00f3a258996a96f49323635e11866ec4d8924b8e316": "0x00000000000000000000000000000000000b53706972616c7761766513436573617220416c6265726469204469617a00001673706972616c776176653740676d61696c2e636f6d00000d4073706972616c7761766537000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714629a4d1544110b26a8f85ce44267618f170518db7da6321a685e61838d3efde0d62d46a10ea16b20": "0x00000000000000000000000000000000000a4a756e7175656972610000000000000e406d7970726563696f75736678000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471462c58c7418228d6852310e6542cccdcab43d1104aa442792b3198b67913966b339ae8303b7b8f010": "0x040000000002000000000000000000000000000000000c444f545f4b534d5f53544b00001640646f746b736d73746b3a6d61747269782e6f726714646f746b736d73746b40676d61696c2e636f6d00000b40446f744b736d53746b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471462c6144c430228802e62b548856a9ff975d160a0df8219bd36a7807620ac1ae2eeeb34498ba3e470": "0x040000000002000000000000000000000000000000001064656967656e76656b746f722e696f0000194064656967656e76656b746f723a6d61747269782e6f726715696e666f4064656967656e76656b746f722e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471462dbdca0ca2af18f4c440cddf43c86794b066df57248545bbfd487ca4bb653f97efca73d1c4c1949": "0x0000000000000000000000000000000000065365646c6f00000000000011405374657070696e5f52617a6f723737000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471462e240b15fe5fc9d40750e87a8eeb07ffb982670415979c0b6b8c33c27aa81c621b5c96df3148520": "0x000000000000000000000000000000000004524b4f08524b4f204152541f68747470733a2f2f6c696e6b74722e65652f486f757373656d3133524b4f000000000f40486f757373656d416c6c616731000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463168c77524eff6872b83296f11b567d5dcfae7f23e88b1d4c33216002a6bb6a3892a801d4ca4c0f": "0x0400000000020000000000000000000000000000000013436861696e53616665204964656e7469747900000012696e666f40636861696e736166652e696f00000d40636861696e736166657468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463182e6ca878bb873e459ba69f3cfc7148ceb115a6be76c18bd69773eeeb6b5bd5240d3233ec0014": "0x0000000000000000000000000000000000104d69636861656c20446f75676c61730000001a6d69636861656c2e646f75676c617340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714633914b3a4ceda021eb38b0d5178bc680c10a204f81164946a25078c6d3b5f6813cef61c3aef4843": "0x040000000002000000000000000000000000000000000e416c69636520756e6420426f6200001a40616c6963655f756e645f626f623a6d61747269782e6f72670000000f40616c6963655f756e645f626f62000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714633b64caf2f93c5bd8856a8b804829eee642bf2b6b516e28958926179cf089338f2ea81a64470152": "0x00000000000000000000000000000000000b6d6f66666f5f6a6f6a6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463415cea64dd2404ac41d6bb0835464e8428f9393e3edd73b74aad6d978a9870ecf4e7eed1ed8c0d": "0x040000000002000000000000000000000000000000000f68656c69787374726565742e696f00001b4068656c69787374726565742e696f3a6d61747269782e6f726713746f6d4068656c69787374726565742e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463469200c98418da9e91c0029b5a22ff3799a39634f2cf1e89060f4acd5ab2855a4b91fae1150a3e": "0x040000000002000000000000000000000000000000000a506f7765724c61627300001640706f7765726c6162733a6d61747269782e6f7267146d696e7a756b76696b40676d61696c2e636f6d00000940564d696e7a756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146354c3c5f32f80e56ce8f0f322c021ca4991c83240d0feb94ad1678835b51d228999252bf9223e49": "0x0401000000020000000000000000000000000000000020f09f90b05f2e2de3809020435259505449445320e38091202d2e5ff09f90b0001668747470733a2f2f63727970746964732e6c696665154063727970746964733a6d61747269782e6f72671468656c6c6f4063727970746964732e6c69666500000b40637279707469647338000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714638103b9b7fd6d8154902ac86eb3bc2e1ecf30533e2d9f1f1b034ac0dd35ff41f44da47384646169": "0x040000000002000000000000000000000000000000000669616d7a73037a73000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146386fd585f1ea07542a041a8ffd0a0de1d7a09e1de1635a8fec8d94f3410ad806111ecc9e456a14d": "0x0000000000000000000000000000000000094d6f736772656174094d6f7367726561740000166f6c756d6f73733230313940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714639f42b914578e805412791fff5f735f273124674635bdae68a09229b99bc0bbd1ae0edbe83a9b05": "0x0000000000000000000000000000000000074e5f4c6f6b6913456c697a617665746120536f6b6f6c6f76611868747470733a2f2f696e6c6e6b2e72752f414b644576770018617274656c697a61766574617340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463ac3c1368e584e17277877d44db05f92e11933c218cb6a0521f24896c2406e5aa60fefb204cd72a": "0x0000000000000000000000000000000000114c616c6f204d61696e204b7573616d611c4564756172646f204a617669657220476172636961204c6f70657a00001b6564756172646f2e6c616c6f3139393940676d61696c2e636f6d000010404c616c6f313939394a6176696572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463c5b9775db401c68e303bd9a1d343eb4a0b4bde59e42981bfcf6e0013b87835529233cbacb63e2d": "0x0000000000000000000000000000000000094a61636b6e46696e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463d7ad13e4a5e5d66c7794b3f35a9636f38ce0e7fbc035b445f7d8cb19d2eb1c4deee97ca8e3dd6f": "0x00000000000000000000000000000000000d6b7573616d612070756e6b73046b73701968747470733a2f2f6b7573616d6170756e6b732e636f6d2f011a6b7573616d6170756e6b7368656c7040676d61696c2e636f6d00000d406b7573616d6170756e6b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463d8eec7a22e3fe26f3913b4f1a51729f61ec915230c7de2a7d577e4da9034d02e3d047a9498cddb": "0x00000000000000000000000000000000000f4b41424f4348412050415241494400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463e692f33df6177fccbd7176021b4da713cb1d0acfcd28fdd2ed0657f34d7341e055160e67a5ce64": "0x00000000000000000000000000000000000a796573626f72796573056f67757a00000000000b40796573626f72796573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463e7faa7d3930e42c443fd5caf9808af1b7a5586e7717f4f85ef6d4762d0ed1aa98edb83577e957b": "0x00000000000000000000000000000000001041727420556e73746f707061626c650000001f6172742e756e73746f707061626c654070726f746f6e6d61696c2e636f6d00001040417274556e73746f707061626c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463e8632182788bd60a439f839504ef07c5cf8daf62beb17546e808ed1026c8a683be8207245f300f": "0x0400000000020000000000000000000000000000000018556e69746564205374616b6573206f66204b7573616d610000001c756e697465647374616b65734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463ebead6dee4cc021cb5747641960389b41372ddf6c5eb13b7aca0e06193dc732c9975c2feacae3b": "0x000000000000000000000000000000000008546865204f6e6501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463f0045ef18b9c5c9468b8cad284058b157ef324f85ab25a84e890efc6d08b1068df790d06387953": "0x00000000000000000000000000000000000101010101000009406d657663686562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463f0f91780f2ce733674264b4be5fccb6e5b960a8259e2920a7d5a85774560360b76c2e219983d78": "0x00000000000000000000000000000000000944656c6f7344414f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463f4f567548c9f8c2843d91b23b106e3020b7a903da075113d1aaca1db7ac30e119d6250fb6f5961": "0x040100000002000000000000000000000000000000000b48595045525350454544000012406c6f6b616c3a6d61747269782e6f7267146c6f6b616c40687970657273706565642e6175000009406c6f6b616c7070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471463fce0f80bcc10c07006f88b83702ddc8509429bb2d29e8b0e538aa42f01b495f269f358beae5635": "0x00000000000000000000000000000000000853616d7361726100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714640c0a62703f8c354ae4661aa6417a9200e77acc80beaf8222c4d6c43318e9ce44bb4827ba401a24": "0x0000000000000000000000000000000000074e61696b656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464127eaeb41ddf9d8e73597eb622ce0a2ea8c15674502d2099bbc62cc9251269d31bd1fc0a56bf7f": "0x000000000000000000000000000000000007436f6361736f0000000000000c40436f6361736f73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146419f57ea3f84915121b12be1a2b918b9d01ff05c3d2fe5a28769cb747ff9fd7ecafc320dd5f810b": "0x000000000000000000000000000000000010446f74204c65617020456469746f720e4272756e6f20c5a06b766f72631f68747470733a2f2f6e6577736c65747465722e646f746c6561702e636f6d0113656469746f7240646f746c6561702e636f6d00000a4062697466616c6c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714641ab77a8f62130ee4b0ce3fdd2e23b0be2314a084becb2f782302768fd25900e51b241c6a8b8b2d": "0x00000000000000000000000000000000000b506c617a6d617469636b104d61726b6f204d6968616c696e6563127777772e706c617a6d617469636b2e696f00176d61726b6f406d6968616c696e65632e73747564696f000010404d61726b6f4d6968616c696e6563000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714641f551ea31b85752a6cfd49c515150a2daf15df3dd7e94d3bbdbad7a2f2c47651b1cf12fc0b0a44": "0x0000000000000000000000000000000000076a6f686e647912416e647265204d75736573616d62696c6901010100000e40414d75736573616d62696c69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464212dfe8be1489d70ab4d54ff22e17eacd7d1a393811b4c555f60803c068e64470d74d55ed2223d": "0x00000000000000000000000000000000000a414e4f4e594d4f555301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146436bbd870b62a0a0475fa54014587f4211cf4bb360489a63b4e0d7c4dd03e2cca08bbc5adfb9f57": "0x0000000000000000000000000000000000064a6f72696b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146451faf4c30c21127c329830176364028bd694be68b8e62b1cc3508a6779889926b6cc2a22d8d574": "0x00000000000000000000000000000000000a486173685370696b650000001a686173682e7370696b654070726f746f6e6d61696c2e636f6d00000b40486173685370696b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714645a2111e24537a2c088a8a35f9a31008c7ac0d4103078bb14b3d50213e4b92bf03ea98c081f173c": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464680adbdec0e1af3e2256acd251ae7db0c356b5b5aa4d67adbf25281d9d074d364d57398a60b31b": "0x0401000000020000000000000000000000000000000009457667656e526164001b68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b1540657667656e7261643a6d61747269782e6f726716657240726f626f6e6f6d6963732e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714646ace64bb54bf1ca6b6d86d75692bc3d6f3c2c9b83173ce3b9e5e738adc16009c5d4a0d80e36c31": "0x000000000000000000000000000000000006517561647300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146478c35322287a2a38bc40bd7bb3dc77516be2d9fd9c02168506073728317baafe272267873ce80b": "0x00000000000000000000000000000000000d4d6574616d6f72666f7a7a7a00000000000010404d69737465725f4368657272797a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146480d6c21997bbbbd278adfb237acd334f2939c917a94a5acdd972ed468a743e7c562a6f1bf6ba27": "0x00000000000000000000000000000000000476764b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464850ed977f64df0a49a4bc7683f6ffd027b75a783f6c5b182a633a22cc0605ba0abd470de9def5b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464acb2a5e7697e7428778f95bd35e3fec4ee72a0d252c47097380c3ffdf93a9600b364ea119c0502": "0x0400000000020000000000000000000000000000000012524d524b2e617070206f6666696369616c001168747470733a2f2f726d726b2e61707017406272756e6f3a776562332e666f756e646174696f6e0f68656c6c6f40726d726b2e61707000000940726d726b617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464b2511e92b6677ab1e8b074b1c82002a33e63338a04b974107769099111637275514fb0cd740978": "0x0400000000020000000000000000000000000000000017536e6f776272696467652042656e656669636961727900001d40776861747265676473666f64726a6b673a6d61747269782e6f726713616964616e40736e6f77666f726b2e636f6d00000e40736e6f77666f726b5f696e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464b6eda43f595223dcbb7ca8b988aa2a9771a34d8ddde1bdddc4177d021a87a2e6559b58a4252d57": "0x0000000000000000000000000000000000064d6174745800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464bcffa5a054b3fbf06b28b48291aaf2818a2bf2276ef4bfb2702c9b1a651b58c8bd45c91d926d3d": "0x0000000000000000000000000000000000114d61726c75612047616c6c6572696573000000000000104054686547616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464c69542e90ec9f70223f0fec2f4aa58a1666aad88ff105170d3cbc67343f17070fa95047d0aac0a": "0x0000000000000000000000000000000000044e6174084e6174616c69610000126e67726f6d6f76616140756b722e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464f0f0b4da5c0746d0354e9fe5a5be336577b8759695e5c13dd9e07bd2bea414f2a47b88c2cca867": "0x0000000000000000000000000000000000044e656f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471464fffce989e2fabc6a0051ef580a2b9dd19a368b82ec20f9a605b0207f2e8d364e6c985b5b2ba871": "0x04000000000200000000000000000000000000000000064d49444153000014406d6964617338393a6d61747269782e6f7267156d69646173676f64383940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714651097b4998394e146d1b7fd733a68d1c3e53d6bfd7134a5803fe5a4033c2dc9eba2e31dc21c4a65": "0x0000000000000000000000000000000000076272656e7a69000013406272656e7a693a6d61747269782e6f726700000009406272656e7a6935076272656e7a690000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714651f9baac64c847fb004ba829fae5aec26aaa3aef02d67856a32c161d3d50807a17338bc06592a74": "0x0000000000000000000000000000000000056b736d6300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146522b168b23b5549d8e1ead6bf0091994d15f0df75afd35759da29eba0512ce3913b668fc656a229": "0x000000000000000000000000000000000007457572656b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714652d11d1e91fe674e0588915142c9ed7cad4b2abeb48263fca36403643561fb0929da1949c983160": "0x00000000000000000000000000000000000c4d6f6a6f2053747564696f0c4d6f6a6f2053747564696f00000000000f404d6f6a6f53747564696f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714653cf62e15004fa7a68f012e4e382e5eb35895b62f3184be8aa381109bd6a270d661c05ee8565930": "0x0000000000000000000000000000000000086d61657374726f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714654cf21a2fd00f055e520486d48edd5e6f31158b9960a0673503235c10135a57c147389815412162": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146553c10b93169dc66e8a3622a7355ab70892bc48236c461076d5163f55309b7e5d0a459d17c6272a": "0x040000000002000000000000000000000000000000000d57696e746572737072696e670000194077696e746572737072696e673a6d61747269782e6f72671477696e7465726b736d4070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714655dfea04bf9ae01f8b3e568239aaf85034f6f4a28e4d6b90a57ecf04de0005531f141d849aea160": "0x00000000000000000000000000000000000b417374726f4d6164647900000017617374726f6d61646479313040676d61696c2e636f6d00000c40417374726f4d61646479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714657b24569b4318acd6e71489d5d3479fb29f2f7cf4b3a9534f72de76d0d76880066362330f818c09": "0x000000000000000000000000000000000008444172746973740a5065696e2057616e6700000f777065696e406c6976652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714657f579f3442148eea0ab1b08b58a3708b50ba9928c4e25ad71d68efcbb868a2f75b987d0e8e4108": "0x00000000000000000000000000000000000a575252696368746572000016407772726963687465723a6d61747269782e6f7267000000114063617473776974686f757468617473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714659226a0e9136adf1010b8a9bac58b959a3b92e0ff6a1a2946d36a543b8f8d34a70f231c91f73313": "0x0400000000020000000000000000000000000000000010426c6f636b20416e64205768697465000018406372697374695f616e5f6d3a6d61747269782e6f726715736f6d6574696d65737340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146595beebc30abfa94e56d4889d3aed021503759b7a8428959648af042d123e2a8f495179ee7abc53": "0x00000000000000000000000000000000000e456e72697175652040524d524b00000011456e726971756540726d726b2e61707000000d40416c706861697264726f70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146598a12412759f6926f23bd836ee246363cf6151d26b5d323c077e5d73697de6ea099d1e8368b937": "0x000000000000000000000000000000000007e5b9b3e5928c0000000000000e405a6544617343727970746f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714659cef47a15bd68424401b30707f2ef5ffbcf62a082f989655d8d542f4b49f2d0cef0e4bf622bc6b": "0x00000000000000000000000000000000000c43727970746f57696e6773001768747470733a2f2f63727970746f77696e67732e696f00000000104043727970746f57696e67734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471465b47ab9f3aec5ec06e3ed1e088da56a1e7ea6b57a856a0ead9e03bfbbd1ec74b33153e35015f10a": "0x000000000000000000000000000000000008546f6d69747a7500001440746f6d69747a753a6d61747269782e6f726712746f6d69747a754070726f746f6e2e6d6500000940546f6d69747a750008746f6d69747a7500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471465bc13bbec192777643ccd0e9c3470bced3320d37d632da5fa7a7f13eda60bb6ca83ccb2ba0f495e": "0x000000000000000000000000000000000006504c55544f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471465c283803e3c51bba2c30b2305139eb8d015e3eef8b71accde489c01030153ee2599a5de59dfe869": "0x0000000000000000000000000000000000155449515549205449515549204d494155f09f98bc00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471465f501be466f9b4b4c476e3612a313e1ce03f27e26affdf86137396fd1d38fee5b8902c9f0892870": "0x00000000000000000000000000000000000e4d75726174204174696d746179064d757261741c68747470733a2f2f6c696e6b74722e65652f6174696d74616b757300126174696d74617940676d61696c2e636f6d000009406174696d746179000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471465f65e549ed519ab389ab756df0ac71f85739a5ad44971dcd1f0afaf783daa1007cf3589c94fc1f3": "0x00000000000000000000000000000000000a436861742d436861740000000000000d404368616261737469656e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146644353ed65ec6a1589ad5b4e32f5317c485258bad05fab5a0d716971f7832fb565d6037ef4be95f": "0x000000000000000000000000000000000010556e636861696e6564204e696e6a61011c756e636861696e65646e696e6a612e737562737461636b2e636f6d010100001140756e636861696e65645f6e696e6a61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714664fe17c743b2df5d09338c5be5ef14c6d2e27a0ac9e65ce1167d13a79584cb684cd11a9b7f1b977": "0x08000000000201000000050000000000000000000000000000000006416c65785600000014616c6578676d696e6540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714665285c8d09dbb63b44cc7489f7ee065a888cb76ad104715a6a9ad5b0d2be070949985734fe32f39": "0x04010000000200000000000000000000000000000000196f726c6f77736b692e696f2076616c696461746f72202331104c756b61737a204f726c6f77736b6913687474703a2f2f6f726c6f77736b692e696f00136c756b61737a406f726c6f77736b692e696f00000c406f726c6f77736b696c70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146652dea770af814592374b554ae5a1ce10e87eaf0b25b26d3d2680fb9bd59b32e203ded3a2936471": "0x00000000000000000000000000000000000d4e465420426162616c61776f0000001d6d69636861656c2e616b696e6d656a692e6f40676d61696c2e636f6d00000e404e46545f426162616c61776f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146663c4bca0fcc63836af143c60658947d49e753293cc454dee77beead3b919ce47c3467a12f6266b": "0x00000000000000000000000000000000000a596f75646c6544414f0000000000000b40596f75646c6544414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714666400683ecf9c61ac94924e4f863b0d6b74957b1641de4cd23dd809276a9f8ae5dc32c5eefb2717": "0x00000000000000000000000000000000000b576176696e20476f6f640000000000000c40576176696e476f6f645f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714666ad47322da5d72a62b6efc3312fabe517bf8e1f407a00a676bf2112161ed1daeb0f5e784208b43": "0x00000000000000000000000000000000000973656f73657263680009776172702e777466000000000a4073656f7365726368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714666f15289c2f579fba6b7bb322f0a9aecd1faa52f835110cfb228107676c28771a2a024a2bbdbf53": "0x000000000000000000000000000000000003454400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146670b1e816a2cedaaa2b3e0a8702aebcb83d552838a17902b2403b0f16c4e52a4514fe02df532e3c": "0x040000000002000000000000000000000000000000001af09f8c9020646563656e747261444f542e636f6d20f09f8c90001868747470733a2f2f646563656e747261646f742e636f6d001661646d696e40646563656e747261646f742e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714668bbbac68a19cb7a02f7333e25590e4f568ae8a2ddc93a879e92e48fa3cf1666ac56e020c106d55": "0x040000000002000000000000000000000000000000000b436f696e53747564696f0000001a636f696e73747564696f4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714668ce779b7a9f3801e76b9da6373b204c3db21d2a7097a79afcf32f642a516980ae26c910e70a35c": "0x040000000002000000000000000000000000000000000a4b5553414d41424f5800001740616e746f6e696f626f783a6d61747269782e6f72671b616e746f6e69676c6962657274626f7840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146699d463bc3acb0176df0017195b220a733f294a1835837a8a8ec22d66deb8cacfcbeccaad77e748": "0x000000000000000000000000000000000005517565730000000000000a40717565736c6f7264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466a0ec80cc3122c082bf733f44a840f0a5c1935a002d4e541d81298fad6d1da8124073485983860e": "0x040000000002000000000000000000000000000000000b73616d20656c616d696e0000164073616d656c616d696e3a6d61747269782e6f72671273616d40696d6275652e6e6574776f726b00000b4073616d656c616d696e0a73616d656c616d696e0000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466a17448b8730ba3089e132a7e8fe6484138542c6e44a303d0e66750a9381730bb421a28cad7f033": "0x00000000000000000000000000000000000777616c6c657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466ab20bec2c8842b5c7a60ff74811eee72747ef1f1ae376eda2d3c8aab129f6c2cc76abaf59fb87c": "0x040000000002000000000000000000000000000000000a486563746f723c423e00001840686563746f7265737430363a6d61747269782e6f7267156862756c676172696e6940676d61696c2e636f6d00000d40686563746f726573743036000d486563746f7242233936313500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466b6b504ec5881431a57245f1409f422242aefe885d3b0c7227cfb00aa278c6b84e34a803c14eb7c": "0x040100000002000000000000000000000000000000000c415245434f4e542e70726f14417265636f6e742053657276696365204c4c431568747470733a2f2f617265636f6e742e70726f2f1840617265636f6e742e70726f3a6d61747269782e6f7267117765623340617265636f6e742e70726f00000d40617265636f6e745f70726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466c21eb278416a36b6217be75d0c62d8fe8d921563198f317fc92f65025cf3d1d1bf2cab9b7cf732": "0x000000000000000000000000000000000014504f4c4b41444f542e4a53202d20524f48414e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466d2ce8502374c4f9c4f65bbb181e89e5539eecf3cec64c02ff858973646fff1a72563e8fe81044c": "0x0000000000000000000000000000000000064469706c6f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466d850d0167dfb3ff429460ae52548e754c712a7cfc75f1bf7c9295da165293ca52ccc686db5c02d": "0x040000000002000000000000000000000000000000000a5354414b4550494c45001a68747470733a2f2f7777772e7374616b6570696c652e636f6d16407374616b6570696c653a6d61747269782e6f7267147374616b65407374616b6570696c652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471466f1abaccca5dc5ea22523537072ddf4b80dfeedc797c613e8c2452a7f82f810b6e30ebb7281843e": "0x00000000000000000000000000000000000942617274204b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714671d243feb29878cc23a09ccefbe0b2e0bd6ca9e44ea9f9f566180c324f0ee94d750493b2a90d364": "0x0000000000000000000000000000000000104469676974616c20466c6f7269737401010101000010406e6f6d616463727970746f677579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146736de782d724588d2777ebda943e55cb791aa8437709ef3bb53c3231bd91a75b835439dd6ef4663": "0x000000000000000000000000000000000009536572676579373500000019736572676579736f6c74616e303240676d61696c2e636f6d00001040736572676579736f6c74616e3032000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714673b3b4a1ad50d479c644791dc08755b8abe4530f04692c895f2a4a93ab128acc17fc4fc0808372c": "0x000000000000000000000000000000000007477575676c6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714675581c1eea085a9d8dba69752ffb04fa563b126a31b037c8bebeb73e3c66cacd7c8efab46bd3423": "0x040000000002000000000000000000000000000000000a70616e6472657339351d5061626c6f20416e6472c3a97320446f7261646f205375c3a172657a1868747470733a2f2f7061626c6f646f7261646f2e636f6d174070616e6472657339353a626c6f7175652e7465616d15686f6c61407061626c6f646f7261646f2e636f6d00000b4070616e647265733935000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467568de3317e474e9a64ad79179d3f9e018447fa67d8d05d92f0d82e4dc731d14e516ae10a25d924": "0x040100000002000000000000000000000000000000000e496d627565204e6574776f726b001b68747470733a2f2f7777772e696d6275652e6e6574776f726b2f0016636f6e7461637440696d6275652e6e6574776f726b00000e40496d6275654e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146775a976f24cb02358805bce812d39a03405e454ea71401dbc7be353f65686c4c6bb30e656c8b76e": "0x000000000000000000000000000000000009486f6e6579706f741054657373616c69652046656e64657200001974657373616c696566656e64657240676d61696c2e636f6d00001140626f6e676d61737465723132333435000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467baf0838d6b1b2ae02e07f40a4d21e0d5fa5ff929adf8b9bfeacaf06bd5987b2741522b01ba4a32": "0x000000000000000000000000000000000011446567656e206f6620446f7473616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467bcc2ca4091537b5c7125e83d4230d1818f811230994a118ac01ccb73ceb2146a8a3f443ed75241": "0x0000000000000000000000000000000000056b61746f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467d3e4a96a4337066e31ecbbe0f191c3a02509dec5145e1bf73c7ee1ef086904b36a8a3fc249e138": "0x00000000000000000000000000000000000c4a6f73686573756d6172650000001d69717569717565697175697175653230313940676d61696c2e636f6d00000d404a6f73686573756d617265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467f3ca507a532ccb2e1884c53071526483b14004e894415f02b55fc2e2aef8e1df8ccf7ce5bd5570": "0x00000000000000000000000000000000000970657079616b696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467f85c2c7218fd6c409c3164dee58108840f004e49ad5abcc680714ede7ea4a064986f268e396e43": "0x0401000000020000000000000000000000000000000007434855525255000000195468654368757272754070726f746f6e6d61696c2e636f6d00000b40546865436875727275000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467fc0f66fe815ab410383630258381dd93b530a4c73fedb24d04aebe8cc7cc6ba4f7e008eef32f47": "0x0000000000000000000000000000000000066961676e6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471467ff75c4bc963c22fa77d65110d751716c8236da48f45bec37350fb0b36b6dbb8cef029fcba86b00": "0x00000000000000000000000000000000000c716267406576726c6f6f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146811e36909dc3ca59e42ace67151e0f94d4fd29937698d7ed05d8b5e663dde63c9227b0a3ae9334b": "0x00000000000000000000000000000000000a456c6c7920456c6c7900000012656c776972757a40676d61696c2e636f6d00000940656c776972757a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468180e8198681ff7e0d744a6f291a2dc1e6d744d5ae0747e314b046739be170638ecc185ff4a9b5f": "0x040000000002000000000000000000000000000000001e624c64204e6f646573207c20f09f988e436861645374616b654b696e67001568747470733a2f2f626c646e6f6465732e6f72671340626c643735393a6d61747269782e6f726710676d40626c646e6f6465732e6f726700000a40624c644e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146819d27a5574bf9d52f1cc1b6904a99f88fe1a80a09959ec14bf0c4505cab1c13af31d107b817b22": "0x040100000002000000000000000000000000000000000a4269746368617267650f42697463686172676520496e632e1568747470733a2f2f6269746368617267652e636f001368656c6c6f406269746368617267652e636f00000e406269746368617267655f636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714682226526c5637c6f4e893116c799faec7c11176104e134077d0d1902ae545b9db21fd842a773362": "0x00000000000000000000000000000000000b4c75636163727970746f0000000000000e404e4654736172656d796a616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146823ed8df7d5f458c46ff658221e07564fde2764017590264f9dfced3538e283856c43e0ee456e51": "0x040000000002000000000000000000000000000000000f747572626f666c616b65732e696f001768747470733a2f2f747572626f666c616b65732e696f1840747572626f666c616b65733a6d61747269782e6f726717737570706f727440747572626f666c616b65732e696f00000d40747572626f666c616b6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714683a845d2e2728b9246469efac79c9f41621d250f07f19805a6596176d39826ce44253693ebd5b56": "0x0000000000000000000000000000000000084372656c6c657307546f6d61737a01010100001040546f6d61737a4a61726f737a3137000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146844ca75100b198bc4b1960de3e58b7b296b26befd8d2588871a3fdb9c58bc3240fb5fb279bc0712": "0x00000000000000000000000000000000000c6d617474616c6163686961054d6174740000186d61747473636f74746372756d40676d61696c2e636f6d00000f406d61747473636f74746372756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714684be26b14283aeb2821c06b6812ffe1a79be4b1374799e641b89dafdd961d79720c299827a05802": "0x00000000000000000000000000000000000c49636562657267536c696d00000000000011407472656675636b696e676d656e646f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714685887d42c2579e03839e4be40e252a56e2d7c8e89a0c8eb990df5910714fea61c6e1d3b1c4c5502": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714687a668789176ce3a262b69b9bfcc58a6707cd9d6d68e30f6815920b3df7016a0d0315b21a45901d": "0x0400000000020000000000000000000000000000000004474f4400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146887fb7291f50ec61ac3c67396f49987dfeb090be1ff560b8e00eaa42218093f3043e59a352e5005": "0x0000000000000000000000000000000000036d65066d65746f6f000012616c65786c6a6d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714689719bd3780b5a8d031f202a2d2aee29aa291ddea64d37b43c9120519e5508a6eeb8b61b232c553": "0x0000000000000000000000000000000000084465657044414f001368747470733a2f2f6465657064616f2e696f00106579616c406465657064616f2e696f00000c404465657044414f5f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714689a20d8714b51d538cadf9abf7492ce1df73d8b7ee82e10c2a0571970e2aa5ded4b9a6f91a49833": "0x040000000002000000000000000000000000000000000f55766f20746563686e6f6c6f67790000001255564f746563684070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714689d5109a8aed88944657c9cc1d0202b2a9508ae547b03bf833352be16facad780b19b179cbd554d": "0x00000000000000000000000000000000000d536e616b6520436861726d7a0000000000001140736e616b65636861726d7a4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468b195054093d962441ad818e57097e7d044b15fe0dcdf61742cf279444c5e8ffa9ae554ceb61c6f": "0x04000000000200000000000000000000000000000000037071000000127071686f73743540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468c9be061f3c16c170e0cdf5c21bdd68eaa9eafec9fd9fc0b6123251406f01de516a06cecdefe64c": "0x000000000000000000000000000000000012576562332e3020666f756e646174696f6e12576562332e3020666f756e646174696f6e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468da324624114433da47e564f57cad4eb817c1e7d2287012d5fe459992ae2997995bc03dc55f3256": "0x00000000000000000000000000000000001354686530726967696e616c47616e64616c660000001f7468332e30726967696e616c2e67616e64616c6640676d61696c2e636f6d0000114030726967696e616c47616e64616c66000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468ea576627e05a04fa0dcc186bc3f6b9fb943feca1bec230acda1bb80b3cb2f9d3ecc3e7d089241e": "0x00000000000000000000000000000000000b4d41442052414242495400207777772e696e7374616772616d2e636f6d2f6d722e6d61645f72616262697400186d6164726162626974323031384079616e6465782e727500000d406d726d6164726162626974000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471468ee2c2eedcec18516fc047d8cace5a7f17cc8605f1fa2de274ad27664a5ed7d6a33dd54e3dfe84d": "0x04000000000200000000000000000000000000000000104d494348495341524e49545a2049490000001a6d69636861656c2e7361726e69747a40676d61696c2e636f6d00000e406d696368697361726e69747a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714691af4f75a591a304e4593da91318df8bdb35d247accf2db96e12f1d1a7bcae43c047c13991ae924": "0x04020000000200000000000000000000000000000000105068616c614e6574776f726b2d30310016687474703a2f2f7068616c612e6e6574776f726b2f12237068616c613a6d61747269782e6f7267156d617276696e407068616c612e6e6574776f726b00000e405068616c614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469259d1259754a2ee8f80e4dd56979a1eb996faf0d02b804d4b8d3986687d1bb096ef61494881b73": "0x04010000000200000000000000000000000000000000084a6f686e6e7942000016406a6f686e6e796234323a6d61747269782e6f72671766696e6765726c696e6734324070726f746f6e2e6d6500000d406265726d616e5f6976616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469283fb3584b29920cf1d73c4b30f8f97080ad60115e05a5105025201dbad0e95e245c6d78f43805": "0x00000000000000000000000000000000001a5374616b65204361706974616c207c205374616b652044414f0e5374616b65204361706974616c1b68747470733a2f2f7777772e7374616b652e6361706974616c2f1440626e65696c756a3a6d61747269782e6f726716636f6e74616374407374616b652e6361706974616c00000e405374616b654361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146952ec1f162d715fd2f6e5569a0398b8af4ecb4283a1dbeb06a94a1c093b8d2b8532b5944079291e": "0x040000000002000000000000000000000000000000000a736d696c656368656b00000016616c657878786b6c696d3640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469546ab63701f3cde46a9306739edfedb7505df5e98e1212ba27f17dd964e4607da678379984206c": "0x0000000000000000000000000000000000056230726701010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714695b23e099c12086505eb7820f60d0949697617b2f3366bd616d8c7e96724aa681e0113f6bf45c46": "0x040000000002000000000000000000000000000000000676616c6b610000174076616c6b613a6661697279647573742e7370616365000000094064617461666f67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714695dc1e151a40b7a60ed744aac415baf7621e0335ec5046c8edbaa6c164cb4134a1d7879ef5c0a40": "0x04000000000200000000000000000000000000000000094d6972736c61766100000016736176656c6f767633393940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714695fd23b8e9c5e7a24d1da766a4abeec540f5fcb3d9f07f4f1395c7eacdb2e277949f2f5c3a50f2e": "0x00000000000000000000000000000000000e526f636b585f4b7573616d613506526f636b581268747470733a2f2f726f636b782e636f6d0012737570706f727440726f636b782e636f6d00001040726f636b785f6f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469610a6934b675c69eafb1ad57ed8ee595ac311709e19ca5dae7df48680cf3c822074b2d69891d58": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714696f75486035f5d11e94bf36131632d37719d822bd603d9675488e206d77a509c5bd31ac4ff5ab2e": "0x0000000000000000000000000000000000074d6f72656e6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714697c98e61ff7a035f436ddc71e0400b93ece90a48e94cf0e193c9157c4a21199bc32b6dca543313e": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714697ead568e820ccfd2eb07f02043788e254d9e2df57be11566d241c56302b91199b4647947af3020": "0x040000000002000000000000000000000000000000000846415241444159001968747470733a2f2f666172616461796e6f6465732e636f6d1940666172616461796e6f6465733a6d61747269782e6f72671768656c6c6f40666172616461796e6f6465732e636f6d00000e40466172616461794e6f646573000d666172616461796e6f64657300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469937a5fa154cc0722a58635dd1a211d33750333282985df00d84e87b160293d6b39e89ea4bc7d67": "0x04010000000200000000000000000000000000000000084e45574445414c144f7665726d6172636b202620506172696465461868747470733a2f2f616e6f7665726e6f64652e746f702f15407061726964655f663a6d61747269782e6f726714696e666f40616e6f7665726e6f64652e746f70000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714699a4e2e91f07769c8f44643be482988aa2bcd437f7de9722e6a8990e44e2a64c2f426ce3337f006": "0x000000000000000000000000000000000017466c6f7878204173736574204d616e6167656d656e74000000000000104074686567616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714699c5d3507c778d4cecb620d2e44c2e64a400ff3fe531d5e4716897072fbda0fd33fd58dfaa5fa17": "0x00000000000000000000000000000000000b414e444557204e494f4e10416e647265692053746570616e6f761768747470733a2f2f6e696f6e2d73747564696f2e72750017737465702e616e406e696f6e2d73747564696f2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714699f178882ae3a35ec306760410fb8a67209ee8286fb9ecf86bf6dd864d277b7f3830b288f319267": "0x00000000000000000000000000000000000b677265656e6d61736b3900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469a2abccefec01421488aef5fe1d334d513adde87cf781758c6d9c6841cd1925b3b1fcd27f2e6e51": "0x04000000000200000000000000000000000000000000076b6f706f6e65000013406b6f706f6e653a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469b743ba383eda3afe7d71599a2b67c5085142c626641ccfc1f44919270fcac28d2ecfd41e0c7e3c": "0x0401000000020000000000000000000000000000000004496365000011407a6172313a6d61747269782e6f7267177a61723133696e617a69617440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471469ea407a9f4730a1de5813cb17d418545d0c39927cf50adf35e0a5676f4f9ff8ee9125dfb1cf1a0e": "0x0000000000000000000000000000000000124368616f7320436f6c6c6563746976652000000018696e666f406368616f73636f6c6c6563746976652e6363000011404368616f73436f6c6c656374697665000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a15d0669087eed9208735c92b8b6d8391241b17fffd2cd8a74ea8c713cd5ad058360fe8615d1c2a": "0x04000000000200000000000000000000000000000000064a756c6961000018406c6567616c5f6a756c69613a6d61747269782e6f72671e6a756c69612e7374656d7066656c4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a20805653256a9b76dbbe01275e2d5edc1aa637fa5e9e3f83b2eaf5338f3de24332be755548b018": "0x040000000002000000000000000000000000000000000641676176650000002161676176652e6e6f6465736572766963654070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a22a847a729096bb6c51bd8c8b45c224054c4ade99572611c2c41d499e26493c32e93e6868edc70": "0x00000000000000000000000000000000000c547572746c65204d6f6f6e0000000000001040576f6e6465726c616e64734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a2edd04aff025a00a71c6a0fbf9b63ac089c5395bdea4917a84aabb3475d4454147c4d24ce1013a": "0x040100000002000000000000000000000000000000000c45726e7374204b696e74730c45726e7374204b696e747300000e656b696e7473406d652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a398ba50f12d00734e23dcaeb2f272db78575091eb39369fcee10abf1bfc53551a9b9ec94b94c41": "0x040000000002000000000000000000000000000000000841757374696e5a000012407a6f75745f3a6d61747269782e6f7267146c65726f6e677a6f7540676d61696c2e636f6d000008405a6f75745954000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a4f96f9cd70bd9472e7ccd983b92c5ae60481a636eab0fe42269c9f43c302a74f9dc65e0fbe202b": "0x0000000000000000000000000000000000175375627371756964204c616273204f6666696369616c135375627371756964204c61627320476d62481568747470733a2f2f73756273717569642e696f2f0013736f6369616c4073756273717569642e696f00000a407375627371756964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a6c65861cbfd4f690ebd94a58a07211dcf05c4164ebab8c3abaca45f16f793fbe34072ae7b9ba08": "0x0000000000000000000000000000000000054d61726b00000000000011406d61726b5f656d6265725f7279616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146a6e72184ec057bf2838ec53e79c47d990272aa7c797218bcbdb229dbb4a083890ebb47a143387e1": "0x000000000000000000000000000000000018444f542056414c494441544f525320414c4c49414e434519444f542056414c494441544f525320414c4c4c49414e43451b68747470733a2f2f646f7476616c696461746f72732e6f72672f000000001040444f5456616c416c6c69616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146aafc9e20cbf801c6e2d7ed8cf2cde362abfdf7d9fa95859c20f906d98ca7aeb305a723cdba08927": "0x0000000000000000000000000000000000104b7573616d6120496e766164657273001e68747470733a2f2f6b7573616d61696e7661646572732e73706163652f00196b7573616d61696e76616465727340676d61696c2e636f6d000010404b7573616d61496e766164657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146ab589167a0b898fcc9f261e20561ee1a137a7c03770706d09a6f85e36e7a313f04d92faefbd3d43": "0x040000000002000000000000000000000000000000000942494742414c4c5a0000154062696762616c6c7a3a6d61747269782e6f726716696e666f4062696762616c6c7a2e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146acaf91ac46baae4f280f5a4ff014f822ccb22c7482c0b0c688b0fd288f57ea28fcef55ef7fa1451": "0x00000000000000000000000000000000000a4f6f6f63746f7075730d5061736b61204d6172696e690101167061736b616d6172696e6940676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146afd27c18040cef1a2af46cca496f67510c65b4ed9f745ff058392bdf7526b99764fb54eb6a1fd03": "0x00000000000000000000000000000000000b4672616374616c456c6600147777772e6d617968656d6e6f6465732e636f6d0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b1e4c1928a48d22a604120d3444af15fde1d4b1906795e462d4978bbd0ad2995312293221af136c": "0x00000000000000000000000000000000000a626f6e64616e76656c0e416e64726569204f6368696576001240616e76656c3a6d61747269782e6f726717616e647265792e76656c646540676d61696c2e636f6d00000d40416e6472657956656c6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b22402cd56d342a42e3f1833e3a53fbc58fc821cbc960242707bf6570504a0ce6d62de52df1fb3a": "0x0000000000000000000000000000000000076f6e64696e33000000136f6e64696e37373740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b2c66241f33f7627cbce8173250e3191a2ff3c05d37a116d3956565fd029fdf531795e3f429b431": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b3ea68cf38610c0e697c9f32c96c1d09daec35b2d6881c22c01a315dc9e44e17a1a1454c7a33f36": "0x040000000002000000000000000000000000000000000d5354414b452e5a4f4e45203200000010696e666f407374616b652e7a6f6e65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b602156dcd19a36e0b1d428d91be9ef7f6933b17ecfe93b41dc32014329c8f47697c43d11142121": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b6157a13ed645fa040298f71f02d7b6a67c0ecee7d7a62ea51dc6daecebf4dd9ad72e0510537a58": "0x040400000002000000000000000000000000000000000a43757272656e63797800000014656574696365706f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b72dbbac6798f2746fe2480205384715045cce22348bb6e69153e172c8780cdfdd9f48177edda29": "0x04000000000200000000000000000000000000000000067961726f6e0000104079726e3a6d61747269782e6f72671179726e40636f64656c7578652e636f6d00000a407961726f6e736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b793eedafb74ea99424aaa1e5fbf3eb4200f5686578f97d514f46f90093271607e7309ffcd5ae2e": "0x000000000000000000000000000000000005556c796100000017616c7661646f6c796d70696140676d61696c2e636f6d000010406e61756d6f76615f756c79616e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b8a8b66e5aaceb88ee2a383ae9ce2d6589f1b285935d8f4930f78e65edc311971df2526d2f55132": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146b9579021acd44d76a4e6c8afc7a8bd02ff300b3dd1edca19adae52cb65c1908935abba4e193a705": "0x00000000000000000000000000000000000b796f6e6763727970746f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146baf8445decbe4302880ceaa5b3bfd387562510764a2324bca0444751ccf843dba6d9950cb6eaa6d": "0x000000000000000000000000000000000008524d546572726100107777772e726d74657272612e6f7267001665617274686361726540726d74657272612e6f726700000a40726d74657272614f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bbba429de58b1c6ee8e0a7379fb0908719062234d2982188a3b31eb3aa895e6046981b865479b29": "0x0000000000000000000000000000000000155261696e696e20416c7068612041697264726f7000000016416c706861697264726f7040676d61696c2e636f6d00001140416c706861697264726f705261696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bd6f5cbed6591426e0b706961e1b5f3b545003ff3544f22feae738534cefa08be15d523f52ff114": "0x00000000000000000000000000000000000f4f647973736579404b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146be5d0bab82378087042479798003022a5753c8547cb0de8ef25e2471e40889ff3909fe714e24c5d": "0x0401000000020000000000000000000000000000000007414e414d495807414e414d49581468747470733a2f2f616e616d69782e746f702f1440646270617474793a6d61747269782e6f726714616e616d697840706f6c6b61646f742e70726f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bee5533ec8299d8ce116bea2fcddd47f5540ab01eb225b9cb60b053d5f0dd863d33ce89a6da4055": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bf5f668cb5d93dad21839a4704482a87db32156b9990a0eaa841fb2ae49e362cba1f0d5ded52376": "0x00000000000000000000000000000000000f67616c657261732d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bf9c9353fd020348c33b686a457b74f9b1a61b4446404e522d122064d6713ffacee88bfa9a15861": "0x040400000002000000000000000000000000000000000b53796e61707469636f6e0000174073796e61707469636f6e3a6d61747269782e6f72671a73796e61707469636f6e4070726f746f6e6d61696c2e636f6d00000c4073796e6170746963306e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bfc5690a062a1afacf62b7427d226aeaaa925a52f3b0dee7c343124b0adb8785b3fa48694a0b94e": "0x0000000000000000000000000000000000094a484f4e20524f59000000166a686f6e726f796172747340676d61696c2e636f6d00000d406a686f6e726f7961727473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146bfdbf25ef8b99373c016a81d6b5a5d805e1b21e8e0bb9014ba2dfcd7d128251b5dfc30502b3037a": "0x00000000000000000000000000000000000b4769676d696e64204949001468747470733a2f2f6769676d696e642e61707014406d6d61686572653a6d61747269782e6f72670000000a406769675f6d696e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c01c6b0489d52fa600031e4527046dcc067d2cb23fc6cb1970d94e9251fcc131cd5f23b6ca6d476": "0x00000000000000000000000000000000000c446164647920416c65782001010101000011404461646479416c3238393835303436000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c12977fdc424f56cea296c4097c6926c86d188eb65b0f77877584512ba5054f7c52873be1a0580b": "0x040000000002000000000000000000000000000000000c4d65726b6c6546726f7374001768747470733a2f2f6d65726b6c6574726962652e696f18406d65726b6c6566726f73743a6d61747269782e6f7267156d3475353461643440616e6f6e616464792e6d6500000d406d65726b6c657472696265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c1c74353498a63bf41c4ce9c03cf28414bc4e05a5bd6d5d79e72f700a38d5c722aebd796608c44e": "0x0000000000000000000000000000000000044b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c22738133d6c7a48e9da09f277ab09ea322900d4c6e0e3d3221c1a2b702f72590545e851fa9aa72": "0x00000000000000000000000000000000000e6c6c616d617a70726f6a656374000000186c6c616d617a70726f6a65637440676d61696c2e636f6d00000f406c6c616d617a70726f6a656374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c23be321ba1d5692aeb5a90eb2107b7490991ac059fc314c28974cb318c16f75f04241085fe936f": "0x000000000000000000000000000000000011416c656a616e64726f2050657465727311416c656a616e64726f20506574657273000017616a6f73657065746572736840676d61696c2e636f6d00001140616c656a616e64726f706574657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c3f94c82b8b136c880aa8e4ef5d44c88e477371270a5d5187b12475a39b620f0b813bd002966024": "0x0000000000000000000000000000000000124d697373696f6e20436f6e74726f6c203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c4d2026575763437cdc1a6a5a7f23437b6528edcdf553d0685f940a4e6e85579727ef3dc574563a": "0x04000000000200000000000000000000000000000000114365727448756d204d61785374616b65000018406365727468756d2d6a696d3a6d61747269782e6f7267136b7573616d61406365727468756d2e636f6d000009404365727448756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c53b7f96dcb583d9c2b14c09923911fe0ff6918b7c7702a91762aede2c2cdd0f1f0bdcf7b9f2a5a": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c6da4b2c10d05fda63297294a9d13df4e9fadfa013e8e6855d330075c55f9347bc4a63a883a8412": "0x00000000000000000000000000000000000748726f6d6f760d496c6c69612048726f6d6f761b68747470733a2f2f6769746875622e636f6d2f4d656e74616c47001967726f6d6f76746865666972737440676d61696c2e636f6d00000d4048726f6d6f76496c6c6961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c6fc4e27d0976af0043984dd2239bb88a209976e33ca5cd20ca0479096d86aab7e9b6137d5c2d62": "0x000000000000000000000000000000000008426972646d616e00000017616c65786a7573747761697440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c7206770c39d9295a5f7eb7050fb96d8d7895d9afce428a064ce66e3b094805bcad9a8e68cb9934": "0x0403000000020000000000000000000000000000000013424946524f535420464f554e444154494f4e14424946524f535420474c4f42414c204c54442e1868747470733a2f2f626966726f73742e66696e616e6365001668656c6c6f40626966726f73742e66696e616e636500001140626966726f73745f66696e616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146c748650b11aedf08eeb78c1dd6b2244b18b549a0c3cab933c680dbc18b411764be1ce4667f41649": "0x040000000002000000000000000000000000000000000948616d7a696b35330000001368616d7a696b353340676d61696c2e636f6d00000a4068616d7a696b3533000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146cae0ce72d947795c8ad53e6aa24a6208566faab7d3e203476531e2ee2b4c7d0d77c80245791a00e": "0x040100000002000000000000000000000000000000000c506c616e636b204c6162730c506c616e636b204c6162730000156c616273706c616e636b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146cc4e49307ea87327232db7b484171854543c6b3d42b95f6a16f4742d2f683d97fafb45e9bcdca34": "0x0000000000000000000000000000000000076d6f6a64697000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146cd2b2fd45e2e3d0702a6dc9592ec94ce9e1f07e2a0559d7f43f932101bace2400d0e92419218732": "0x040000000002000000000000000000000000000000000a73746b656e393939390000144073746b656e39393a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146cebd0b9de064aab0e038990f47761a17f45c2bb01c4c7746f4ad67c7d0c1dfbd6915372faae911f": "0x040400000002000000000000000000000000000000000a2a2a2a2a2a202a2a2a000000196c756e61722e706f6c6b61646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d01b9ac106696b20ec8ef626347c834d4d964b525fb46f8db2910e11d88c0100e62590d10ac990f": "0x00000000000000000000000000000000000f4b7573616d615f573353746f7265002168747470733a2f2f646573746f72652e6e6574776f726b2f726d726b2f752f4b001f4b7573616d615f773373746f726540646573746f72652e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d12ad5162806a9cca76c36de0085c8c561dbb64575cb016d4d6e7cef42b666d3ea978543f1c935a": "0x000000000000000000000000000000000008736b756e65727400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d1339be09f0555c5c229899568bac5fdc0ab838a23ee5391f704eac09ec1bdde78841beed461b6c": "0x0000000000000000000000000000000000074b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d301a445678938ac43aabf384c6baf54ef9712a96be7c46533b538c05d4e6c687fe09b109664b28": "0x040000000002000000000000000000000000000000000a4d616e7472614b534d000016406d616e7472616b736d3a6d61747269782e6f7267146d616e7472616b736d40676d61696c2e636f6d00000b404d616e7472614b534d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d34ca1ecaaeb6174471abb5438fa95f8c85b8d5a417df0a6a38b4372874f27f30f20645f3263830": "0x040000000002000000000000000000000000000000000b5975647573204c6162730000154064757979756475733a6d61747269782e6f72671579756475732e6c61627340676d61696c2e636f6d00000c4079756475735f6c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d54b71cad5f64b392e2419c0839bb61ec6ab6aae9fbb0c4fc9e519138faba9ae9e5eb4bd17f836b": "0x00000000000000000000000000000000000d616e746f6e696f5f323030320f416e746f6e2050616e6665726f76000016616e746f6e696f5f3230303240696e626f782e727500001140416e746f6e696f3639373637343938000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d5ba05b78a2e080daa4917008c6339bc42960ff491ffb03c3a6ddfc2b2b045d1c24112383398252": "0x000000000000000000000000000000000007686f646c337200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d74d28ec12105fa9e2ef38fe8e04e6f04dd146920ea60a5eb88dba8aeb59cba116768220dff632d": "0x00000000000000000000000000000000000a564953494f4e415259034d4a0000196e6674766973696f6e6172796d6a40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d77aae7d9cc2c6b6a08d5461e12b86fb79830fc2c45b9df0883ea74d91a02ae0c8ba8519d90f91e": "0x040000000002000000000000000000000000000000000b6372617a796c616e6464000017406372617a796c616e64643a6d61747269782e6f72670000000d406372617a796c616e646464000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d7865ba4ce38d13803c48fccb86dbda70ccfa6ac01c6246a558cd1ed3082276e3ec55ca850e1520": "0x00000000000000000000000000000000001373746576796861636b6572207c20524d524b0000001673746576796861636b657240676d61696c2e636f6d00000d4073746576796861636b6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d81d41850c8478a76016fc20a6457ff8953bf29686c5698c28bbfa860669ddd07b386c910f1107d": "0x08000000000204000000020000000000000000000000000000000016f09f9a82205a756769616e204475636b20f09fa68600001840726f626572743a776562332e666f756e646174696f6e17726f6265727440776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146d8e6ab01df42c15d25af2fedd4eb672f218932fde44f97f10c1d7788efd0079957ffad4f186ae78": "0x040000000002000000000000000000000000000000000b6b69616e656e69676d610d4b69616e205061696d616e691e68747470733a2f2f6b69616e656e69676d612e6769746875622e696f2f16406b69616e656e69676d613a7061726974792e696f0f6b69616e407061726974792e696f00000b6b69616e656e69676d610b6b69616e656e69676d610000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146da178aac6ca938996ef2b0677180342454254d3b508e6ce27545440454a0e810cbc779af50f476b": "0x00000000000000000000000000000000000763616f67656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146dae9d8fdc97e46a740e01932711bd4fd74b1c85696ef68396a6f11437ef8b8f44815103ffdbd942": "0x00000000000000000000000000000000000d4348414f5320414c49454e530d4348414f5320414c49454e531968747470733a2f2f6368616f73616c69656e732e636f6d2f0000000011406368616f73616c69656e73636c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146dcb518544a17d04f4fb2a6f05eb4f0ef01e695d677ffd9f940af819590642305c12924e203f9143": "0x04010000000200000000000000000000000000000000074d626c6f636b001368747470733a2f2f6d2d626c6f636b2e696f14406d2d626c6f636b3a6d61747269782e6f72671576616c696461746f72406d2d626c6f636b2e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146dd970d8cf026efb58ef09d3489cf843247e53debd2d08faabf4953de4eda8a0221474a1ec42e51d": "0x0000000000000000000000000000000000023500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146ddff06071871e051c3f1f94a947e045496deb2fb43db180a284a1f0f141875865aae404d0b38f17": "0x00000000000000000000000000000000000d536c65657079204c656d75720000000000000e40536c656570794c656d757273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146de5c15d472fd831e4e00e63c3647fc8c0a3d1b163ac988b6f0a7c3d05a01e209d4adef8e285037b": "0x040000000002000000000000000000000000000000000842696b657234620000001272656b6962346240676d61696c2e636f6d0000094072656b69623462000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146df179326c6132ac783485f72737efdd4e0c86f1097b1deea2a1ef0ea22514a081151293f8e78d77": "0x00000000000000000000000000000000001b54616e656c65657220616b612074686520436f6c6c6563746f720101010100000c4056696e694c6f6e646f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146df74e3c08670c34887a557f77bf1881bcf40ba6c2c8d41f819e5630997472cf310c76b8679f7d00": "0x00000000000000000000000000000000000873616e696f6b7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146df9089f721a647b5e18f2acdd0df1e1379c4e45df53fd18ae057e351a2f7df26cf6538bf1f3951e": "0x00000000000000000000000000000000000a4c6569662057796e20001d68747470733a2f2f6c65696677796e2e62616e6463616d702e636f6d00126c65696677796e40676d61696c2e636f6d000009406c65696677796e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146dfe113c3c0ddaf4a65e518d273553f951a8b5de9928449255508036636aafab13e479e51fa83153": "0x0000000000000000000000000000000000106172616e656c6c612e6b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e0bda57536f0f7afe8ed746b2f0fafda336e27346a75f2f03db0f73a3e73e1ca6deb3676e14d139": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a4d61747453616e746f0000001b6d617469617373616e74616f6c61796140676d61696c2e636f6d00000c406d61747473616e746f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e137c0fa3493007c85e3aa75711f5028f297d018c3e20ae87e5c605a4a42c32d075ffc5a2b1aa2a": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f353300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e1af8908544b70bbaadb6c3e6fb2482077a53cdba093a8ad605991be5a8f692c348c96cedb3b310": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31340f42494e414e43455f4b534d5f3134000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e2b59d3240a71b136bad3dc145e2a9330d4339cd3ae78ad38899297f90179c89e1c164e7db9792b": "0x00000000000000000000000000000000000b417263686976657273650b41726368697665727365137777772e617263686976657273652e61727400186172636869766572736538383840676d61696c2e636f6d00000f4061726368697665727365383838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e492261936ee303a8a1e3cbfa50d90dd8c3387e41849ee31bade6c9dd7631949b278e063ba0604c": "0x0000000000000000000000000000000000094b7573616d69746100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e49b5b6b41150cb5648a5099cc672def900b179b0b166c0cda43c5741fa016a0a4e59159eb4cc4b": "0x00000000000000000000000000000000000d50726179657273345261696e0000000000000f405f50726179657273345261696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e4c492ee4a04b7be0e388350540bfbcc4ec71eed079ac582106107fb7e4c3e0644a78ef77090f0d": "0x0000000000000000000000000000000000084752554d4c494e000014406772756d6c696e3a6d61747269782e6f72671b706f6c6b61646f742e6772756d6c696e40676d61696c2e636f6d000009406772756d31696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146e5600c7cb67a52de262091990c95c2667f621831f3215e8fc2a0958daa5658f4ce7c548fd687070": "0x040000000002000000000000000000000000000000001433394b7573616d6120436f6e74726f6c6c657200001a406175746f636174616c797469633a6d61747269782e6f7267116b656e6c303940676d61696c2e636f6d00000b406b656e736572736f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146ebf663bc0ff3d824445227fdc045db50d470f830869813c458eaa12071681d76ff022a7b9b5e750": "0x00000000000000000000000000000000001a4265636b795f66726f6d5f7468655f626c6f636b636861696e13526562656b61682052696368617264736f6e0000000000114042656b695f66726d64615f626c6f63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146ec642500076ba25a6c5f0595d6ed85d6260bc682d4a68a4b4e605d43c67d56f2765d19698549772": "0x040000000002000000000000000000000000000000000b5374616b656c792e696f0000124069696363313a6d61747269782e6f72671161646d696e407374616b656c792e696f00000c405374616b656c795f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146ef36fb6f6a6627954d552eafb3c32b82bee18d1093507b22d300293d0691948950fb2a6cfbf1d12": "0x00000000000000000000000000000000000b4d616b6569747265616c05416c65781f68747470733a2f2f6c696e6b74722e65652f6d616b655f69745f7265616c0000000010406d616b6569747265616c5f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f007ed8cae8e00c428480e94271bfdffe5fba698c5049093175433f81dde2e8f2f656a228995312": "0x000000000000000000000000000000000006626c6f6f6200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f162ae750478cd420d36d6d4b71407dccd0a9fe417f847296503b1db88b49034e72b107177d5e67": "0x0000000000000000000000000000000000106675636b746865636f70732e6574680000000000000d40665f636b746865636f7073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f1853e1ebaebf497a688ccd0cad14cf3e26ad4b10c0775968bac5ff48f77a8c4b09cc3c3d77ad23": "0x00000000000000000000000000000000000b4b75726f43727970746f0000000000000f404b75726f63727970746f525047000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f2598efe3f47fa4e622f17425a56e7acc6bcd2b36f6912005287c470d94a3deb0f0ba39f8f41f75": "0x00000000000000000000000000000000000753616d6f6c6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f2b5e9f208392888cf6773ed595b6b8f123786931160f5162f826be90f00ba77493312a768e9e2d": "0x00000000000000000000000000000000000f424154544c454b414e415249415300000019626174746c656b616e617269617340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f337845d3ff300d84ef1a151887ad6d4baedf802cfe9ade9c4c9ca57747723f0b3d7ca956997f7e": "0x00000000000000000000000000000000000d546865204e61727261746f7200147777772e6d617968656d6e6f6465732e636f6d000000000d404461626167686f646c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f360d963f230c31180b25c72c11ca6b74d6601e3684642afbe828f3e7b45479a42d0b84fc8cdf12": "0x00000000000000000000000000000000000b446f62726f646979554108416c656b73657901010100001040416c656b7365795f313936393131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f3d6f5d8945a2a9d896f718b4ad053ba53468ba0347060b4a80f03fa72e9c14da5e2e7ea80e3f2c": "0x0404000000020000000000000000000000000000000008426974446173680000001a6d65726365646573736f72656c313040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f3df2817b3b9c94e44dba99bb5810bdc7a2a1d32a4b021ac735ef01322f57be7b51210f46d3b323": "0x0000000000000000000000000000000000074c656f6e5f4701010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f56186447cd7ef15aa188fa54383921d848228f0e40540f07297c6241a05e63f675ce5ec53da525": "0x00000000000000000000000000000000000f666f6f7462616c6c68616e67303100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f630b718e317f68aab8c369bfc11e722e4328afbcf0bde98b014ac292eb9a33e745acd3c4e820cc": "0x00000000000000000000000000000000000d484f4c44504f4c4b41444f540000001c636f6e74726f6c6c657240686f6c64706f6c6b61646f742e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f7f4b41e08c803b185c5ef33d3d91ed9167e35bff60265cec83c040ed7766f256ce0f599da6c749": "0x00000000000000000000000000000000001056656c696e6f7661207c20524d524b10436872697374696e61204d6979617209726d726b2e6170700013636872697374696e6140726d726b2e61707000001040436872697374696e614d69796172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f808393005db1390cdd6d75a061aa70b5d57bd30e693cecb8e7a392788262319da19105c0f4604c": "0x0000000000000000000000000000000000084e61706b696e350f526567696e616c642053747568720000127274737475687240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f99dd7465b93e507c6e2eb7daa3efe47026b0aaccc5c24d5a8c36387f471d5ad10b63a269bbc11c": "0x00000000000000000000000000000000001541746f6d757365202d204b7573616d61204d4b311541746f6d757365202d204b7573616d61204d4b311368747470733a2f2f61746f6d7573652e63630010696e666f4061746f6d7573652e6363000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146f9bf1c5c47f9bff1c378d545f64248bedae80ec34f8f29551fc9f814f8491f8fea50f10fff6e229": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047146fbe924612f6781f544bbcd309eadfd42df83e1483616da5dbccf5a8cc0bfcdc023c4d310580cb2d": "0x00000000000000000000000000000000000f596f6e6b6f204d7567697761726101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470014f24dcab4fe440a6b2797a5499aaba937f5931186ce4ec4831af09c1571f185e68a0a926451a": "0x040000000002000000000000000000000000000000000846696c6970706f1246696c6970706f204672616e6368696e6900194066696c6970706f3a776562332e666f756e646174696f6e1866696c6970706f40776562332e666f756e646174696f6e00000d4066696c6970706f77656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470023b9d2a2c164748ca001326b583070e370be3bc6680d09cad47649584a5c992bd388c693b9a54": "0x040200000002000000000000000000000000000000000f4b6576696e204c69207c20455043000014406b6576696e6c693a6d61747269782e6f72670f6c696a756e7169406d652e636f6d00000e40647573687573616e6a75616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147006767d397f2ca9ea767408daed5fa84321c8d73e1353b847391877cb07ede4de41a98c010fe702": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714700eadba413b7d7e9a017a02ac5e0464e0fe81c2db6d53396f85e7cc4818fa63972ddba87c1db039": "0x040000000002000000000000000000000000000000000d4d617968656d204e6f6465730000000000000e404d617968656d5f4e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470175c9772705b5ba28f7a2b2fd4fd83e0dc9c67d22fea19d5e755aedc336a973afa342ef2642147": "0x0000000000000000000000000000000000094d69636b794e465400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714702bcefac99fd4dd8679aa82b4485f9035d099869dc380bc36b390ae89b77a21b1dfb8db3de56d54": "0x0401000000020000000000000000000000000000000007746477736e690000000d3040746477736e692e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470381211b81bd578b208742339c55723f8834a3379a95ba73073d7583a7d381ed6ec1b860f46692b": "0x0000000000000000000000000000000000043737370000000000000d40766c6164626f6e64373737000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714704211a750c9b855eed08a5b10b1835610d66ce4fa273c8e2436b978c9f65442efb6074871b48a6a": "0x040000000002000000000000000000000000000000000c50726f766520436861696e0000001570726f7665636861696e4070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147049f2f99a873c94c00f86f5f5421e98f7ba345ccd996c53412f39308ea854053fe650ca7bf44f75": "0x00000000000000000000000000000000001242726967687420496e76656e74696f6e73001d68747470733a2f2f627269676874696e76656e74696f6e732e706c2f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714704fd4d990de5befa2062502692e27d3608be0d008ea4b92ec004291e439f90b050bef5ec7f0f23f": "0x00000000000000000000000000000000000d506f6c6b61646f74746572730d506f6c6b61646f7474657273001440706d656e73696b3a6d61747269782e6f72671c706f6c6b61646f74746572734070726f746f6e6d61696c2e636f6d00000f40506f6c6b61646f747465727331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714705bdbc11ece35d4b43cfa22c3d218af6782a4d65b8f3634fce7cffea162940ca819714f49747337": "0x00000000000000000000000000000000000d3320457965642042696c6c790000000000000b404243727970746f6e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714705e6ea755bbf165fee29a5ceb96897553f0573c57f2824416ab0160259c6dedd23dc9553e7f7979": "0x00000000000000000000000000000000000c506f6c6b617370696465720e506f6c6b617370696465724c7500000000000e4061696c696e67797532303138000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147061508d0facf9d35a1a549172a49f7591155007c51680ad8ad77571cea04acd1b0b84459e779234": "0x04000000000200000000000000000000000000000000073078546f6e6500000000000008403078546f6e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147067b025e697cd29c8ceb1c664df2d960b92a98620baf455b678d17a8c066832ad463537dec7b916": "0x00000000000000000000000000000000000e416273747261637420536563740b54796c657220526f776500000f746a726f776531406d652e636f6d00000e40416273747261637453656374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147073fca8d293ce1f104f30a7ce921de97e2b0953c03b1b52290417f02ddbf93f00d32560ce6cdc73": "0x00000000000000000000000000000000000014486f706520446f726f746879204d7572706879000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147074ebffa575049570886222c37e2ae242e928891fa622a6117888450059ea48efb53048e2b7d46b": "0x000000000000000000000000000000000005527572750257010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714707a1c5ae852ffd0d6e82061804fecd8a01e8c288670158557d1e0d29fd43965d6d9a18f456d9e5c": "0x00000000000000000000000000000000000e63727970746f20706965727265076c6f7572646501011a6b6576696e6c6f757264652e70726f40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470862ef001da720f4c91bbedabe6c9691a94cf18545d962d105c46e421a187a1762475116b6e3931": "0x0000000000000000000000000000000000104162737472616374204d6972726f720101011e617274627961627374726163746d6972726f7240676d61696c2e636f6d0000104041627374726163744d6972726f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147097277b2a5e0e0c74c08ab30239142fa489802606f4ba630d10ae640d418068e557125f7ab21437": "0x0000000000000000000000000000000000044a444c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470b0ccf61769cfd8360745c8f812f88313ecea48072c02d3af2e0879f0788fb42ca57d2a08308913": "0x040100000002000000000000000000000000000000000a414747524547415445001b68747470733a2f2f6167677265676174656e6f6465732e636f6d16406167677265676174653a6d61747269782e6f7267206765742d696e2d746f756368406167677265676174656e6f6465732e636f6d000010404167677265676174654e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470b521035124345e708abc87f99cb7125a4485ab287fe649da93d7f63d94f1723eff0702ce271b38": "0x0000000000000000000000000000000000104f6666696369616c204b75646f7473104f6666696369616c204b75646f74730000196b75646f74736f6666696369616c40676d61696c2e636f6d000010406b75646f74736f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470c16b639ae50cfd227dd8d2161a0ec5c16d32bb404f4397db4eec7a0384dec4434653c46d6b4e68": "0x0400000000020000000000000000000000000000000007616e73616368144141524f4e2054494e4720534541204b494e4700001574696e672e6161726f6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470d819a2c84da4c51854e80d2ab67fb4b12a0372a7345e933258591fa524445f98f9e228c6c2d157": "0x04000000000200000000000000000000000000000000054f7461720000000f6f746172407061726974792e696f000011407368616b617269736876696c693237000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470e8af948020788b9023c272646be7fdd636e3f40a760528e8d3ed13a56a7f60b70dfb0865e01057": "0x000000000000000000000000000000000006566c75796e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470edeff14bdc035a2290b0d093c2c0a08acdb392bed5b03a80bdd6654e950ff597feeb3c9b9fa831": "0x0000000000000000000000000000000000114d79436f696e7461696e65722e636f6d001968747470733a2f2f6d79636f696e7461696e65722e636f6d001761646d696e406d79636f696e7461696e65722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471470f0a3ba8fdc51ba04c760ba8b16be7af64b5fb7e1b3243abc8a02ffc7e87fde86fa29f6ed3c5776": "0x0000000000000000000000000000000000076f6c657a62610000000000000a406279627972616279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471116de1a587c32588a4ed0e6c34d0464f85f9b7017fac279d96a1a581c00df0a2d68e655836b75d": "0x00000000000000000000000000000000000b537072696d6f4d61696e0000001573616261697072696d6f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147112ba5d6dbefa86fa8cae363fae322ca18adf9cb334426c0d8a4eda052ae2919136fb2aaf810d2b": "0x00000000000000000000000000000000000a43726f636f64696e6f12456b61746572696e6120426c696e6f76611163726f636f64696e6f2e64657369676e001a64696e6f63726f634063726f636f64696e6f2e64657369676e0000114043726f636f64696e6f44657369676e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471136285006adf116270f8a05e7e0281bc17de3331550f81e8089dad4b80614c028c0c816a872566": "0x00000000000000000000000000000000000d534652204465706c6f7965720000000000000d405346525f5f53747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147133801574a23097407c5d153353f5dd34183ce2c8b55e6b7858de0baa2a568b7c577ae65f04623b": "0x00000000000000000000000000000000000b6b68616e6f6e6472756d076b68616e6f6e010c406b68616e6f6e6472756d0100000c406b68616e6f6e6472756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471338c87abd75247bec65f0d42a638f8ecec8206173fe2953dfd914fe6285ad35812621e09e8373e": "0x00000000000000000000000000000000000757697374617200000016656d696e34696b3139393340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714714f1bba6aeb57ed503830ae159d84972115565fb0d195f5c84d0b3aedf7661f14923f434c482e58": "0x040000000002000000000000000000000000000000000455534100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471807145847ce7520a9e6fb48b9423ae5939f07fe1d7f41a6c1ebe3d2135e94af94b7fd717a47418": "0x0000000000000000000000000000000000096d6161726d6170611e6d6172696f2061727475726f206d616c646f6e61646f207061727261201b7777772e696e7374616772616d2e636f6d2f6d6161726d61706115406d6161726d6170613a6d61747269782e6f7267106d6172696f40626f796b6f742e636c00000a406d6161726d617061000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714718a792663e13c111e015452870e49b4e4c3e054556b19683e8895586bfa58638a74a5782ab4f712": "0x040000000002000000000000000000000000000000000e414c45585f3031205354415348000019406261626c6f7275626974656c3a6d61747269782e6f7267176261626c6f7275626974656c40676d61696c2e636f6d000011405374616365794d3033393337393233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714718c7c930a9f7254d86997541d3de5e602951b87a658d2b1f239a44b1aa7db63926677175a296130": "0x0000000000000000000000000000000000044b534d064252554e410019406272756e616b616c6c696e653a6d61747269782e6f7267186272756e616b616c6c696e653140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714719741a00f0f258052b508058d399f2d273c624adac51fc2e2e9083a0d13cb59e515c83178b91f08": "0x0000000000000000000000000000000000054e4f4952054e4f4952117777772e6e6f69722e6469676974616c00146472696e6b6e6f697240676d61696c2e636f6d00000b406472696e6b6e6f6972000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471a62c336559149c727cdf9587aa815816cbf027b2040a04860e0ca6863df676ab65e79aed5dfe12": "0x00000000000000000000000000000000000c596162615f44656c7578650000000000000c407961626164656c757865000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471b1a690490b9b855030a81483b3f65ad2904fd32cbcd5d3a534e9617e0c1daf610acd4e1d851821": "0x00000000000000000000000000000000000a646965676f6e616b7500000017646965676f5f6e616b7540686f746d61696c2e636f6d00000b40646965676f6e616b75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471bab60978c7657ac0af8f315fd5c43e3a9d5f24986cff822296343aef9c3c9e9c98d7b8c16dc770": "0x00000000000000000000000000000000000f536c696768746c79204a756963790101010100001040536c696768746c795f6a75696379000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471bdd65031f8d5b4264b8f4a0be4ca7a9b8c7a8a08a119d549bebb1be6049b2947d363cf06f1e749": "0x0000000000000000000000000000000000076261796576730101010100000840626179657673000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471ce39b31932f385f616ea43a83d30c7e9cd14c07f2534d4e1d983feb50af44e2e101786f1174d5a": "0x000000000000000000000000000000000008537461726579650000000000000c406879706574617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471d47d954dd610d384e78712d71e4663b0673f11b9b9119d41b6a74c3ab3e1cc49b2c26e45f2c717": "0x0000000000000000000000000000000000104c6962726172792047656e65736973104c6962726172792047656e657369731368747470733a2f2f6c696267656e2e66756e0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471d6f804bbc175ce2c2fcfda3ef3753aaef240f2d5048bf365a746ac9ad94836ad72d9e4030d217d": "0x0000000000000000000000000000000000074e61744172740101010100000e404e6174616c6961735f417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471471ea140dfcf364da7e3b8fd929dbbbd1986cc76d08bd7d45710b54ebd933c2545bbcaf1981b4f02d": "0x0000000000000000000000000000000000064c4558584f0000000000000c4069616d736f6c6578786f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147214db08aea29f4c2a5bd5797da40fe8be1b94dd3260ef86d6b01cfc891c5c1cd160ad7fa198de57": "0x040000000002000000000000000000000000000000000a726f746b6f2e6e6574001268747470733a2f2f726f746b6f2e6e657418406869746368686f6f6b65723a6d61747269782e6f72670d687140726f746b6f2e6e657400000f40726f746b6f6e6574776f726b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714722083cf8467cb9174725e8d7159b39aa5dd43117d6354ba8f5ebd00f73b484e0b397477ce8fa949": "0x00000000000000000000000000000000000868756e6973616e00000017706170616d6f6e2e676f2e3040676d61696c2e636f6d00000d4068756e695f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147231a73eec660398046ff960b0d51db710b8ca414171afd47c9612311b69fa9416622dfb42a33124": "0x04010000000200000000000000000000000000000000073330383072611f33303830205265736561726368202620416e616c7974696373204c74642e1468747470733a2f2f3330383072612e6c74642f13403330383072613a6d61747269782e6f7267107465616d403330383072612e6c7464000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714724c7c15464878b07802118deb1bdd268c44247e6804781b4548c46e8442a63af94682f2586fd54f": "0x040100000001006c57c10b0100000000000000000000000000000000000000000000000000000f4d792043727970746f204769726c001968747470733a2f2f6d7963727970746f6769726c2e696f2f00157465616d406d7963727970746f6769726c2e696f000011406d7963727970746f6769726c4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714725a86431f305963b0537038713a322f80aecc5a647740589a2ab3a9f558d66e1edff7dbcf321034": "0x00000000000000000000000000000000000f537572662042756d7320436c75620000000000000e405375726642756d73436c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147266c84e2a6ccd54865a0192a7b1bf11f1915b156b8a80e5bc2983a38d075ecafb9fcecd13980210": "0x0000000000000000000000000000000000144d69737465725f436f6c65204344204d532031000018406d69737465725f636f6c653a6d61747269782e6f72670000000c4031393238333734367a7100075f6a706d665f00", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714726d01a4c80d6ba32af509d174981a76e0ea8736ebd955e869e7aa3df90d9782dfd27f8d5275877b": "0x00000000000000000000000000000000000e6d61696e2e73616b692e6b6f7500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714729ca592de7e6cc0349febe9138f7c4f2123246970770df11b411268566c25bcf71377d23717285e": "0x00000000000000000000000000000000000f56696c6c69616e20417274697374001968747470733a2f2f61727469636b7573616d612e636f6d2f00136e6674766966657240676d61696c2e636f6d00000f4076696c6c69616e617274697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473006ea8baa58afe58f26dd10efac24a7fd1813d6aa72a8e60bee976f7da28e492ad033fc1822315": "0x08000000000100902f500900000000000000000000000100000002000000000000000000000000000000000e4172674e6f646552756e6e65720000001c726f647269676f2e62617272696f73393040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147304b924b222e0c7dae5efb233d7bdc68fc16135030559ee44b6372ef24650ca982158e8ae9b1c34": "0x0000000000000000000000000000000000077761766530360101011c6672616e636f69732e6c6567656e64726540676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714730966358482a89df88d7cb742e81b397cdef5f7cb474cf2df150c46a450316042e096240b132b7c": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31310f42494e414e43455f4b534d5f3131000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147315356594fd4a95bcb17afaf0c76d9419961b476bda55ae861b5ddc7517212e5ffe51739ce7110e": "0x0000000000000000000000000000000000074152544b555307416172746f6e17687474703a2f2f7777772e616172746f6e2e6172742f144061616172746f6e3a6d61747269782e6f72670e61616172746f6e40706d2e6d6500000d40416172746f6e447572616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714731673ba1d1b7d986e311246667f84dd2c1d2c2d2125f71c1364b217deab8ef23eacfc4c693fa64a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714731adab152229ba0b659069707b696d313e7ca3bae3a5f2c4951bc142487185e254d35f7af56c40b": "0x00000000000000000000000000000000000670616f6c610d50616f6c61205475617a6f6e1c68747470733a2f2f7777772e70616f6c617475617a6f6e2e636f6d001668656c6c6f4070616f6c617475617a6f6e2e636f6d00000d4070616f6c617475617a6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714731facdea878555ec6f4c6d200f27c4b02afdd345dd02ea77dc45c05b79dcdd2c5709418a0658503": "0x00000000000000000000000000000000000d63727970746f566f7274657800000000000009406673675f646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147321f7eac82ba0a6d68f13f9cf8966128c622327bd4819ab2a9ee1532587bb04ebc99e5e993b4ca1": "0x040100000002000000000000000000000000000000001a526567697374726172202331204775696e656120506967203200107777772e6578616d706c652e636f6d0012692d61696e742d6e6f2d656d61696c2121000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473445c1fa17d2f30828005347ff7053e6a83a61075859529c9ae6f85ea952e2d44d8b5667209933d": "0x00000000000000000000000000000000001a4d6f72677261746868207c486f757365206f66204368616f730b4a61636f62204b656e740000156a61636f626b3130333040676d61696c2e636f6d00000b404d6f72677261746868000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147349ec625640077690a8aa6a4593bba62b920c5dd3f580b4bafa5b6c3b567dbaf5598d3f0963466a": "0x000000000000000000000000000000000012546865204e696768742047616c6c657279000000176e3167687467616c6c33727940676d61696c2e636f6d00000e406e3167687467616c6c337279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714734b6c90edb07bd010f22d753c18dcb34da3b1573e4ecdff30f6d3b2642b1864d3bd7832e5cf9721": "0x00000000000000000000000000000000000759616b696e6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147351a6242479e8c754adb573ab2fe5551264b00100828e552e8ff391fcf975b85ce81f900a2f5b32": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714735585e3f384f206eeae02b784e8ec57b81c2bbe0cbed5bd3cb5dcc98f76d81c99edeae3a2aaa85f": "0x0000000000000000000000000000000000074f70706f757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714737675dbae64b33e3284bc8ce3083b62e671d1c5bd61db5b3fea95a77967341ca8834a69cffcfd5f": "0x040000000002000000000000000000000000000000000b53554241455445524e410000174073756261657465726e613a6d61747269782e6f72671a73756261657465726e614070726f746f6e6d61696c2e636f6d00000c4053756241657465726e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147378c2b706979cac06ecf3372b3e7ece785bb3ac73d9f9b458fe48856ca1a524e929f794e8c17320": "0x00000000000000000000000000000000000b4b55534157414c4c4554094d4f4f4c494e45580015406d6f6e5f70736575646f3a4d4f4f4c494e4558146d656864692e62686140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714737e39e875eb0a9662e891cdb404830ad46eb5fc896e60670f658032c6914f08fab6f79d7b2ccf57": "0x00000000000000000000000000000000000e4a6f6162204e697761676162610000001b6e697761676162616a6f61623130303040676d61696c2e636f6d00000f404e697761676162614a6f616232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147396af96b1f453f59e826b5434525d00c118f3f6b0a29b7f432be7bbd18659d472c5f07298e76949": "0x04000000000200000000000000000000000000000000096d696368616c6973001b68747470733a2f2f6269742e6c792f6d696368616c69732d696e00176d696368616c69732e66724069636c6f75642e636f6d00000d406d696368616c69735f6672000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473ba145c306b74dbccb16cd79f56a5405f9cdd0dcf58fcad90a18beb2398e77175d36ff52eb2cf3c": "0x00000000000000000000000000000000000f4b7573616d612048616d73746572000000186b7573616d6168616d7374657240676d61696c2e636f6d00000f404b7573616d6148616d73746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473d68690216574fd6c6d70ef9d0c65d3371ed462bf273c97368bc1cf484d361ffc7e453f2eeef457": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473e46c80f9d62c235e8f1c9a2103345a007c30d9238d3ddde738792ca155c520ca3d5e6f71c11153": "0x0000000000000000000000000000000000073275326e32690b637269737379616e6e201868747470733a2f2f7777772e3275326e32692e636f6d2f0017637269737379616e6e33313340676d61696c2e636f6d00000e40637269737379616e6e333133000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473e5d8ceda089f22283a608f6cd382190e64f646c648318ba0cef6e3177d31e0d7bd753ffc28e70b": "0x000000000000000000000000000000000005416c657800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473f4bcd1862aa772d67d4382c3093feb355d01710902f2e705a2ad23b41bd67a006f5e82137f1d58": "0x040500000002000000000000000000000000000000000744616e69656c000000146f6e6564616e69636840676d61696c2e636f6d0000114044566f726f74796e63653133333335000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471473fdff1bc4baf9bb02700d16339ef586cc2850916f3a1556ab9cc6ec0fc649b0dbda00eeaa3acb72": "0x000000000000000000000000000000000008486174746f72690000000000000c40486174746f72694e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474083880a0b640654a003aeae28534daddcc861d7d3e91b576683544217044cefcf4803ced1fbc69": "0x04000000000200000000000000000000000000000000086d617873616d340000000000000e404d756469745f5f4775707461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714741fac12b13370280685555e8c1a13943f5c7702c73b2f447830c65030eaccc6b924eabd400cbd4f": "0x000000000000000000000000000000000007616d616c696b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714742651abfff8b63f6efa3511e9ccc0610b2002fefe0d71f5faefaf5b0cc88b07fef66b2b1cf2ac35": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474271bdfa6ae1a69da47518aa64a1ff00dd57c2ff1727281161e074938a18a6096b1babdbd7d1e06": "0x00000000000000000000000000000000000b52696368617232363834125269636172646f204865726e616e64657a1c68747470733a2f2f626c6f636b636861696e673939392e636f6d2f010100000c4072696368617232363834000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714742888be1295ba6bbaead6c7fb94fc60bece91d9847eec0b31d78bce6152066713100b34a839505b": "0x0000000000000000000000000000000000056552654c000000146572656c2e676f716240676d61696c2e636f6d0000094053746162316c30000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474406008848ff57f0c82db2f36c07bfec5b0740ed71bbf04598091b6d37990d6bf84c959e3a4abff": "0x00000000000000000000000000000000000743726978757306436573617200184063657361726361737669643a6d61747269782e6f726716636573617263617376696440676d61696c2e636f6d00000d406365736172636173766964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714744b3cf73bf091eabcd7eb9a65ba6073a4b69584560dac24856d42dd86c2626369f9e8cae4ff4746": "0x00000000000000000000000000000000000a4465657020426c756500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474559469cf43f4e2c4fcd7297103660b29d0123458798ecb8bdb13eecbc41a9c04530e9d13159f74": "0x00000000000000000000000000000000000830785041494e5a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714745d268c749fdfe7f456c1a72c215f5a9ca81bb0df28c94111eca509b92500b47c2b31f8bfc59d7a": "0x0000000000000000000000000000000000096b72616b61746f6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714746c4fe5893bfd45e09fc6d479ac74e565c808896aea76e5fdf7246342e37e353c5c94efb64b3f67": "0x00000000000000000000000000000000000653415459410000000000000e407673617479616e617665656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474716d14814cef8d82f736294488b59a485d55f39a68754429437d762a2973da86c68a69dc70ab59": "0x00000000000000000000000000000000000b626f7265646b6e6565730000000000000c40626f7265646b6e656573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147475f3aac064f73442831969ffd0acbbf3f772b0456bf8efe1217f291efa8feb4e989f85afa43c33": "0x00000000000000000000000000000000000661727475630000000000000a4061727475635f6374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147486007852d722beb28d79f911d3438c510261d54ebf88c62527eb890a806c921fb67177d5cc2248": "0x04010000000200000000000000000000000000000000066c75313931000012406c753139313a6d61747269782e6f7267196c7531393173756273747261746540676d61696c2e636f6d00000000066c7531393100", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714749169ed52de2b9f4854e348f7dba33f64383ac0cb3cc067b4fca99fc2b72710cb78cc9c4e1bd343": "0x00000000000000000000000000000000001c4e49434b2753204b5553414d4120312028455854454e53494f4e2900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147499a373d4b2f70f8419a4ac409fa4e7bec032c696c526fac10ff9114d928df56ca0bf9e9ae29149": "0x04000000000200000000000000000000000000000000104d41415254454e207c204153544152000013406669657865723a6d61747269782e6f7267166d61617274656e4061737461722e6e6574776f726b00000b4068656e736b656e736d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474ae4b04f564e823e42dd6f52f63bcbaf33ac5fb58a55537539f1ed9f811c1341329e975c71a4930": "0x0000000000000000000000000000000000055376656e010101157a32363039353232373440676d61696c2e636f6d00000b40416c7269635376656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474b0f64b9469490136260874c384616f8b5a95c2411b348c39fff27cce76cd42755d8d6fece3431b": "0x00000000000000000000000000000000000764636363757300000014646f6368656f6c4068616e6d61696c2e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474c050d87caa47647e4e0465c71777ec6af833a58cd011d79e25a7ff7c0a0dbdd7f8128f95bf2347": "0x00000000000000000000000000000000000a627261776e646f6a6f0e4272616e646f6e204d61636572000016626f626279736f7833323240676d61696c2e636f6d00000f40626c6f636b736272616e646f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474c0ebf8c6444329b22c3558e9004c7c046c943774f9f95a6459ade5b4aad4180d7159ebe4119a24": "0x00000000000000000000000000000000000c50696e6b204f72616e6765134b69746368656e7a6b7920262047726f6f6400001870696e6b65646f72616e67657340676d61696c2e636f6d00000f4070696e6b65646f72616e676573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474c3ae49c1416014a0afbe96d21f06c21f01a6e501750fe36c0e4697b8431fab6f94a558541b6446": "0x0000000000000000000000000000000000053230373500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474cc699b7926e3dd6a935bf6362c818dd3106b1b36b6ae8024e257a1a626ae763aa1b4858ad2a239": "0x0000000000000000000000000000000000054d4945530000000000000d406d696573746572696f7573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474d82617272f8f5c901a175702ec27245aa892dd1bcf5cbd174d3db6eac6768ca832fab149273429": "0x0000000000000000000000000000000000056d61747400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474d9203d38249c605c58ceb3d9af8f7088d7f2ae7496000c0d358cbecd774629a4f03e413497637c": "0x040000000002000000000000000000000000000000000662697432300000001461373931363032373640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474e73ec4f7c76752d65d5c1484e5faf8ad32907ab729add8ffc2ffe0f29bc18015bec2c3f8ac7c66": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471474e91f24b625d4c85eb083f19535ddfc1936497ce8db7b4dfb4af273000c4e2b9148077da9260547": "0x0400000000020000000000000000000000000000000008414d49522e454600001740616d69726b68616e65663a6d61747269782e6f726719616d6972656b626174616e69373540676d61696c2e636f6d00000c40655f616d69726b68616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475229331a2dbb39412313fce4a12f0d70df33b7e34d5d4465c36287f220e43ea28005ac76322132f": "0x04000000000200000000000000000000000000000000084b726177696563000015406b7261776965632e3a6d61747269782e6f72671c6b7261776965632e76616c696461746f7240676d61696c2e636f6d00000f404b7261776965635f7374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475257b58fe3742e82ca47b427122fbbfe8de659ddc23844cac97f091453869825c922079c350ac2b": "0x00000000000000000000000000000000000a506172617368696e730e766164796d206f6c69696e796b00001a766164696d73636f7270696f33313140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714752ce2fc0e55cd08ac33b989d0b4dd35d2fb8af4cd04cc5a3831e59023cb884044f5cda0541f1064": "0x040000000002000000000000000000000000000000000b4d61746843727970746f001c68747470733a2f2f7777772e6d6174682d63727970746f2e636f6d17406d61746863727970746f3a6d61747269782e6f7267116d61746863727970746f40696b2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714753ac717444b23dd1cf3e5e0a3f8f198a63f5f7284fe493c23e88161d92d2cd418e52d050e3bd22b": "0x040000000002000000000000000000000000000000000ff09f8cb46a756e676c65f09f8cb4000014406d616e5f6375623a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714753bb535f9a5c087d4e6d6256f56677bcdbc0543f1a2c40aa82497b33af1748fc10113b1e2a1b460": "0x040000000002000000000000000000000000000000000f4c75636b794672696461792e696f000018406c75636b796672696461793a6d61747269782e6f726714696e666f406c75636b796672696461792e696f000011404c75636b794672696461794c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714753d125c2bf217855867f9ad84580fdde5310bb3bc75271259aa2e8b2c2c98fc249fce382e1b3871": "0x040000000002000000000000000000000000000000000d506572666563742d6e6f646500001940706572666563742d6e6f64653a6d61747269782e6f7267146b6174656b7261737640676d61696c2e636f6d00000b406166696b736c697465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147550c5deabfe47ad2c1bc0240190ae1f8f11a721be76cd4b628e0ba46eb943bd040cdb4c93883513": "0x00000000000000000000000000000000000c4e65642052796572736f6e0c4e65642052796572736f6e010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147551fa3a9029b0b45c8c6d9b15990f00bae2cb1ada580b4542762816af1644539183aa12906923d9": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714755c80f8e6c4a211e0a847a82939b522cfc1e77ec7067dba177ea048e7241bb47415e867e1149d5b": "0x040000000002000000000000000000000000000000000a56616c69627269756d0000164076616c69627269756d3a6d61747269782e6f726718616c65787469636b6f7269736840676d61696c2e636f6d0000114046616c6c73456c6973653531383139000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475682a0307a79151dc5097277a9b8a83b3886f07f7ea245f1f487de234aec097ea6ad84d2d71343e": "0x00000000000000000000000000000000000843484d522e494f0943484d522e494f201068747470733a2f2f63686d722e696f010d7468656d4063686d722e696f0000094063686d725f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147571a6ecb5a2dbf4548dcb6c3aabe041e7f7ee65af37818dc7ff1ff1a4300008100322c39e9c610b": "0x040000000002000000000000000000000000000000000c4d65726b6c657472696265001768747470733a2f2f4d65726b6c6574726962652e696f18406d65726b6c6574726962653a6d61747269782e6f726714696e666f406d65726b6c6574726962652e696f00000d404d65726b6c657472696265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714758982f5e32232cc0a223d7867531f2390fd0eb3a2ba98d93ea437e2cd466997e2912a83ac278a01": "0x040000000002000000000000000000000000000000001062756c6c735f616e645f626561727300000012706570657065703832406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475a0d6509fc0241396a4d072a866d0159f05d71a556328aac66e6615a6317e3ef3e1ea8809bd211f": "0x040000000002000000000000000000000000000000000a6d63626561737465720000000000000e40647269736d65676973747573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475a38f0aede221241069369c13e300464594a119fec27d43ff2a939abed871a8fbc0e0610bf6736d": "0x00000000000000000000000000000000000a506f7368506572727900000019706f736870657272794070726f746f6e6d61696c2e636f6d00000c40506572727932506f7368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475ccfb98243b897452cadfbd70405e7a8fe22235a0d0eeaf7cffc9644b3a3ccd8b5177cbb56c3c57": "0x0400000000020000000000000000000000000000000009616e64657273656e00001940616e64657273656e303730373a6d61747269782e6f726718616e647265693037303730313140676d61696c2e636f6d00001040416e6472656930333334333837380010416e6472656930373037233131353900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475cdc28c14a9cc2afa39f29d6a982110baf95aa0df5ea004d5bd47384487c755bed36e36685caa39": "0x000000000000000000000000000000000007596f6f6c757500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475d0e8e1b508954d865adbf7513359dbe7c0a088bec21c757875053271f78b003f2442b42720dc31": "0x00000000000000000000000000000000000c44757374696e20204c65650b44757374696e204c65651768747470733a2f2f6269742e6c792f334f6d67517069001564757374696e4061737461722e6e6574776f726b00001140696d63727970746f687573746c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475df5a7f3c11bfadc2519ea66bb836e7ae7d3491feaa78a9f3ea413e94c386ab086580f208d31432": "0x00000000000000000000000000000000000a4c696564324865726f0e416e6472657720546f6d6c696e0000126177746d61696e40676d61696c2e636f6d00000b404c696564324865726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475e1678efd9c765a8255ea05ae1ce1c34195681672bdb31e2b8bf9b5d39a3f22a84191d40953dd20": "0x0000000000000000000000000000000000064b75674d6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475e225b4667968a73461d66688269f501b405d7c0ffff6b767f705c5057a833d7ff7749cbfee384b": "0x00000000000000000000000000000000000f4d65746150617263656c2e636f6d0b4d65746150617263656c0f4d65746150617263656c2e636f6d000000000c404d65746150617263656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475e3c5fb2fc81969a22ae2f665befd20682d417e794ee4836e534dab09632319e7e0fa66537cab16": "0x04000000000200000000000000000000000000000000124e65774f6d65676156616c696461746f720000154063656c726973656e3a6d61747269782e6f72671363656c726973656e40676d61696c2e636f6d00000b404e65774f6d65676135000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471475fc0cc738d3f7c5e8ceea4a5b67c6502a4d1da2b7f2c09498bb0584b6410d0dda3e242748635f4d": "0x0000000000000000000000000000000000054d6f4844054d6f686400001672617a6974616a3130313140676d61696c2e636f6d000009405370756e6b4d6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714761bdb16cf74a422cc1653dc9247ac12fc2c0dd939ef12fdadd7d244e74b0975be811e4843f35352": "0x00000000000000000000000000000000000476697109566963746f72696100001376697175652e767a40676d61696c2e636f6d000008407669715f767a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714762278ddd7f9d2fe420ae612725091be044c1275af4ac86541f24a1848edb4c357b36b816839da09": "0x00000000000000000000000000000000001556616c656e74696e65204b69746368656e7a6b79002168747470733a2f2f696e7374616772616d2e636f6d2f6b69746368656e7a6b79001761656f6e7765626563616d6540676d61696c2e636f6d00000c406b69746368656e7a6b79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476436269fe98c06f8453d0ccb4af13c4b487ae02866867342e2fe6fe124c430824f583ddcb7e9e59": "0x00000000000000000000000000000000000d53616e676f2058616e676f201054616e6e6572204a61636f6273656e00001c74616e6e65726a61636f6273656e34303940676d61696c2e636f6d00000f4053616e676f3234393331363937000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476552190c60e7f90a0495a650d73c54c563ad571868583a27e8b209f2f2f4cc31c67f332cc331769": "0x000000000000000000000000000000000003626400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714765a1861cae96efbeaedc22b9e782d9d4d40aa5f1f3e4de97fb3268e30d0de993a03bc65359d8c1c": "0x00000000000000000000000000000000000a616e6e61206168686100147777772e616e6e617361676164696e2e636f6d0018616e6e612e7361676164696e6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714765f38af2758527ade93f42cc38c7609e349ca89bb1480dbd59541afc27c843526c5a3fde0fc8c37": "0x00000000000000000000000000000000000e3648414f53206f66506865656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147661b26815a3370c9ef2c74b5a6820a16eb04205a9d177c4244a94cdcfe1275039ef8704480a3905": "0x040000000002000000000000000000000000000000000763796265724700001440786379626572673a6d61747269782e6f726712383876676b383840676d61696c2e636f6d00000f4076616479686f646c6572373737000c637962657247233438383900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714767231bfd9d9921676d33240f4b328bb3536f2f5f43ecafbeb3694a7e25598d81bba69ce69506168": "0x00000000000000000000000000000000000a436865756b204e616d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147680539dbbaf0658cecae006fbf10a81337d87455340ce6112b125a971482490e02d75a27bb2c33c": "0x04000000000200000000000000000000000000000000064561726e58000017406561726e787374616b653a6d61747269782e6f7267166561726e782e7374616b6540676d61696c2e636f6d00000c404561726e785374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147698861f374eefe70ce1cdf8f0c7f65b38b034bbd62a2c51eb4f02bcf4ce6691c01ad2f50bb01841": "0x0000000000000000000000000000000000094d6f6b756a65616e0000000000000a406d6f6b756a65616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476a3455700cb811448f31778f2cd7b542127a81c6399a5dc333c691cda16418ce9dcf2023d3b230a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476ad7533e77fcf9ee4d08b1a297dde589fa652c4e340037e5108c7e7fd7fb94631e02cc5602e5a4f": "0x00000000000000000000000000000000000867616c6572617300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476c091a5cfc0b569cc10aff3a4e5cf2f467d1ebcff68b3a06d432ef8bad605064fc88866429b7000": "0x000000000000000000000000000000000005416c657812416c6578616e647265204c6f6d62617264010114616c6f6d626172643340676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476d10d82508ddae096e24e9b5ab82dc275b82318a52cebed1cae3e25be096d5f288229b256359e43": "0x040000000002000000000000000000000000000000000b537769737320506f6f6c0000000000000c4053776973735f506f6f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476d4bdfcc3fd9b0f169844782440a77d789ef60cf8b4dca2caaffbdaef8842105e401a6628aebe11": "0x0000000000000000000000000000000000134a65666665727920426c6f636b4d616b657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476d8de28c15a8e696a51e7f4c64e59e468d49709561ab3d04062aebd5c0f297a491a8002f2a72250": "0x040100000002000000000000000000000000000000000a4a696d6d79204368750e436875204368756e204d696e671d68747470733a2f2f6d656469756d2e636f6d2f406a696d6d796368751f406a696d6d79636875303830373a6d61747269782e7061726974792e696f176a696d6d796368753038303740676d61696c2e636f6d00000f406a696d6d795f63687530383037000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476eef4ee4756ace55c00bdb5472e548ff2126b45ee064c8dc4a28ec22bacedde0b94ec691ca5d648": "0x040000000002000000000000000000000000000000000c416c78203220737461736800000016616c6578657940766f796e6974736b69792e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471476f257bc22f38143849b3cc4c3aa80841d99f834aeb0b204a65bf71c9ccd6577945e75188397554a": "0x0000000000000000000000000000000000096173656e7475726b0000001861686d65642e73656e7475726b40676d61696c2e636f6d00000a406173336e7475726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714772841a40326b32e5e7a3f7b33d6abe2f9510091af389384bb1ab14ab421c4b3bd6bcf795fd54873": "0x0000000000000000000000000000000000084e466d617263690000000000000c406d617263697061616e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714772b6dd134dbece18e428bc5c22f213b32118358403cf626ddeed283fa946889b5512e92eadd8a61": "0x00000000000000000000000000000000001359757269476969207c20524d524b2e6170700959757269204769691668747470733a2f2f7777772e726d726b2e6170702f0018797572692e6769726a616e736b6940726d726b2e61707000000a40797572695f676969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147736d72637ca5ab07af655360c0cf90fcb636adb5caa425cf3911b2707fa85a86ed8cf16e590d216": "0x00000000000000000000000000000000000a536572686920322e3000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714773dee8f55ce5355f6354361a43b2ac461373d645f232de95222e5a067e4dfae25752e1f5a92c855": "0x00000000000000000000000000000000000a566c6164696d6972530101010100000f40566c6164696d6972535f627463000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714773f55df525fa6d534ea169f0bbf6ab861377b3e9cc34e52ffa3f1674f887b71b14b32404221b135": "0x040000000002000000000000000000000000000000000a73656279747a6130350000164073656279747a6130353a6d61747269782e6f72670000000b4073656279747a613035000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714774da64b663dd7d90eedf5b5991e93ca6682d493f8684926b6b63234410e1486ab77d2f32c0d997c": "0x000000000000000000000000000000000004676b320c4761746f724b6f72707332000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714774e798df2f721b6945e3aeeed6199fd8d6847051b2a2d934dc9829eedaa45cec70271e37403d050": "0x000000000000000000000000000000000010444543454e5420504152544e45525314446563656e7420506172746e657273204c74641868747470733a2f2f646563656e742e706172746e657273000000001040646563656e74706172746e657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147775da760598d092885ba76f4524bc17e5b1bfa2a4adf9b232fb8fa878637d8a9a9fe9ab8de2db4d": "0x00000000000000000000000000000000000847616d6544414f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147784c0640018c813102e184cab1726546391446bfb60b78b2fa78a927f7bf2bd4a734cfeb62c8909": "0x040100000002000000000000000000000000000000000d444953432d534f46542d31300e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714778e5b823e917c204e1b7df1c25a717adfd14ac5b1c65729320a22679677aaa76a874481fb47e140": "0x0000000000000000000000000000000000054f7365720aed95b4eb8f8bec9db4000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477a8f518e90d0d2cbe1c8831d018fed582688b5e75be3c9983ac1761fb24a916451c6999c0c66f5e": "0x00000000000000000000000000000000000a73796e636c75622d320a53796e636c75622d32000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477aa5087f8d73da5f298ab8705f9d69a9955907f011b1d7eb853967859fcc6065deb0b2152f99b2f": "0x040000000002000000000000000000000000000000000a677265676f7269757300001b40677265676f7269757370657472693a6d61747269782e6f72671b677265676f72697573706574726940686f746d61696c2e636f6d000011406269616e6361696e74686563697479000967726567676c612e00", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477ad80c392d951980a16d6fd4dc2954c449699e5f6e3c7d2f0dc64df5b8008135fd60eb3eac61e6f": "0x040000000002000000000000000000000000000000000c7733636f696e73202f20320c7733636f696e73202f2032000010696e666f407733636f696e732e696f00000c407733636f696e735f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477b2306d55618a8bdaf9e258248303362ed9d0b45920e6dc07a1bfafd053c4b7a345340fd4bd9357": "0x00000000000000000000000000000000000b77656e6d696e747369720b77656e6d696e747369720e6d6f7573652d64616f2e636f6d001577656e6d696e7473697240676d69616c2e636f6d00000c4077656e6d696e74736972000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477b87309f6cae82ef455298acb3f8ea6f9d027b7c64a09fa48e70e793797ab0671a65fde287ef917": "0x0000000000000000000000000000000000115a657573205468652042756c6c646f6704524e44000014726e646c763230323140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477ba939f01b84a579c498e54dc6d09282842bd6c3d6add63c626b0838149004d3fe55df18467424a": "0x00000000000000000000000000000000000f4b7573616d6120596f204d616d610000000000000b40686564766f7963657a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477e7c81b688e86ab38a7ddb36feebd8be00186f38273c7b9c0f3415d0dbcf9425af23baa7e86454e": "0x0000000000000000000000000000000000000000000000000f403038324b7573616d616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477ef359c63039c607a7a5f759444657faa370e0c7648ea82b7de38d94095646afa9889dff83a2b3b": "0x00000000000000000000000000000000000672313076340464616e00001364616e2e3130763440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471477fd1e387545e3290a84cc0f8014ad2583df5d2a0298128a8096160a1303b5700785e59acebe4f06": "0x000000000000000000000000000000000007503474746f6e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478002396ad151eccf413237f470027cfdcbad3f3ec8a4bd0eeae013767ba226d4b8ed4e422e61f01": "0x00000000000000000000000000000000000f706f6c6b617263686e6f6d69637300000019617263686e6f6d6963734070726f746f6e6d61696c2e636800000c40617263686e6f6d696373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147803fd5293bb10b7f40a5105916d3b2e8d8dbc33dd65990b50002d116e41833ce2fa96c8619f7229": "0x0000000000000000000000000000000000065061756c420b5061756c204272617475010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714781495c979b2e4523a4ac0daf927a452ba14109b8e0c334aad8f0d2d2fe2605346eb14c4745f4f5b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478255621fd0ac553544ff9f7dd373ef4057deaae18a4cac212e8ab6c3ddd696af9b6f945c1336e08": "0x0000000000000000000000000000000000094f6a6f6669726d650a4f6a6f204669726d650000136f6a6f6669726d6540676d61696c2e636f6d00000a406f6a6f6669726d65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714782e7be4e56dc7e9ae963c00a7c164fce3f4a8ed94ba0a87e83cc1a7b192726836819cf1f63c522b": "0x0801000000020400000002000000000000000000000000000000001356616c6964436861696e73204b7573616d61001868747470733a2f2f76616c6964636861696e732e6e6574154063673135383335363a6d61747269782e6f72671668656c6c6f4076616c6964636861696e732e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478331d8cc49f0ef276f45a1045fe47a639befe802be7eeea599080222e2f45fba46492039609cc07": "0x040000000002000000000000000000000000000000000ff09f95b454555845444ff09f95b400001a407475785f696e5f74757865646f3a6d61747269782e6f72671774757865646f2d77686974654070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147839058a91da35f1a263c8ff41827b72b0e7c7f2dddf460cf61bd57cabe37e1936ac5451452c8119": "0x00000000000000000000000000000000000e506f6c732061206c276572612000000017706f6c73616c65726140747574616e6f74612e636f6d00000b40706f6c73616c657261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478401030f0261c10a49deb88afa394b7eb478483a65a8c8f060b7de319dc6f65776a84d9e8f40e7e": "0x040000000002000000000000000000000000000000000e56414c4944414e44554d2e494f00001e4076616c6964616e64756d2e696f2e6c65653a6d61747269782e6f72671c76616c6964616e64756d2e696f2e6c656540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147842c8fa2321f1331c8631eed8177ca1e36107697b82afdcdc5ca1a3221796e8e614f3a6fee09c3c": "0x040000000002000000000000000000000000000000000964616c6d61444f5400000018726f686974726168656c34383540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147844550bde08fe13c40c37aeda337a3d84628534a349c778f4718fb9f6e6c5f0c9bdca2b5e44fd49": "0x00000000000000000000000000000000000d466c697061636164616272610e466c6970204163616461627261000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714785d8583e9b989bc9ca9b80f86dcc4755225a09c681b3f26f8726727be13e22edce6d9606f90c605": "0x00000000000000000000000000000000000e73686974697362696774696d650a44616e204261756572000015626175657264616e353340676d61696c2e636f6d00000f4073686974697362696774696d65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147866877cb9f3ebb8002112fe63749d3925cc0f36c9440450f21fe76c46a36e5b3343bf47d8c27400": "0x04000000000200000000000000000000000000000000054e696b300000144073616368696b303a6d61747269782e6f72671c73616368696b6f2e76616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478793b4db20d123c8e111a2e445cc0f64b5809496887b3130718d969db6637c0ebf1118c39b15c55": "0x040000000002000000000000000000000000000000000c7733636f696e73202f20310c7733636f696e73202f2031000010696e666f407733636f696e732e696f00000c407733636f696e735f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147883a128c175fcda5c7c138d8c7e2fa8a340509d00abee2e593ee159d44aaed005e6cd715fc3a962": "0x000000000000000000000000000000000005f09f908901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714788ce32e00a517a71a6704e77a51c290fd77bc04c40e080df04cbe0d05c6153809e315bb6aba2f7c": "0x00000000000000000000000000000000000f53706163657273206d696e74657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478a36b37e7c8a45b4c676770b34941cb7911f0ae00880839f51ad31da8c0eb3703b10f37e6ec461e": "0x000000000000000000000000000000000009417175615461696c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478bdc0755cc0041a684d341d7bd4328296ef486454ae52c31e38b1420d509d66e34a473ce15c4914": "0x00000000000000000000000000000000000d56657865644f7374726963680000001756657865644f737472696368407961686f6f2e636f6d00000e4056657865644f737472696368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478db62c47c6f528d0a4713b1197cab2fc64ebc8f1f65b3c6d76a8e64d13d61a4e7e6d26018fbb8ab": "0x00000000000000000000000000000000000c474d6f724469652044414f00000011696e666f40676d6f726469652e636f6d00000a40476d4f724469655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478dc64ae118a61a2b80adab283f96e115f1bcc05211dd11e75ffa4257dcc33cf704d019606094739": "0x0000000000000000000000000000000000066c75636961066c756369610e7068616c612e6e6574776f726b08406469656f683b00000007406965686575000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478edf2d109908df4067f9883bbb39d48af456babb990409e10567c251c7237cb8709b56a7ec5786b": "0x00000000000000000000000000000000000963617272797765620d6b6920686f756e672068616e00001465636f2e6b6868616e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471478fa03421f9ba61e726ef17b500f436cf596935acac782c71a423d35a959f3e6831f13c34db9d71d": "0x0800000000020100000006000000000000000000000000000000000a58796c6f44726f6e650000001978796c6f64726f6e654070726f746f6e6d61696c2e636f6d00000b4058796c6f44726f6e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714790543fc3e74b681e0f527663883fadc99963738cc81dd244d866241b296cb6d54596c296170534b": "0x00000000000000000000000000000000000f4573706163696f2043726970746f0f4573706163696f2043726970746f0000196162726168616d406573706163696f63726970746f2e696f00000f406573706163696f63726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714790d9013966da8e5aa586da0f7eb3da5b7ec7dfc89be91b6ec1ed7fd82aab54aebb6d71423080868": "0x0000000000000000000000000000000000087061736375696e00000011702e6272756e407061706572732e6368000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714792c8b74a404b20220e6f95ce6c0d08f1578ea375de14bbf04d449cf817c1b0b576edd00add11d5e": "0x000000000000000000000000000000000006426c696e6b0000000000000a404b534d426c696e6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714792db7b2b1e449a2d0c696806e3f6020040241eefddbbbb6ef5bf870f4c77feaac4775d26e7a662c": "0x04040000000100902f500900000000000000000000000000000000000000000000000000000009706f6c6b61646f74085472616c646f740000116a677472616c40676d61696c2e636f6d000008406a677472616c000a7472616c5f6c656c6500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714792e04f3dda19263a61514d5cabf81b3f62650806870ad83b2e5059538b846b6dd9963e010566a17": "0x040000000002000000000000000000000000000000000a504f535448554d414e0a504f535448554d414e1b68747470733a2f2f706f737468756d616e2e6469676974616c2f204076616c696461746f725f706f737468756d616e3a6d61747269782e6f726719762e706f6e696d616a757368696a40676d61696c2e636f6d00000f40706f737468756d616e5f647673000f616e74726f706f636f736d69737400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479400eb594b6cde92ac4cde57f9b59d92a58b75a696fc7c8f23f63f0e507145f1d0ef3413a0a4255": "0x0000000000000000000000000000000000104e6962626c652062697473204b534d0c4e6962626c6520626974730000196e6962626c65626974732e61727440676d61696c2e636f6d00000d406e6962626c655f62697473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714794c7db721956af68a56b1da8dc3f4bd58630c15f5754ee634528a007ab510c86a7e1fe6e62f4166": "0x040100000002000000000000000000000000000000000a414c46415354414b45001668747470733a2f2f616c66617374616b652e636f6d0010616c66617374616b6540706d2e6d6500000b40416c66615374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714795234d3f309d6d928806960ed2b5fe0085bf2a7119dfa7d5aafa82cd6a4c13ba365e6f60b351e2b": "0x00000000000000000000000000000000000d4a616e6973205069706172730d4a616e6973205069706172731f7777772e696e7374616772616d2e636f6d2f6a616e69737069706172732f0018706970617273666f726576657240676d61696c2e636f6d00000e407069706172735f6a616e6973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479585c82582ba5886c8f9ce90ef15bbb188d6b310bf351d0ab7db5b56ad0c612a2f59faef49ad307": "0x000000000000000000000000000000000009766f6c7465726f6e0d456463656c20426572696e6718766f6c7465726f6e2e61727473746174696f6e2e636f6d0017656463656c2e626572696e6740676d61696c2e636f6d00000c40766f6c7465726f6e3364000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714796a244fdb685192402f9f91c708b2f2bce4117ced908fcc3d2627b9f49cab6eda2aa0466800d90b": "0x040000000002000000000000000000000000000000000b4541524e535441534833001668747470733a2f2f6561726e73746173682e636f6d001367726f77406561726e73746173682e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714798bc3485a0137f5de4a268c87586c0396cd8a46f0bcffd0229bd1075894df86d3c95193b27efc2e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714798f3d8958aea0ecce17aeb93e8c317b03168d3459ad0214f0ab47d844d7b22033b79d8e45508c04": "0x04000000000200000000000000000000000000000000154c6f6e67204e65636b2056616c69646174696f6e0000000000000a40626f6c696b617465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479ab4299c1df4149c2ed7fff877c4b79589f9716c09946592ff894a011fd5f462b3e0517f1bd562c": "0x0000000000000000000000000000000000174368616f73204269726473204172742053747564696f0000000000000c4042697264734368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479bca3c1ed2e66e5daca1f54b717110efd2c4ddba6a4a2af7794a66a38bac564e2eb93a627bfec1a": "0x00000000000000000000000000000000000441737504417375010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479e65a55eba330a3ba169058d0c44fb1c127201307004ea2f54930043ac06a7ee0fc6a2e2293b329": "0x00000000000000000000000000000000000749534142454c0000001a63727970746f737562694070726f746f6e6d61696c2e636f6d00000d40737573755f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479f44e04fbf309e0e8ba1059e1e856708fda311f1e008afeff98f61978b96740f4b566bf29f32352": "0x00000000000000000000000000000000000a6d6f757365363439320968656c6c206e6168000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471479fd3f4b616af04ea62f28c78bc6e6f0fa30808f5c8f203a4881c77fb732a00089fde9ad87ded73d": "0x0000000000000000000000000000000000085348494b4f4241094164656d205a6f72000019706c616e6574616c6d616e61634069636c6f75642e636f6d000010405348494b4f42415348494b4f4241000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a0fd3be900ddd6b0a7ac5be69a8243f8880d5fd015b2e8f8f30ce6c7162f8bcb5ad1a1fa4246d32": "0x040100000002000000000000000000000000000000000b426c6f636b736861726410426c6f636b736861726420476d62481668747470733a2f2f626c6f636b73686172642e696f001468656c6c6f40626c6f636b73686172642e696f00000d40626c6f636b736861726431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a246b025078730ed4fa8184e7ea69dbb3cbee71cfd7490803d457140d5d57d0e53a49a887bc4a06": "0x00000000000000000000000000000000000c6578706563746368616f73054769616e2168747470733a2f2f6c656e737465722e78797a2f752f65787063746368616f73011a65787063746368616f734070726f746f6e6d61696c2e636f6d00000c4065787063746368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a2939f6c5b0bc2542a463a7a8813a1272eb8605af0c83660ce65b57d3d5f85ffa5eeff31793ad21": "0x040100000002000000000000000000000000000000000a416374697661746f7200001a40616374697661746f726e6f64653a6d61747269782e6f726718416374697661746f726e6f646540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a3a19d147ea88111e0df3bee6fe15fd9bda70092476cf116506064e04aa9388bfb5cc95fe9a7836": "0x000000000000000000000000000000000007636861726c7903435200000000000b40435261796761737365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a44a3d1b39b54493692082b41c6f2cad15ba58a7c962c2f435ec4e6638aedb2c851a90bd4f03f11": "0x040100000002000000000000000000000000000000001a6e2d667573652056616c696461746f722023312053746173680c6e2d6675736520476d62481668747470733a2f2f7777772e6e2d667573652e636f154076616e74686f6d653a6d61747269782e6f72671563727970746f2d6f7073406e2d667573652e636f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a5bd17ec506c9c5d2365c4c6c0e812a77aabfb804bf75ece6c010669c21fcff48edf5208a3e3a63": "0x0000000000000000000000000000000000076b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a87c1a545342f8db6f53125f95e71a35535efc16d86142bb9547ee9e24abc8e74fdcef0b078ce50": "0x00000000000000000000000000000000000864656e697378660644656e697301010100000a404446656c74616e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a8cdcdb01c0984188e5872b9f167067f4643d21128ebcebd8a017e601055451432503af1703cd7a": "0x00000000000000000000000000000000000b487970657220436c75620000001a68797065726c6f636b6564636c756240676d61696c2e636f6d0000104048797065725f436c75625f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147a98a4b9eacb17aeaa77918b3029d54685efa54738d2dfb3a172cdddf800b7bb1189e1717220e472": "0x00000000000000000000000000000000000a496e65666661626c6501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147aab7b06334f0de4562ff43de6459fe64e03e965644c3ae5aa94d383c6eeeddfe96a85777d196603": "0x000000000000000000000000000000000005534841510553484151000011736861712e696e74406c6973742e727500000c40534841515f5457495454000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147abcdd59281433e90a5cc2047a1215e4758a0cbfc07d10b287327c0929e780d7be8642874c4b7606": "0x00000000000000000000000000000000000a79615f616d61726f6b1159616e61204e65766f646e696368656b00001a79616e616e65766f646e696368656b40676d61696c2e636f6d00000c4079616e615f6e65766f64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ac654eefb24124154af43ebc6cea9969e01ad1cdb66b1d82c291f1aab334cb3f854f67ad68a9a26": "0x00000000000000000000000000000000000c47686f7374204167656e740000000000000f4047686f73744167656e745f4f47000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147afcd22bd458c5e66aa7f16d0ce7a6288dd1d2f1779fafb18d4c60ee78e89ab3dd3bc0979aad386e": "0x040000000002000000000000000000000000000000001b4d61726b65744163726f73732d426c6f636b4275696c6465727300001c406d61726b65746163726f73735f62623a6d61747269782e6f7267196d61726b65746163726f7373626240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b2722eb6380c719b4b2436a2db80368af17fb8a41e3895f3e1ae305d705eda24a60e20ee5055e02": "0x00000000000000000000000000000000000b457265626f73303530360000000000000c40657265626f7330353036000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b2a45dd87ad9b19a6ad826eb856ef28698449bf4103a10f62f5f20ed4604ea2c1c62068cb26200e": "0x00000000000000000000000000000000000006416c696e61000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b35d7021f4bbfded244ce5d458028ab10f9ba6eef01fda2953990aec9f433c2badd94d982918e0a": "0x000000000000000000000000000000000009444f546e4441534809444f546e4441534800001b646f746e64617368617274776f726b7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b3c1c60afa16946d463b40af00de0a725978a340e77acec44981702cb83d3f6b7eba082effe333d": "0x040000000002000000000000000000000000000000000b4b534d2057616c6c65740000000000000c404554585f43727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b695b311c79a7fc5ab511f883a11f02c9af8054b409f4878f98b04f7cb9eba289b8a0297d79173c": "0x0000000000000000000000000000000000074c65737465720000000000000e406c5f776f6f64666f72657374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147b85696876ff480a6e72261b4e3c4405420177b2d56a579337eca2fb61e849a66ae35be7b0f0cf02": "0x04050000000200000000000000000000000000000000104b616e6973686b612052616a707574106b616e6973686b612072616a70757400001d6b616e6973686b613633393372616a70757440676d61696c2e636f6d00000c4b616e6973686b6152646a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ba630360149afeb56e9233d9889e00e3c03f1cc20dd23c0dab8ea23e5b60fc423b0e631f2a19b47": "0x00000000000000000000000000000000000d434f4c4c41544f52532e494f001568747470733a2f2f636f6c6c61746f72732e696f0015636f6e7461637440636f6c6c61746f72732e696f00000d40436f6c6c61746f7273696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bb29bc9d1b02b887063da8fb9f496867aaed0e760ed9866ce51c4e91dd7e4a341f9af7086f08c34": "0x00000000000000000000000000000000000e5061772d6665637420506177730e5061772d66656374205061777300001770617774726169742e6e667440676d61696c2e636f6d0000104050617766656374506177734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bbbb302ea3c73fd6a1e7cf7558378809fa376f7eec7b065d30759f8a4e7b721ec2ae74b313f0855": "0x0400000000020000000000000000000000000000000015616e6472656974612d76616c696461746f722d3000001540616e6472656974613a6d61747269782e6f72671b616e64726561662e7370657a69616c6540676d61696c2e636f6d00001140616e64726561667370657a69616c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bc80f4306d5529f7a54e6a55c0453407909789a06c3ee6719f8735ac370d6f17dc342717fd76819": "0x040000000002000000000000000000000000000000000b5374616b6520506c7573000016407374616b65706c75733a6d61747269782e6f726713636f6e74616374407374616b652e706c7573000011405374616b65506c757343727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bd011e2b24427fd3ac61927f22210f94e610302612161d8b654db31a59babe728e48c3365313440": "0x000000000000000000000000000000000005426c6f6200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bf2c0491ddcbed34e908afcf0fb6b394bd1a043bc8b226fac33b4742731b9cde5d324f450eb3006": "0x0400000000020000000000000000000000000000000018454c444f5241444f2d544543484e4f4c4f47592e6e6574002068747470733a2f2f656c646f7261646f2d746563686e6f6c6f67792e6e657415407061756c2d6769653a6d61747269782e6f72671d7061756c40656c646f7261646f2d746563686e6f6c6f67792e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147bf3bd886ed78f2a3e01274f4de899bd98847d7bb544371503102f4d5a201aae95187cb850f4ad2d": "0x00000000000000000000000000000000001072617269736b617465626f6172647301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c042a4fb9dbabf496bb0203d41e1ba3170850ee862f64c451b09159d9344d10b641feed65d30162": "0x0000000000000000000000000000000000086d617263616d790000000000000a406d617263616d7931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c1466766d8e06522ce1929ab903f695bdeeeb79a588774d71468362129136f1b7f7b31a32958f98": "0x040000000002000000000000000000000000000000000d696e636861696e776f726b7300127777772e696e636861696e2e776f726b7316406461667269636173683a6d61747269782e6f726716636f6e7461637440696e636861696e2e776f726b73000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c1a4ee18bd3983f5262b0fe348437cc140f47a9fd3818787fc5b72fdbf2a79693b599d464416f7d": "0x00000000000000000000000000000000000a426c61636b7374617200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c1bddbb2e7b2b75a85040fb4858bb0af5be5d20833d58a0b093c35927090deed8a2a6ec8ca95d4b": "0x00000000000000000000000000000000000a506f6c6b614b696e6701010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c1f3ea8d8d889e4aa6716504b6e349996c6b7d6832a2103f48fcf53ead6a647a36af9eee8ad6733": "0x00000000000000000000000000000000000e46726964612047616c6c6572790853414e4354554d000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c24fdc8783352eda417107f4162f22d0f8d00f4d4498216cb35682c90240b59ef80a93d6018d520": "0x00000000000000000000000000000000000f506f6c6b61646f7420576f726c640f506f6c6b61646f7420576f726c640000167465616d40706f6c6b61646f74776f726c642e657300001040706f6c6b61646f745f776f726c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c2fabb1c3a36f8f280a78e265cd8a5274321bf5d0036e20ec9aa7e145667fce26f6e774c2516773": "0x00000000000000000000000000000000000c43727970746f4a6f65323300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c35760e1493bdc39244b39ea5a40c289a1bae88df2aafb1c7024e53a8ba9924065aace7b5f17d1a": "0x0000000000000000000000000000000000096d61756e616b656100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c36ab3c7817f712728ea7cd638962b92ec6405e7b5572b67cfbc96c7c2fc7becf4cddb22b50b02c": "0x00000000000000000000000000000000000e4e6163696f6e2043727970746f07416c657820470000176e6163696f6e63727970746f40676d61696c2e636f6d00000f406e6163696f6e5f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c379f62304c02a738bf717e43124f5679168a3ab1ef2490662f9b08508c5328786ea7c8fda2d72e": "0x00000000000000000000000000000000001242756c6c69736820e382ade38383e383890e444d20666f72206f666665727300000000000f4062756c6c6973687468656b6964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c55d4e4996a81667670dd46299698281a6d0034fdd5484979f6f96ecb0f181e96442387fd1bf831": "0x00000000000000000000000000000000000b5346522053747564696f0000000000000d405346525f5f53747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c7bec710790ac95948ce1d407b5915c413f1b4813162a9782bacedbff9bf43844df10e5612a4d33": "0x0000000000000000000000000000000000046b6f7401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c898863ee64a53fd0fcf4956cda58392e1602fa60d6bcb408356ad853287beaa4c33962b6440f20": "0x00000000000000000000000000000000000d72616e646f6d626973686f70001d68747470733a2f2f7777772e64617461736369656e63652e6172742f000000000e4072616e646f6d626973686f70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c9b151305dcded7e26969331bf77ce04768009026a5362d51e5bccc12f788b8cda2a43ef218bd04": "0x040000000002000000000000000000000000000000001856462056616c6964696572756e6720f09f87a9f09f87aa001b68747470733a2f2f7777772e76616c6964696572756e672e63630017636f6e746163744076616c6964696572756e672e6363000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147c9e204de64a64fe366850fd0d31d0261237699990f450e0b2cb41cfc4ec7b2ca6ebb7b0435d3654": "0x000000000000000000000000000000000005526f6d610f526f6d616e204368657265706f761f68747470733a2f2f726f617274692e61727473746174696f6e2e636f6d2f0013636865726f6d383140676d61696c2e636f6d00000e40526f6d613633323032343630000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147cb3d8e166e9bea1044e495ecbfe9e4a4c436b753e3bd41b0249e45e7210ae7caa5e7bce20671e6d": "0x000000000000000000000000000000000009646170686f6d696e00000013646170686f6d696e40676d61696c2e636f6d00000a40646170686f6d696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147cc6f5d138fccd7c32c57d0d50eea3e0561d15d28ffded023d7ea2489499d39ffd20c07bbbd11732": "0x000000000000000000000000000000000008486c616464696e0000000000000d40686c616464696e73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ccb553670cc1be59a9407f791aa5535102209c0d7c89f97f52f0f40b3091f672c5141aa11801f59": "0x00000000000000000000000000000000000a506176656c204b534d17506176656c204e696b6f6c616576204b72617374657600000000000e404b727573746576506176656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ce1a23eb5655e8050c8d2fdc12aabf21a31c0f6812cc0e7525597972ca0a37ab9bcef9f51650811": "0x040000000002000000000000000000000000000000000846524545444f4d00001b40636f6e6e65637465636f6e6f6d793a6d61747269782e6f72670000001040636f6e6e65637465636f6e6f6d79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ce6fa220b1f0d1ba06446b3474c3d9dcfb759f3df134cf4b6620b2559c4e1b99d3be4d010378f40": "0x040000000002000000000000000000000000000000000a5354414b452d4f5053000011406876616c3a6d61747269782e6f7267147374616b65726f707340676d61696c2e636f6d00000a407374616b656f7073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ce77bdfc2d91a1e54e20840d041d6626327c3ee6c0555e991b4e893e6b998f269bc85f1a7503f1a": "0x000000000000000000000000000000000006556e646572001968747470733a2f2f686f6c796368656573652e7370616365000000000f40556e6465726772617068696373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d13ee9b5b531cc24ea378f0cd9285451e51e00c2e68851a57a36662990baa9226ab5c7734e05737": "0x0000000000000000000000000000000000065350414345054e4153411168747470733a2f2f6e6173612e676f76000e696e666f406e6173612e676f76000006404e415341000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d26f412c600f65a48745d28d9e9596ca41b7f7bcb03f874757f4f0716a7237e566662a6393bc125": "0x040000000002000000000000000000000000000000000852686f6d627573000000146b656c6d616e6d6d6540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d2dd084386fd77b18cf1686419c41dc5d3e76d373e3176c32c6d23c755fe1fc357f9c755ffc0019": "0x04000000000200000000000000000000000000000000075374616b696e000014406564776172646c3a6d61747269782e6f72671168656c6c6f407374616b696e2e636f6d000010405374616b696e4f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d363e805ca7dc102e6dde560aa0f00b08d0db5e3c2f199181be3ca53d2e7a0a742aa5692433060d": "0x000000000000000000000000000000000010446553746f72655f4e6574776f726b214b6f747a7572204d6172696e6520496e647573747269657320507479204c74641968747470733a2f2f646573746f72652e6e6574776f726b2f19406a6f736961686b6f747a75723a6d61747269782e6f7267186a6f736961686b6f747a75723340676d61696c2e636f6d00001140646573746f72655f6e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d3aabffb2e14c3d20dffa395a3019c0f32205ada0abe3d79389a209a7ec31e53ff55ebdeddff46d": "0x00000000000000000000000000000000000d466f756e646174696f6e2e5801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d3c67d22eef172a8c20d46f86242eea89c400d5c478207e05c76bbab29a748af8aac90d627e1a01": "0x040100000002000000000000000000000000000000001256616c696461746f72732e4f6e6c696e65001b68747470733a2f2f76616c696461746f72732e6f6e6c696e652f000000000d4056616c696461746f72734f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d411dcb862ed4531294b53cb96f295c8920789005ffe63ce3a3b02d8bd7591fdcac8cfd50ccae11": "0x00000000000000000000000000000000000c436f6c6c656374696f6e5a0000000000000c407261696e626f776e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d44fe16767b62f23c52ad5876acd95595414a3e1c47afc410f9cc28db853b2f024dfec10d8bbd4f": "0x0400000000020000000000000000000000000000000016416e7469205374616b65205374616b6520436c7562001c68747470733a2f2f616e74697374616b652e6769746875622e696f001d616e74697374616b657374616b65636c756240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d4bc48ac25c63f1a68d2023d2a06f5042d7b2a268a330c38732d209b07bca2802ee241952235210": "0x000000000000000000000000000000000007436f74746f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d616786735a0c05f27568417dfb3873918d1e4316450de4e3af810622b72e9931863c31ed854f5a": "0x000000000000000000000000000000000015e284a2c39fc3b8c3b8c2b6c2abc3b8c3b8e284a200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d647315c276b2ad56baa9b15ae335e108f3a6a84c2f6c8ddcea0a96477fefe9f5670a819802116b": "0x0000000000000000000000000000000000094269484f444c203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d6816787a83cc6cccb149c0e1f585be4511d6f942de360c39827f904cbdb9a8c572d580a8b95f0e": "0x040000000002000000000000000000000000000000000a736572676579303037000016407365726765793639363a6d61747269782e6f72671a706f7461706f76736572676569383640676d61696c2e636f6d00000a40736f6c73615f736100087373613131313200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d73ff709d9ae6a4d53c9c6e61431448ceef1eb49542ddee942dd3d6c81c19d53efbab8acb02f00f": "0x0800000000020100000002000000000000000000000000000000000f426c6f636b7365656b65722e696f001768747470733a2f2f626c6f636b7365656b65722e696f1b40626c6f636b7365656b65722e696f3a6d61747269782e6f7267166b7573616d6140626c6f636b7365656b65722e696f00001040626c6f636b7365656b65725f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d76b3fc859618eb1a41e8f79310cf5b804b038d19f28b535261fc5c1c3d1dcfdc49e6bf5a946d32": "0x04000000000200000000000000000000000000000000067a7a4265710000001466726f7a656e67756b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147d8fa5989cce248be07628deaa9c6fbbf2288f879396ff3566871c0dbce85c9e23764d15b810657f": "0x00000000000000000000000000000000001e44616564616c7573202d205374616b696e6720466163696c6974696573011f68747470733a2f2f7374616b696e67666163696c69746965732e636f6d2f001b696e666f407374616b696e67666163696c69746965732e636f6d00000c407374616b696e67666163000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147da4d6e045faa8163a731ac0ae7375a2cce5b504484d91f1c49923b3425072e36e12b0afd5f2a857": "0x040100000002000000000000000000000000000000001542696e61727920486f6c64696e677320f09f92b01042696e61727920486f6c64696e67731d68747470733a2f2f7777772e62696e6172792e686f6c64696e67732f17407461636f747572746c653a6d61747269782e6f726715696e666f4062696e6172792e686f6c64696e67730000104062696e617279686f6c64696e6773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147db14798f78c92e409ed7dc92692f6d1b8bf5e71b68f9019a16f825e4eb71bb22c5bcbb9fec300d1": "0x040000000002000000000000000000000000000000000830786e3030627a0000144030786e3030627a3a6d61747269782e6f72670e30786e3030627a40706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147dc9a3488002e55b9ef65e3341a0a9e7e3b70c9af1ff1d6ee9e59567071bbf6f67940d5367532225": "0x00000000000000000000000000000000000c6c65616b65642d7a7330320c6c65616b65642d7a733032000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147dd1665541d4746a38753d84c52f2cf326a92899fc7113242a46879511684ef558436b2ce95d8a7f": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000b73697854686544617665001768747470733a2f2f736978746865646176652e6d652f124068657866663a6d61747269782e6f7267127369784063727970746f6374662e6f726700000c4073697854686544617665000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147dfe17f3928dd74c88480d4bfa9c9e6e217df08b61134f96a9f1b78713d3c56540d865296e530e0d": "0x00000000000000000000000000000000000d4d72204d616363686961746f0000000000000f404b696e674d616363686961746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e1d98e7b551be5a30fd1beaa72357f61ba1fe7e90aa8c5080fcd49b2c82e1b8315bcd9a223cbe41": "0x0400000000020000000000000000000000000000000014f09f909d2043525950544f424545532e58595a0000164063727970746f6265653a6d61747269782e6f72671e63727970746f2e6265657a7761784070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e2263555f112d23e0b27830a257252988efa5bf9d223ece5ce9eb120abe621bf5423deb2c3a8c67": "0x00000000000000000000000000000000000c496d6167696e6163696f6e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e5233edbec5e2e006e6492fc1524f365b7045cc047a7ecf6c1c2e147081f41b851219e4b1c5c245": "0x000000000000000000000000000000000009417374757254696301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e550986ce912ea7305fe17c669dd937d1ed23df884dafef2d92b970bcb8f043ab297a3ed8a2ab01": "0x00000000000000000000000000000000000a496e66696e6974456400000019656464795f6a61636f62733440686f746d61696c2e636f6d000011404564776172644a3838313236303637000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e5d5a07a968882aa81126ca612e86be5e697a772a636776495ebc044916218a1286f9031ab7c038": "0x000000000000000000000000000000000006525c44656306526f6d616e000017726f6d616e706f646f6c736b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e5dd4c385ce0fd8a810d21a048615e37979f5c5e4f8ec80853dcd1d961bf8c1a5d4048d034d151e": "0x000000000000000000000000000000000003585801010101000009404e465462795858000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147e869f600c42271970b2d516a4815cecf618133b7987a8362995b78ae48035a1643e4bce5ccc5d3f": "0x0000000000000000000000000000000000096a617a7a6c6f737400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ebcb68d19e2cb6d2ea8c3fc9696643972bb4d9af28b01fe9a7105b4530b337cbc31a2d3896b7025": "0x00000000000000000000000000000000000773616b614d75001e68747470733a2f2f646973636f72642e67672f7a71746d735932637758001573616b616d753230323240676d61696c2e636f6d00000c4062616467657262723073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ecc461d41cccd863b7bd97ef2fbe878b2a978258f73697519dbf246e00514930f04daa24602b1aa": "0x000000000000000000000000000000000010e6b19fe58d97e4b880e69e9de88ab1047858780000067840782e78000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ece2f2beb48f825300255e8ee286bf5f0e90134d2d24b212b644b4da71d243ff1885f8d972bc23a": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ed96b7d3f8a3e92083857fb5e068b7253110088fdc0431964252a7d2f46622d6b3cfc66be587c30": "0x0000000000000000000000000000000000085341544f53484900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ee646bfe72c5b3abcac4380e7aa66426d530f0cb21bb82d67ae68ab51c86a20c87cd0cdc185da36": "0x0000000000000000000000000000000000095075796f5075796f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147f34cefba02f9ae1b45943b4ed9825ec0f00a5d760c6fa50ac9cbe4f8d3aedcf807f8bf0bf6f5c0f": "0x000000000000000000000000000000000013536b794c616220436f72706f726174696f6e001868747470733a2f2f736b796c6162636f72702e6e65742f0017627573696e657373406b727970746f7666782e636f6d00000d40536b794c616273436f7270000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147f3a10eaa5404047e2fc99f3a3ab840d9097da913d9516ca82943e0c61efcf1eef379ec46ed01f1c": "0x00000000000000000000000000000000000a486f6f6b65724e46540000000000000b40486f6f6b65724e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147f8c60eec0cc4d652827816806c65a098eef53ff0b47b7ae84b811119ffb96d519bbef1402e07b32": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147f9e55d7623ce6876ae93e7162785a77d3a2c0413a9ee04af1b948ba5df9ac191552b72e1dd49b71": "0x0000000000000000000000000000000000064372616e65000000000000094030786372616e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147fa561eaceb076e25ad683920f3457b2599f4669eb42fdbea3b475b38f85fe6afd74203c6117ea1b": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147fbcd6b06fe4b789aaf84aa2cb81d84aa9c578081a5f107723eac3fa3af95df8d72e025840ffeb71": "0x00000000000000000000000000000000000c4173686c6f73654b736d310f417368204c6f7365204b736d20310000166173686c6f7365406d61696c66656e63652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147fe79549034d8b46a2e1685f62b2a1a996a2a1ba10ac6836c2b72174cab1bd1c6907454e6365fb70": "0x0000000000000000000000000000000000144b696e7473756769202f20496e7465726c61790e4b696e7473756769204c616273000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147fe8792204e9c295d0f95f0b6b0f3784199f064eb87e6230aba869addbe2898705673d06385f1179": "0x00000000000000000000000000000000000e4375656e7461434f4e594b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147fe9ee2c58e8b05db88f14766b6b332c755a2a08ffa22c4783a73ececa4062d64e24ff80c9165c5d": "0x040000000002000000000000000000000000000000000e49204c6f76652043726970746f0000001d63726970746f616c62657274627572676f7340676d61696c2e636f6d00000f40495f4c6f76655f43726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047147ffbd1415556c174eed8aa4c0f53370d2d6cea6c89603ba8155d80856e81ff4f45fc4eb4df8bd019": "0x00000000000000000000000000000000000b446172696162616e616e064461726961000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480060d7753f9b8d6680f824acef4a0bcd554d24e911c75f8453f4979a433016d521023d625ad5706": "0x00000000000000000000000000000000000977336e3a206a696d064a616d65730000136a706f686172613740676d61696c2e636f6d00000d4053747261774861744a696d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714803d5aecf59783b17628a5be63c4d3c8dbb96c2904b1a9682e02831a1af836c7efc808020b92fa63": "0x0400000000020000000000000000000000000000000006626b636872104261737469616e204bc3b663686572001140626b6368723a7061726974792e696f0f6b7573616d61406b6368722e646500000740626b636872000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480463187525d27801c22d9c0275c636dbd1efaedf149337a591a85423be5ee06e0b459bd7db75c32": "0x0000000000000000000000000000000000000000000000000a405369725f506c7835000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480728ec7d78ba2aa1cf7204d94b6e54fd231fddd65147458abc6350f084bb65d8417702c4d0c934f": "0x00000000000000000000000000000000000b70697462756c6c69736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148079574f18bbad18449df0c2eb08117322b4037a5dfac6b84385228492b377a1b6871791f344f357": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714808ebc416a42b5dad4dd0db36826124c944cd84245cec4db714bf5e22cd7354f06d855fb39e358ad": "0x040000000002000000000000000000000000000000000752616661656c0000124072616661656c3a70726976617a2e696f00000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480997bddfac735ca6e92c07e2a51a497bd1b6d9769dc3dd9342184b22cd903ad5bcfb1f5df973918": "0x000000000000000000000000000000000008536f6c4d696e650000000000000b40535f6f6c5f4d696e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480b33d9bdfb990d7ece16124407c7b88b0ef392c160d9ce49dc9f57d14ebf88ec1f5c0a8171d5a0a": "0x04000000000200000000000000000000000000000000055855414e000013407875616e39333a6d61747269782e6f72671b79616e676a696e677875616e6d61696c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480bb42a185021da0ee4ada127e6b71655f2b821dcef49b1b7a9c2c2533dd7bb686f6cf25d6a43c56": "0x00000000000000000000000000000000000f536f6e616c2042616e65726a656500000019736f6e616c2e62616e65726a696940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480c30a7cda5adab606ee04dbe5970b2babe888f787f22e17da71ae752427427611a869f8a71f2a70": "0x00000000000000000000000000000000000f4d656d65636f696e20436861696e0d4d656d65636f696e2e78797a1b68747470733a2f2f6d656d65636f696e636861696e2e636f6d2f0000000010404d656d65636f696e436861696e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480c3b8a059192b8fe0b174435a2214def3b876b9c695b812cb5b4f58de2948b76abee22c98a45445": "0x0000000000000000000000000000000000095461616b7769747a0000000f7461616b7769747a40706d2e6d6500000a405461616b7769747a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480c4e0efde12fff3981467bc43c55319c70cde08e341fe0629c34bd92bf3fcc25d33e7f990c22466": "0x000000000000000000000000000000000013445220537472616e67652053747564696f730a4452206a756e696f721f6c696e6b74722e65652f4b7573616d615f42697264735f41636164656d79001c6472737472616e676573747564696f733040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480e633d9b260415a7c504d6e49be15d262c72336d6cb5cb00c96471a168cf8bc5c9e5388d91be86b": "0x0000000000000000000000000000000000044d3244114d6174766979204d617473697075726100001d6d61747669792e6d6174736970757261313140676d61696c2e636f6d000010406d6174745f6d6174736970757261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471480f72a77b66dd393b36020ebe1f4954611d109e2badcd2e8aa7e104f43dd3b09d728f187894a32f1": "0x0000000000000000000000000000000000205350414e49534820434f4e54454e542026204556454e545320424f554e54590000001a626f756e7479656e657370616e6f6c40676d61696c2e636f6d00001140426f756e7479656e657370616e6f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714810a268051077a1deabf400732513443aec4f98d477ce3bea66725f271c496c8e52e7a6f5d6e2c4a": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30350e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714811067f8be6075ad60b5c072d3e0f45cfcb0fb99318f17c49fcc6bbbde23e392577a30d7bedd9f5b": "0x00000000000000000000000000000000000b506f6c6b612048617573001b68747470733a2f2f7777772e706f6c6b61686175732e636c75620000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481325f28f848ffe9a411987e278e1a1883853fcfb029d8a17c08f44880bfe2492473744de632e830": "0x0000000000000000000000000000000000076b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148132e691730eba14b6b5cd171f242e060b0d16566e21961dec966e34cb5cc667b08923b248c07749": "0x00000000000000000000000000000000000d416c696e61204c6f73657661001f68747470733a2f2f6c696e6b74722e65652f416c696e615f4c6f73657661001668656c6c6f40616c696e616c6f736576612e636f6d00000e40616c696e615f6c6f73657661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714813ba8ca144d6d26562427d438fcaac2c2be2b22bdec3d8c65b11048d013e77c0d4f21f7215a490a": "0x000000000000000000000000000000000006486f614c5800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148150bb2411acc76d1aee272e3633e036e6f22d4da4a65c844b515353161e8f7186b2c2e71e7b0a5f": "0x00000000000000000000000000000000001245636f4672616e6368697365732e636f6d0661646d696e1245636f4672616e6368697365732e636f6d001861646d696e4045636f4672616e6368697365732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714815938890f454d06be78a8a56ca63c88f3035d0dadea57cf12d42c7d8ef61795deec2dd98ca0393e": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33340f62696e616e63655f6b736d5f3334000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714815a863bd5bac191942f56470b01e3fb44288e85a90be6bacff225537a556eac4c61f25930284b66": "0x0000000000000000000000000000000000114361205465747261206f66506865656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481644b5c9a9a13e69a9ebf1328e64aac1cf749436ec602945693a088d0ffb823da08dff6bc4fd739": "0x040200000002000000000000000000000000000000000c52554259e2808bf09f928e00001240746174616e3a6d61747269782e6f7267166b7573616d612e6e6f646540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714816714a6c487ab8b56495460066a5fab4be4b0634c41f0e550f4f3e4d3436924364ce98d8678372d": "0x040000000002000000000000000000000000000000000a4578747261436f696e0000104079726e3a6d61747269782e6f7267187961726f6e736b694070726f746f6e6d61696c2e636f6d00000c406578747261636f696e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148173fc75c8868e7434c4c671dc3f4b52d14b36134e3ab9cb71580ad6130331b0e16aacecec396e75": "0x00000000000000000000000000000000000f6172696e61736d69726e6f7676610f4172696e6120536d69726e6f76610000196172696e61736d69726e6f76766140676d61696c2e636f6d000010406172696e61736d69726e6f767661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714818371d947b2dfe99e6f2c2051af39eb875189cb0584c88f9979e8a11e196fd709788bdc360bb303": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481a8aa27b7c69abc7c7d2fe83c4af79c49136f0f8c5f1a00cd8d0aa91c94fe74d0145cb96d688f66": "0x0401000000020000000000000000000000000000000009454d4d414e55454c0000001864656d62756f6e67616374726f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481ca6b2d789063a60c57c0853ddd25eba3342516d472dc386718377fd76df4485eeb60a105ac7055": "0x000000000000000000000000000000000017526f79616c20536f6369657479206f66204368616f7317526f79616c20536f6369657479206f66204368616f732068747470733a2f2f726f79616c736f63696574796f666368616f732e636f6d001e6368616f7340726f79616c736f63696574796f666368616f732e636f6d00000f40726f79616c736f666368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481d06e4180e1ea3d46783c52055cd65e6c7b0cc7ffe525be5bd41a30837c25cd5f061802c1ff9707": "0x00000000000000000000000000000000000943727970746f42691041726979612042616e6f6d796f6e6700001a61726979612e62616e6f6d796f6e6740676d61696c2e636f6d00000a4062695f6172697961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481d88cd163efe288face4e155edc11a8a64d04d35885b5b9189172fb4c225a9c4c3ad2997a699121": "0x0000000000000000000000000000000000175468652059656c6c6f77204775792050726f6a6563740d5068696c697070204b75727a00001c7068696c6970702e6b75727a4070726f746f6e6d61696c2e636f6d00000d406b75727a65747765657473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481d8e79920233c8de01eae270edb18124aa8bd49e3eca870f25497795d1843e2bbe21ed2808cef20": "0x0000000000000000000000000000000000084b756a696e6e200c4b756a696e6e20526d726b0000166b7573616d61646a696e6e40676d61696c2e636f6d000009404b756a696e6e52000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471481e1f270e2e851570e7aaf6634a1bec0cd73d40e2a69c31d160cd76f4dc3d06ceb3ed1bc58636e3a": "0x0000000000000000000000000000000000074e6f76757358000000166e6f76757378617669657240676d61696c2e636f6d00000b405370616365426f6279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482175dad66ffb1f228f8214ba1b29fbf1d1a0a45f760803cf6539ef1b1739b05019e017b85987a24": "0x00000000000000000000000000000000000a4a6f686e204c756b6500000018696e666f2e6a6f686e6c756b6540676d61696c2e636f6d00000e406c6f76656a6f686e6c756b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482177f02309c6644de455bc9951b3280b717735762428896bcc146adba12c9e4dd2c4a1316f95432": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148218a521e794df69d80d984a8b722fa16d8b8b5d39b18a3074a8d57450f44a072f3bf27f3602ee10": "0x000000000000000000000000000000000009637665746f6d6d790000000000000a40637665746f6d6d79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714823f88e31299deaa7c7546e35503a5716aadd49f18be0bf4e04e65db300e0d9822fd7f2a935c1d12": "0x0000000000000000000000000000000000076b404e61727900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714824e4641808c73d2acb9eb46f872884c2b988d65fe151ce9ca720b9fed0bb3831861429e25bb7853": "0x0000000000000000000000000000000000054d4f4f4e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482560819c55b16b2badd9daa2bcd66e001195e14fe7c6d176a7295734db2f46f05d7d4d38a097922": "0x0000000000000000000000000000000000084b686e656d7564001d68747470733a2f2f74696e7975726c2e636f6d2f327038656d6e753700196b656e6e79406b686e656d7564706f74746572792e636f6d00000e404b656e7a69654279726e6536000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482a2945d18dc6de7685dc052a755ac3cecc0b0bd0d1405ade433d8463a3cabc1e5b7eedb13c08871": "0x08000000000100902f50090000000000000000000000040000000200000000000000000000000000000000064c65696d691752c3a96d79204269656e2042616f20506572657474691968747470733a2f2f7777772e6c6974656e7472792e636f6d001272656d79406c6974656e7472792e636f6d00000a407365787964656669000a52656d79233632373700", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482a6377e5035d73b20e9d154939a016638b30c2015296620adc11207fbe0901296b53556efa4c81d": "0x00000000000000000000000000000000000c53686164794261646765720000184073686164796261646765723a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482b8bce0892920f9ca3d904d81a1b1ba11bd6e391daa897b907ff89c5c5aebfe6f2da23292b8500f": "0x00000000000000000000000000000000000d5765796c616e645f46756e6400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482cc12483eced9790ede38c79ca874b40d63470229ef2d0de1453af484ec71f8af099bb3a37d7760": "0x00000000000000000000000000000000000f706f6c6b615f6b725f737461736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482de5a96dc46220438036dd1fdee37c36c5a5718bda359f3c5eafb47cccbc1b47663b15c42e93879": "0x00000000000000000000000000000000000f526f626572745f476c6561736f6e0000000000001040726f626572745f676c6561736f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482f1848eaab32c01981dc5e72874e0606777ffff70cdd6f1f551a858a8f4bd2c25f06e3ea778fb17": "0x00000000000000000000000000000000000d74656964652d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482f289336c02a916220db94b831a3cd2a856fb540018c949b64ac01c0f3b2a8610be43f862a70b49": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f353000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471482f319a69e3c81ac408d7f8ce355d1566fc9f796813bb4d3b09ae84279232b2349a1c1ec3f0df45c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714830a08ce1ea6aec346e3b7019bc2b1958609cab353fc3ff67417ea982a84fd43f8161b3b1f1de82c": "0x000000000000000000000000000000000008416e696d61726112416e696d6172615f65636f73797374656d1b7777772e616e696d61726165636f73797374656d2e776f726c64001b416e696d61726165636f73797374656d40676d61696c2e636f6d00000f40416e696d6172615f776f726c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714832b1944308e1804da331189f1e7a7a6055dab543cffddfe90888044d75791cfcc13fc02e5841664": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148337944019a68ea6a6500e450888dd3758b301a0f99d433264362547ca7d0f7631ea53871aa3be35": "0x0000000000000000000000000000000000094f4e454352595054000015406f6e6563727970743a6d61747269782e6f726711726f6f74406f6e6563727970742e696f00000b406f6e65637279707432000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483731d75f677cc39943c8d0909cfa78a882249bd5d6aa9bc1abaa7ececfc470c6b0d2f8021f67b6f": "0x040100000002000000000000000000000000000000000a44726f696473697a650a44726f696473697a651668747470733a2f2f64726f696473697a652e636f6d0015796f676573684064726f696473697a652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148378b2a58db8f57d444f83d9012f64dc4acd741cd22442e129a0c5d51e3fc88df1b464afe3dedf58": "0x000000000000000000000000000000000004526f6104526f610000157273616c64697661726640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483932c1bdd63f4dd081159bf1cae87c5c026fb0fa008306db2b21d3a742b9da2508d44cb6e126955": "0x00000000000000000000000000000000000b456e64616e676572656400000017656e64616e6765726564626b40676d61696c2e636f6d00000e40656e64616e6765726564626b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483a221c8bc0e6066b2ed7a9394d1ed621c2e4200faed7ba856fbc722aa34996055b414d8517e712d": "0x0000000000000000000000000000000000064d6f797a610e4d696368616c204d6f6a7a69731c68747470733a2f2f6d656469756d2e636f6d2f406d6f6a7961383100116d6f6a7a6973407961686f6f2e636f6d00000f406b7573616c616d616e64657273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483ad6aeb3e5890e926090dc5275e53b65763f135108a9111289aa1ca6331a8ddb3440059cd33d75f": "0x000000000000000000000000000000000009706f6c6b61646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483af75dd98f115fdc8156333178110191fa71e2c2d85af3f15cf5e4fc191e7a30d14fa03ba4fae01": "0x00000000000000000000000000000000000765696666656c000000000000104065696666656c3533353138323938000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483ce59511097e6b62add0af948eba3b1fcd5cacde1f6fcc70f11ef75056f88ca4d11dcc5b080220e": "0x040000000002000000000000000000000000000000002049204c6f76652043726970746f202d204865616420416d6261737361646f720000001e616c62657274706f6c6b61646f74737061696e40676d61696c2e636f6d00000f40495f4c6f76655f43726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483e3a5f61f9aaf705e7bdc8f8fefc667401cc90e1415d74771543ba45903e763cfec39609e80c67e": "0x00000000000000000000000000000000000c6461706861726d612121210000000000000d406b7573616d616661726d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483f89e0f584ff0b7f60f9b64ebf26b9487c65ada132908745572692aef7cd9c987daf8c9c0c2ff3a": "0x000000000000000000000000000000000012e29b93efb88f20526f6220e29b93efb88f12526f626572742048616265726d65696572001b407270686d656965723a6d61747269782e7061726974792e696f11726f62657274407061726974792e696f00000a407270686d65696572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471483feead6a196ca7384d58485b197a76a478bc70cec24386d631d07789a3fcaa9f2caf559e6f1197b": "0x00000000000000000000000000000000000d446567656e5f6d6f6f6e65720000000000000e40446567656e5f6d6f6f6e6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714840925591fbe6a29706c68ab8f36287cae3a10a27b1572ba848aab662978427464f456f6e7644241": "0x00000000000000000000000000000000001430785461796c6f72202d204368616f7344414f0930785461796c6f721868747470733a2f2f7468654368616f7344414f2e636f6d001930785461796c6f72407468654368616f7344414f2e636f6d00000b4030785461796c6f725f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148414c4f8c9a8cf81640bab9edc54d75165f1924f25f8b979f6b290c1b884b4c5a706bdd25e35b576": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f343700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714841c66ae33e977e77eb07fd02281d018a4c45bab914fc6e2a0f81620663b53ab62432ae62a07194d": "0x040000000002000000000000000000000000000000000b4b6f6272656461627265000017406b6f62726564616272653a6d61747269782e6f7267146b6f6272656461627265406c6976652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714841d45054add5366d228fd275f3f92e8b6ccc56a9437582dc59db70153ab33cdd77562661adda60f": "0x04000000000200000000000000000000000000000000174461726b7374617220e0a590204d756c616468617261000019406461726b73746172313938323a6d61747269782e6f72671c6461726b73746172313938324070726f746f6e6d61696c2e636f6d0000114044466f726b6c6573736e6174696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714842664827980e15e54faa9f0cc59a977e73147865791a9272cd4980db5ff2eee27096d34ff2fab69": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471484424b39102122b2f0c8760979e133469c6c41786f59b4a7c7c6eccad05ee675b3751b83d0684652": "0x000000000000000000000000000000000007544d575349590000000000000b40544d57534959343230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471484438c43a102074910f57ab33929e8e7dc1f97a59d3e21f67fc50bcc92b4237cfe909749d907d227": "0x00000000000000000000000000000000000d436f6d6d6f6e7765616c746817436f6d6d6f6e7765616c7468204c61627320496e632e1868747470733a2f2f636f6d6d6f6e7765616c74682e696d001668656c6c6f40636f6d6d6f6e7765616c74682e696d000010406869636f6d6d6f6e7765616c7468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714849d9d404714c4e49827c3338307099b89b70abd3f743768f9e98fed36c9f8de5c23684ad4cf0939": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471484bce6312eb819d778608868cc221644fb3de1b580e43c0365dcb7bdfc43730edcd0af67afd3e67a": "0x00000000000000000000000000000000000b78567373706f6c6f4878095961726f736c6176000017646f6c7a68656e6b6f5f79617240696e626f782e727500000a40767373706f6c6f68000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471484c01eafe8e77b497036fc2cc5a44e28d92392be9d9ef3420fe2755cd50ee4f6d6cfc2eaa5888e40": "0x04010000000200000000000000000000000000000000054572656e0c4572656e2059696c6d617a0014406572656e7361743a6d61747269782e6f7267186572656e79696c6d617a61636340676d61696c2e636f6d000011404572656e59696c3134383133383930000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471484ccbb22b59b800b7213534fb02c7638d8d7caf1f62b983225c5aa76b8c14d249f7a704b50ba850a": "0x040000000002000000000000000000000000000000000a4c696e6b2073776170000000156c696e6b6173777561704070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714852be0a8606681ce165cb5a983d875ff3fedd96cf02bbda58aab07f644bc61b896a69e65d7b92d54": "0x00000000000000000000000000000000000b4e696f6e205265616c6d000000146e696f6e7265616c6d40676d61696c2e636f6d00000c404e696f6e4465656d756e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714852c1c067967d16ce0347fd9c9ad8e56eef3dd3bcb364273bccac7261212336b24fc87928021d426": "0x000000000000000000000000000000000004505050000000177065706174726963696f323040676d61696c2e636f6d000009404f637572617331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148549b7fd2bfcfdd9bc0525c374a8198f3288a0733918321dfc26532e253d94da3a6a27a4c3e31760": "0x00000000000000000000000000000000000a506f6c6b6148617573001b68747470733a2f2f7777772e706f6c6b61686175732e636c7562000000000b40706f6c6b6168617573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148583ceea4c5e9e7682be679b08a867b9b6e92189ffaf6fe921e50e38c5204ae46450705fa0f39878": "0x04010000000200000000000000000000000000000000134b6f6e7374616e74696e207032702e6f7267047032701068747470733a2f2f7032702e6f7267144063726561746f723a6d61747269782e6f72670000000a406c6f6d617368756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485aa231dc6bbaf55949fc105e6f977a37d0d44fb4feabcd0933d87c1f2b2fad95da2bd979bda234d": "0x0000000000000000000000000000000000094e6963654769726c10456c656e6120556b687661746f7661000017686f6e657968656c656e323840676d61696c2e636f6d00000f4048656c656e3639323133393535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485d657f1acd3f2c92458c79f1b8d080257ba31830f364170c90b6b173be1832ebace48595d193b2b": "0x040000000002000000000000000000000000000000000e4272696768746c797374616b65001b68747470733a2f2f6272696768746c797374616b652e636f6d2f1a406272696768746c797374616b653a6d61747269782e6f7267157374616b696e6737706340676d61696c2e636f6d00000f406272696768746c797374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485db7559145dd87f504320903e1423f2143971b828c16bde706c9649054a2dd6226f4a552cbd7c4d": "0x0000000000000000000000000000000000064b726f627900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485e316d89f98284006783fab54c44733401db93381ce95dbdf7f8cae198a3abd281961d104a6a542": "0x00000000000000000000000000000000000442656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485ed039d265a7ffaa0601b089848ea1f1071885870523f61923c1e6e8000f68ac1a0e03025a21d0f": "0x040000000002000000000000000000000000000000000d73616c656e6b6120f09f8cb80000144073616c656e6b613a6d61747269782e6f72671473616c656e6b61627940676d61696c2e636f6d00000b4073616c656e6b616279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485f67a71efa822abcc3c76905f804cc082bf0dfebda879f5f6c3d37c0139e3e03bef1ed935121620": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000001151554152545a20627920554e4951554514556e69717565204e6574776f726b204c74642e1f68747470733a2f2f756e697175652e6e6574776f726b2f71756172747a2f001568656c6c6f40756e697175652e6e6574776f726b00001140756e697175655f6e6674636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471485f7724f745447635aad391e69d2500ab8d5d6992b8e38cfd3a5937a5667757a875e29a4281f7546": "0x0000000000000000000000000000000000074275726e737900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714860033e5e332e23d6a2bd95c44c00bcad3fef2f7226ad90b8b93c3c1b9679236d5abfdb39c895844": "0x040100000002000000000000000000000000000000000a456e636f696e74657216456e636f696e746572204173736f63696174696f6e1668747470733a2f2f656e636f696e7465722e6f72670013696e666f40656e636f696e7465722e6f726700000b40656e636f696e746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148613e243ad5accda52a6c52dc82940a36fefd1474cc0778517bb1a56b7bda0e308b6c19152dd7510": "0x040400000002000000000000000000000000000000000b4f70656e537175617265002068747470733a2f2f7777772e6f70656e7371756172652e6e6574776f726b2f1840776c69796f6e6766656e673a6d61747269782e6f7267166869406f70656e7371756172652e6e6574776f726b00000d404f70656e7371756172654e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714861d071872c198e2a24e701429baee3c80ed77ab46977c581f43c21ffb13c5a6580366b17d4acb74": "0x040000000002000000000000000000000000000000000e4775617264612057616c6c6574000013406775617264613a6d61747269782e6f7267136163636f756e7473406775617264612e636f00000e4047756172646157616c6c6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148621671899b86161726ac63a0a6a700ad7e1178fef89a87620bbc152a19f74708defc7f08bbc6556": "0x040000000002000000000000000000000000000000000a426c6f636b4374726c00000019626c6f636b6374726c4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148641dd739c11a1441994df5bf0f44342b1719bfbb1561286bd81b6d84f577f55ef45fe7ad6f50e4a": "0x040100000002000000000000000000000000000000000d466f72626f6c6520f09f8ea00d466f72626f6c6520f09f8ea01468747470733a2f2f666f72626f6c652e636f6d16406b77756e7965756e673a6d61747269782e6f726711696e666f40666f72626f6c652e636f6d00000940666f72626f6c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486672c8d8603d645de7fc70edbc29190008415c3b6122dc6390b738453c6f1213b59942b2b76e54a": "0x040100000001002ca07d510000000000000000000000000000000000000000000000000000000843757272656e741546696e436f2053657276696365732c20496e632e1568747470733a2f2f63757272656e742e636f6d2f1b4063757272656e742d63727970746f3a6d61747269782e6f72671363727970746f4063757272656e742e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714867ef0c5910d039618b37b11994703df397ba3817e5a3005c8fc91487518d31093f96dc13f8eae7a": "0x00000000000000000000000000000000000e456c6973616b7572615f61727406456c697361000016456c6973616b757261323140676d61696c2e636f6d00000f40456c6973616b7572615f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714867fc6e4929b002af04c95a6ac10a0db5af28ac44776f95949dd543f494f8b8787925c41fccf7e0f": "0x04000000000200000000000000000000000000000000074f4e54555045000015406876656c61796f733a6d61747269782e6f7267186876656c61796f734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714868406635a107a77f4677f381984864892b8f2646e8474586b5739666db1061ec17e247f1256a73f": "0x040100000002000000000000000000000000000000000b4441564552414d49434f0000124064617665723a6d61747269782e6f7267156461766572616d69636f40676d61696c2e636f6d00000c406461766572616d69636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486998e21ddb35f37688e785a232855035798ed3859b39323e0a889a0bc91433bb2b7491d7552b541": "0x040000000002000000000000000000000000000000000e4761627269656c204e756e6573000000196761627269656c407368696674666573746976616c2e6363000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714869d5132140a00b380971274db9eafa67a4e9baaacec073a76949d8ac63e804fdb71680d0b27d618": "0x00000000000000000000000000000000000f53756257616c6c6574204e4654730a53756257616c6c65741a68747470733a2f2f7777772e73756277616c6c65742e61707000146167656e744073756277616c6c65742e61707000000e4073756277616c6c6574617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486a03b31f22c207f6607dc83a7fc1f33c13e978ee3527fdb2c908ae6b5c0d2dee81bf30a01808263": "0x00000000000000000000000000000000000c426f747469636577736b690010626f747469636577736b692e617274001b626f747469636577736b694070726f746f6e6d61696c2e636f6d00000d40626f747469636577736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486a0b39405083331c0df6f52cc5815bbc65e071936fd135fb972c5d2b08f03e4c9a06ab2ba6b446c": "0x000000000000000000000000000000000008566f78656c6c650101010100000e405375707261566f78656c6c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486a3835ceaaa8d91649b3af5a44c0a5a69f905bdbe203eeaaf5dea0695d9d3e307139236f1e92439": "0x000000000000000000000000000000000011546865204b494c5420447265616d657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486a7a7c4bbbdc511e35a5bb9f11f2d71940593c4ff87fba89a7ab269825da6282025c43bf0b4c07c": "0x040100000001005039278c0400000000000000000000000000000000000000000000000000001f54657374204163636f756e7420666f7220526567697374726172202331201a54657374206163636f756e74205265676973747261722023311a68747470733a2f2f7777772e657468696e636f72702e636f6d144063686576646f723a6d61747269782e6f72671a63686576646f722b7265677465737440676d61696c2e636f6d00000b40657468696e636f7270000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486c0d84c17d8fc6ecef2e5dd707eece5bce1ba22a95b527945e78b6ea1a1bf953b8623e9ceba8f77": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000001c436f6e74726f6c6c65724163636f756e74426c6f636b6f6e61757410426c6f636b6f6e61757420476d62481b68747470733a2f2f7777772e626c6f636b6f6e6175742e636f6d1b40626c6f636b6f6e6175745f636f6d3a6d61747269782e6f726717636f6e7461637440626c6f636b6f6e6175742e636f6d00001040626c6f636b6f6e6175745f636f6d0010626c6f636b6f6e617574233131393300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486e44a960bbce9b16064f216e5b0598fd04f234902e175fdff5f78ac58d24856189cf89772c7711b": "0x000000000000000000000000000000000015546865206372656174696f6e2073746174696f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486e553fb01bfcb3d16f24ecfa07199b88f010d94f47864ace2c0357aa4f37898f85cb39992e2036d": "0x0400000000020000000000000000000000000000000009476f6c646d696e65000000176272656e64616e766163613640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486e69567b2fc7d85a44fe0211e518d4a7e0d647cb66979cafcf322d3427972abf875d29c7c76d501": "0x040100000002000000000000000000000000000000000f44616e69656c204d6172696369631044616e696a656c204d6172696369631068747470733a2f2f776f73732e696f1140776f73733a6d61747269782e6f72670f64616e69656c40776f73732e696f00000940776f73735f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486e97071fc27afaf9cb3ce3a07b00735ce0f68793b5717985758dbbf1fbdc95bb293adccaf6aea58": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471486fafe6b0ee9fc1c9070bd80051c026f2ad47a498257131f7897df07f9ac2e4850fc0594ffb7c16b": "0x000000000000000000000000000000000000001768747470733a2f2f6465636f6d3838382e7370616365000000000d4073686172795f6465636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714870976f0672085c5f8ff75032359f0de13264a134c3e88089cf6a2a31e5cf3cdfe405a4e272f0508": "0x040000000002000000000000000000000000000000000d547963686f204d61736975730000000000000e40547963686f5f4d6173697573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714871588d7f6c0fdd3002f931bb0cf405212de02243756d8ff665710af7fb234bfb1a50bb78ae1327b": "0x040100000002000000000000000000000000000000000b52617669204b756d61720b52617669204b756d617200154069747372617669693a6d61747269782e6f726715697473796f757261766940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148715cdd917100e492ecd4b1267030cbe7bc4c16f0686b668c3b2c4a63887c4b72ed7e61cdbba8e01": "0x00000000000000000000000000000000000d544845204249472042554c4c01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148729829bc3420b4a8ce5570a948cf1f53af41b9ca5e693e27db42957b5feebd496f294083c7b3334": "0x00000000000000000000000000000000000c426f68656d69612046616d13426f68656d69616e20436f6d6d756e697479147777772e626f68656d69612e67616c6c6572790015426f68656d696144414f40676d61696c2e636f6d00000c40426f68656d696146616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148736623ab752230ee06552c57e6cb90fb36289f12641459616eaba6ac6e12bc8df5d27b4348df364": "0x00000000000000000000000000000000000c75387a7257614d3241504e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148744f5b40dccd408f29b23662a19aafa105a3b29cc512bdf7be3d2d90b9ccdac7c5bde9f690d2d33": "0x0000000000000000000000000000000000024d01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714874cbacaa0bc1cceea8e9d3cfedc8afec25785703681d424e6aba10b728927b89d87a3776b47ee32": "0x08000000000100902f500900000000000000000000000100000002000000000000000000000000000000000d506f6c6b61466f756e6472790d506f6c6b61466f756e6472791a68747470733a2f2f706f6c6b61666f756e6472792e636f6d2f0016696e666f40706f6c6b61666f756e6472792e636f6d00000e40706f6c6b61666f756e647279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148779102a034bee1fee548f8308101986802a4f7e713699b60754d59b3722a83e049d7f9b3669344b": "0x00000000000000000000000000000000000b506f6c6b61446f636b320b50697a7a61205061756c01010100000c40506f6c6b61446f636b32000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714877fd9ae533b076ca8e01f1cd734ef1c9342f84af2616fbc4294fa67a820b8ce979cac5e10aa985c": "0x040000000002000000000000000000000000000000000d4b7573616d61204c6c616d6100000011696e666f406c6c616d612e726f636b7300000d404b7573616d614c6c616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487843e0e467379078c79cbd600c63f0cc90b34e7301b7cef8c93f7a404cbacecab96901fe53d4640": "0x04000000000200000000000000000000000000000000084c6f67616e7467000014406c6f67616e74673a6d61747269782e6f72671a6372697374616c2e726f737369383840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487984f82dcc0d15b4a99af57418d7b0845ef9c692352b5ca08f7372fe7bdf6ba27ab3ccb139ffff6": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487ac7128ed93fd445e50e6e8499b921414360c3da7de7ca78544e38412bb6dc313383aaceb7c2068": "0x040100000002000000000000000000000000000000000a5072656d6975726c790e5072656d6975726c79204fc39c1668747470733a2f2f7072656d6975726c792e696e2f0015636f6e74616374407072656d6975726c792e696e00000b407072656d6975726c79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487b8b4219b989155bc4eccf7ab63522ed3545f9285b79e804b0eabae2cc508814bfbe29e22138d66": "0x000000000000000000000000000000000008534d532044414f0c534d532044414f20494e430f7777772e736d7364616f2e6f726701010000094061647362657461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487f8d378447f4f51b8a038b439b411fb7c6cc2d7315292a3d1649601641cbbe0825ab7fa90ce3002": "0x040000000002000000000000000000000000000000000c46696e616e6365204163650000001661636566696e616e6365734070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487fe49129143221da4cac89e333e01f3718e89b1058470f721310828c70466cc6d460fe321238056": "0x040100000002000000000000000000000000000000000f6534792d636f6e74726f6c6c6572000013406534792e696f3a6d61747269782e6f72670f737570706f7274406534792e696f00000740496f453479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471487ff181aa5f0d72d7603df59789b7e57153ab9fab5615620d3ef95cf7843c106b726ea5792ac075e": "0x0000000000000000000000000000000000194761627269656c207c2050726f6f66206f66204368616f7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714880e0c74f6c4f133daf0bff384569f5b20a6e27845a8926b37049833628f90aaaf1011ea6b5bbe52": "0x0000000000000000000000000000000000144c495a415f534f46495f4e46545f524d524b320a4c697a615f536f6669000010696e666f637672406d61696c2e727500000940536f66694e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714881da501afe93dbc7cc45be885cceb3872d32ccea9670b1fb11ef4fa8ceb7f261605f7bd4d9d8d76": "0x040000000002000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488240c4b087c954670d3d29a5674c684a378005daa252a0bdfb4138054278df93a60061965ae1354": "0x00000000000000000000000000000000000a43726f77646c6f616e06417274757200000000000f4047726564647948616d73746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714882ce79ebcfdf17062834a84148dad7c319b78d0f511593e0a882b0b81815575d37ee06fce78d060": "0x00000000000000000000000000000000001345726963207c2050696e6b6e6f6465205431094572696320506f6800144065726963706f683a6d61747269782e6f726715657269632e706f684070696e6b6e6f64652e696f0000094065726963703068000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714885ebea0f5080b1300f53cf59ee4bae1fc47b5df521d48a3cc2d02d5c15fd5d3bfa3d6a4a2e6a576": "0x0400000000020000000000000000000000000000000015f09f909f426c756566696e2054756e61f09f909f00000013616e74756e40747574616e6f74612e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714887069bc3f84e008c6fdd542b5fec95757cddb7f88df8c14fbc998ae30352528cd0745a21f893a3a": "0x00000000000000000000000000000000000f74696d65666f7261676f7269736d0101010100000a404a696d4a65743133000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148876172ab0d0bba3f89b361ea400867da22fa6a069fdd840819fdc24fee6cc3763b6cf3a8a20246b": "0x040000000002000000000000000000000000000000000c4441524b2d4b5553414d41000019406461726b6c657373323030313a6d61747269782e6f7267196461726b6c65737363726970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714888912dae0a7ddbc8268b1d9ea3f3e28439ba92ab93da4a2788b33c3a88b0b8ec776590d5a1ff87c": "0x00000000000000000000000000000000000c4d75636861205069657a6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488a1a9c29731ee3b388fbc33e4adebe4c8296ddf2cf1dcea98d5bb98589cc4965547552ca6dfc215": "0x00000000000000000000000000000000000d436963616461207c204e435201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488a90a53149b04c1fc77c33ab2d50bfa2e62c53701209166f5fdd2afd44e3d9d613c2deb29a2056a": "0x00000000000000000000000000000000000f4f6e652052617720417274697374000000176f6e6572617761727469737440676d61696c2e636f6d000010406f6e655f7261775f617274697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488d2cf1d33c430800ed87826ce11d92d5c738c002d2a0deadc05ede81c6c72d3d22f0bb6e87c274a": "0x000000000000000000000000000000000007546f6d73636f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488de95e48f84c3689085297d964ea873a23b63151b4c82189c1314c31fda6f2d71f83133d0877c5c": "0x040000000002000000000000000000000000000000000c56616c69644f72616e6765001c68747470733a2f2f7777772e76616c69646f72616e67652e6e6574184076616c69646f72616e67653a6d61747269782e6f726715696e666f4076616c69646f72616e67652e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488f2bab6b4633034bee287e579da5137412f2c3bd4d5ae4c6a11c4c420e04261157e04842a2ea641": "0x04000000000200000000000000000000000000000000104b7573616d696361204461626963610000134062756c726f673a6d61747269782e6f72671f73766562697261642e7072697469736b6f76696340676d61696c2e636f6d000011404e69636b7953613338353130363434000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488faf51e2f7bed7746ff2d3857b6622883201338ade0e84de95c9be1587b549bf185e802d29e251d": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34330f62696e616e63655f6b736d5f3433000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471488ffc163fa9907f076f9c831b885b8f1a216a27064fa793733b162ee06afb502a8cdbc2ccd6cc536": "0x0400000000020000000000000000000000000000000009594a52656e7561640000001c796f76616e6e7972656e6175643634363140676d61696c2e636f6d00000e4052656e617564466562726573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148902cecf825f2867273e55ba58de0184bb96e5e691dcc9171ec58658d2b94c42c7e4ca7574f6a076": "0x0400000000020000000000000000000000000000000011e5a4a7e59684206461697a656e2e696f000013406461697a656e3a6d61747269782e6f72670f696e666f406461697a656e2e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148910f5da4fb5fea048e84bb42675b4208dca0a9a06e3e16dfb1820208d363ea473056b4fa280c46e": "0x00000000000000000000000000000000000d417065204379636c6f70732104494f4e2168747470733a2f2f64726976652e676f6f676c652e636f6d2f64726976652f66001466657261726938333940676d61696c2e636f6d00000d4050756e6b324d6f6e6b6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714891b91a049c68e2f8ac73a177aa1ca00ba0fbc44e7d16f9855419e45d6cd9f517a369b9cb39d3a7d": "0x000000000000000000000000000000000016496e697469616c576f726c6443726561746f72303216496e697469616c576f726c6443726561746f72303210696e697469616c776f726c642e696f001c726f6d695f6a6f6e657340696e697469616c776f726c642e6e657400001140496e697469616c576f726c644c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148954d9b6c7704b5c0a912cf4f0c7894598d81d26f2c24f6e5c2541f312462bb576593e9dc549146d": "0x040000000002000000000000000000000000000000001051757069642056616c696461746f7200001b40717570696476616c696461746f723a6d61747269782e6f726719717570696476616c696461746f7240676d61696c2e636f6d00001040717570696476616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148954f8409a1908282288acef72d15ccf97030a0972ba24d944aa27a3e545d9a3f3f5b4e8b613fa36": "0x00000000000000000000000000000000000c61727461726f756e646b731420202020206b617468696c2073696d70736f6e1f68747470733a2f2f6172746d6f6e64652e626c6f6773706f742e636f6d2f001661727461726f756e646b7340676d61696c2e636f6d00000d4061727461726f756e646b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148962ad14faa948d9eae8d17c39cd028fc4e889f74dad887d007342d2e5f76502098e7eea42980217": "0x00000000000000000000000000000000000d646f75626c6520706f6c6b61001d68747470733a2f2f6d656469756d2e636f6d2f40696e666163654149000000000a40696e666163654169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471489667e9959f3863058411145513d689314c9a37396cc497d2f3758a382634f82b2525ca6d01ddd56": "0x00000000000000000000000000000000000b4372697370536b6965730000000000000c404372697370536b696573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148977e9fa22acb7d0d67a205808a76c0dfa0a5a14159d8ed04e0992d31a0671df21a813a8d6ce9b46": "0x0000000000000000000000000000000000094e4654206b696e67010101186875796368756e672e7068616e40676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148980286a570d6ea48865342bccbb2d7592528a183ad9ca54e1738bf98dd7c64e96f4cadf4739542d": "0x00000000000000000000000000000000000c4d656e756d65726f7639330752757374656d00001252757374656d31373440756b722e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148980acab3e7bb9bb1035801fd00144e10a3933ed859f8236bbffb93a7ac515bab9f1ca53cbb3f776": "0x040100000002000000000000000000000000000000000b4a7573745f4c75757575000000166c75752e6b6f6461646f7440676d61696c2e636f6d00000c404a7573745f4c75757575000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148997871f06793d390456840228e994122a2750c966571ca20d2456db20a7cb84603ed8e2d5503776": "0x040000000002000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714899d77357f66a9b3fe56e0dbbdfa9b2197616f3f093228bb9dedcf5677377f4bcce42e4d0bd16eb8": "0x040000000002000000000000000000000000000000000e446563656e7472615374616b6500001a40646563656e7472617374616b653a6d61747269782e6f726718646563656e7472617374616b6540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471489bf72beff341fae9c0504f521d79782f9f198212be1b14b7df0f55e8ba9042f618c6bfd6894d920": "0x00000000000000000000000000000000000e4b52494c4c5553545241544f5200207777772e696e7374616772616d2e636f6d2f6b72696c6c7573747261746f72000000000f406b72696c6c7573747261746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471489df2e19e8562faa88f04758ca57f3a570499fbcb3d10a8d4c9e62662d23223ab5abd805521f2162": "0x00000000000000000000000000000000000e546865204c61737420446f646f01157777772e7468656c617374646f646f2e636c75620101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471489e71b2f143062e5c849c094a957256b4928ed7df80cef4b0e07790ca93c4e35877d6b6c47fb9c40": "0x00000000000000000000000000000000000c4b7573616d615a696c6c610c4b7573616d615a696c6c611b68747470733a2f2f7777772e6b7573616d617a696c6c612e696f00166b7573616d617a696c6c6140676d61696c2e636f6d00000d404b7573616d615a696c6c61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a120585308557016e4020d8682b80d1b7112894cc302ae29735fa311760fda4068d8137033e315e": "0x040000000002000000000000000000000000000000000b4d617373205374616b6500000019656d626965692e6e6574776f726b40676d61696c2e636f6d00000940456d626965695f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a1f3ec68da119f752843653b3cce985caef494fa794e3d6338708ff4f137a3955b5bd18a1ee9d44": "0x0000000000000000000000000000000000094b454e4750454e47000000156b656e6770656e67323340676d61696c2e636f6d00000b406b656e6770656e6733000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a2418436ea9d5744af70f547e94688d2d6398f17ae4b7854b44d38afecadab4615efa4979b45255": "0x00000000000000000000000000000000000c426f6e6b204d617374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a2830d3f9783449b4e279c9042ff410055903287d4cb86f1349b46190239e07698150980e763a71": "0x0000000000000000000000000000000000064372617a7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a3ad77ce069992b8e83d322ee3b892a90f8ac2cc90eae3bcf4470d69ce11f4697072a7ac7ccb508": "0x040100000002000000000000000000000000000000000c48616e6f6948696c746f6e0000184068616e6f6968696c746f6e3a6d61747269782e6f7267116761626138324079616e6465782e727500001140476164646166693630373139353234000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a44d9fb97a9cc4cca90f519f1fa8e69ddd6fa48de4810638bf87b35e59f323ab28cc0e28bc2a62c": "0x00000000000000000000000000000000000d43727970746f2053616d6173001d68747470733a2f2f7777772e63727970746f73616d61732e636f6d2f000000000d4043727970746f53616d6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a5aa20d3da45f2d029918eebbeb816c3ca22773264f55a58d81c327ab4000d721dc791db0c8c84e": "0x040000000002000000000000000000000000000000000b6775616e696e653235310000001a6775616e696e653235314070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a60668e56121433b0a60407efbd5ce5c071f4267495f8722ad56a6027906052604e2d7d08d36801": "0x08000000000201000000020000000000000000000000000000000011436f736d69632056616c696461746f7211436f736d69632056616c696461746f721d68747470733a2f2f636f736d696376616c696461746f722e636f6d2f0019696e666f40636f736d696376616c696461746f722e636f6d00001140436f736d696356616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a729a52375051e3b44422085bc3088cb79fb9e865d030771c4d2f7babd6b61702d277a2cacf271b": "0x0000000000000000000000000000000000044c463500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a7300288338c9b2327497753b33243d0ce0f0e0d4a4c6e102b628d0ca2f49d606cff851203ee36a": "0x0402000000020000000000000000000000000000000005494f534708494f53472056431068747470733a2f2f696f73672e766311406a6f63793a6d61747269782e6f72670e68656c6c6f40696f73672e766300000840494f53475643000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a74772b80aee66a9ea44891f615653c14d58dbad115753afab7339dbc4cdfc5870f19fd47204c7b": "0x040000000002000000000000000000000000000000000a626f726368656c6c6f00001440626f72697366663a6d61747269782e6f72671b626f7269732e662e6f6666696369616c40676d61696c2e636f6d00000e404246616b746f726f76696368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a7ddcbe937a53aea001e095bd9798f3f8e46931b31953568f444bf4de6245a5cfb81781de277d73": "0x0000000000000000000000000000000000106372617a796d61676e756d2e65746800000000000010406372617a796d61676e756d455448000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148a9080a29f48df317ee04c70647cade0a0bbd6de1b0d21b21136271cd571809e3c1c59424e3e5f59": "0x00000000000000000000000000000000000830784172696368000000000000094030784172696368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148aa02eef8fa57876de87313ed608e73b1c5a4fe34d2336ef43ca2d6d308ae2cc419b932b356a232c": "0x000000000000000000000000000000000001010101186b616e617269612e626972647340676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148abf00f6f189f2ef4a5668af20fe1f0033cd223536a501acc9d39d384513ed2a14d6f41ec28c074f": "0x000000000000000000000000000000000014566c74726156696f6c6574732053747564696f010101164b7573616d614475636b7a40676d61696c2e636f6d00000d404b7573616d614475636b7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ac021761134a4cb6844aff218212e05dff7200a70bffe6b560703ec7541bc47795d3d85c966c14f": "0x00000000000000000000000000000000000d4d6973747279616c5f444f5400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ac96f5c2c35bba5c4eaf39cf3853472cb4ee6809d93108ef7e95284dd5eea32f12a5d1bd0239006": "0x0401000000020000000000000000000000000000000006422d72616410427261646c65792041204f6c736f6e000012627261646c6579407061726974792e696f00000c4062726f6c736f6e313031000e62616f6c736f6e39233337343800", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ae3f21bacbd9a75dc9869be31db55e4f23085f9d300c4dbd6f04c2dac9df98911305b183770b74e": "0x0400000000020000000000000000000000000000000011566972657320696e204e756d657269730000194076697265736e756d657269733a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148af64018762abc4c8644cf1aa56904c194a54bdaf91cc42a95a65bd2e7a6845026d0ca135d430522": "0x040000000002000000000000000000000000000000000d4a61636b20467269656e64730000001a6a616371756573767269656e73363940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148af7bd58a91d6470161254fa03e07813f5eec8b0f734a2976d33a06ea4b57e88d611179e8a8f8193": "0x00000000000000000000000000000000000a53494d554c4143524100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148afa4a7f5b70a3e0904168b519b2745aa1480867fbc7db364c79e03fafd6e30ccc1691e7214ef860": "0x0400000000020000000000000000000000000000000014f09f91a8e2808df09f9a8073706163656d616e0000184073706163656d616e3131363a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148b089e201ac6d25e5e7030e312ba8dd8a9bbffda3d93b34a3ec8d2ff441845be5185e6e0eedcee7d": "0x0000000000000000000000000000000000134e4654f09f9791f09f94a56c616e6466696c104e6967656c20466f726e626572727900001e4e46546c616e6466696c6c61756374696f6e7340676d61696c2e636f6d000011404e465464756d707374657266697265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148b299234c2604004face99d3401cb9b45ee1bc0ec52f4cb35914dc5ad27806230534230eedb8413d": "0x040000000002000000000000000000000000000000000542494c4c0000164062696c6c3a776562332e666f756e646174696f6e1562696c6c40776562332e666f756e646174696f6e00000c4042696c6c4c61626f6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148b72a01f273fec5b1ae6196e6d0656d7b2986e26c2265f462eeace67593da0fe87d1341b0e4ef001": "0x00000000000000000000000000000000000a41726368697669737400000016726f67616e61766572787540676d61696c2e636f6d00000b404c6f6b695061676573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148b99dd128482b33028ef38027a9dca274aa6ffb31e788468c1707dc9e1539164e4be048748244476": "0x00000000000000000000000000000000000b42617272616375646173001b68747470733a2f2f6c696e6b74722e65652f636c617967616e670017636c617967616e677374617240676d61696c2e636f6d00000d405f436c61795f47616e675f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ba9eaa6ab907510383b9fdea1ee994d93bbacd6d67f7cda32fbe6d351d359c257b9e93d92eab75a": "0x0000000000000000000000000000000000114d65616e696e6766756c204d6f74657301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148bd5e851d3f0ece282ab24b11d8ce676a4ddb69f0a2d1a4990c73761bbea86ee509cd5f5af038c35": "0x00000000000000000000000000000000000a484420676172616765011768747470733a2f2f63727970746f2d6172742e65732f010100000e406e66745f6265686f6c646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148bdc67657419bbeb22ce51e9b096db10638d2889c4a847781e0360f6fd3adffa6280107ef7260f62": "0x040000000002000000000000000000000000000000000d506f6c6b61646f742048756200000016706f6c6b61646f7468756240676d61696c2e636f6d00000d40706f6c6b61646f74687562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148bfc916011aac51348ffcdc60f24e9b546980dba143340f37be597cd0b6135eba9c87c4cb434a53d": "0x00000000000000000000000000000000000a43796265724e657264074265636b657200000000000b406a765f6265636b6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c1c29593b2d5db604c73bb4b37fd89e159ea8dda26c4021a4af572826ad6397d8fa9942c18b3568": "0x04010000000200000000000000000000000000000000094741544f544543480d4741544f54454348204c54441468747470733a2f2f6761746f746563682e756b15406761746f746563683a6d61747269782e6f726711696e666f406761746f746563682e756b00000d406761746f746563685f756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c24c3ef8bc4c3e412c0e71d326f83f4e6089448e147fdab51b0b7398a7d0cc9a88b0571432e7310": "0x0800000000020100000002000000000000000000000000000000000c5a7567204361706974616c001768747470733a2f2f7a75676361706974616c2e636f6d0017636f6e74616374407a75676361706974616c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c3084898ad5f06e529c401186113eb29d37baf9cd8f00c62ab900c8f45587e224c70af5bc231f66": "0x00000000000000000000000000000000000a507572706c4e67687401010110707572706c6e67687440706d2e6d6500000b404e676874507572706c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c36932cefb7a9ecb4caa4a0e94ce7de3a3b240421eae5ac497d3222dced621b09dc5b0790575538": "0x000000000000000000000000000000000013506c6173746963205268696e6f73204e46540000000000000f40706c61737469637268696e6f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c4a4a005c89c680fa7c443627d84ad0a74c4510d28d286ac0121c70a2a8191961f689957a625250": "0x00000000000000000000000000000000000a524d524b6e696e6a610000000000000b40524d524b6e696e6a61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c818112f3226361ba19adf8ab8528c9f53058b494b6154dde0fadfe2bdeb3a9b9c87761cdcbb441": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148c8a104718f01d73d20463560bc0be7d6e5eb0c6f46ac13bbd2a52be9764eb0ea5664224d188b162": "0x040000000002000000000000000000000000000000000b4e6f436f43727970746f000017406e6f636f63727970746f3a6d61747269782e6f7267156e6f636f63727970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148cb3a38ac67409ba900d19dc7ddf1723c1b0ee589e54392ae66f4dfdc4e340813d3982ee3c444e4c": "0x00000000000000000000000000000000000b646565706f6c6f6769630b4a616e204b6f6c63616b1768747470733a2f2f646565706f6c6f6769632e636f6d0014696e666f40646565706f6c6f6769632e636f6d00000c40646565706f6c6f676963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148cbad522066132e614740e9f8ba7bc917ece78a0cf3ad3a59dc190a467983fc40b6e10d26df2424e": "0x00000000000000000000000000000000000d656e7665726d65697374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148cf331474cf8ca77789371e25daefddfe31380de2e849beae016eed32ef426bca684a87b2722b226": "0x0000000000000000000000000000000000127361746f7368695f646f7473616d6f746f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d136d7c7984d254da01077bdc025fd779cc21c9760727ec07e52aa132410b82e5fabacb6f45b055": "0x04000000000200000000000000000000000000000000064f4e44494e000012406f6e64696e3a6d61747269782e6f72670e6f6e64696e406969762e646576000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d15d9b9ba448549ceb2a7cee1fe704ef408c1025e5f70a508ce24d0d005b110bb8b92aee6729823": "0x0000000000000000000000000000000000065961796f6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d17af330f9b2c86badb27b0ea87f8b6de054d7ab764af17cfec0a00fa2d9d55ea6317a6202cad58": "0x000000000000000000000000000000000009626163636869737400000013626163636869737440676d61696c2e636f6d00000a406261636368697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d181a92494fefeeb2e15eb8b4fd587fb9d94c5345cbdfa949b059dd12653ebea1df1bc8c00a8d56": "0x0000000000000000000000000000000000046875650000000000000c6875653533363337373831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d22092b65a0be40263e0e2220ee17f5e592687553243ef2cd9dc0f870e3bc8c5aa4759350c66f74": "0x000000000000000000000000000000000009536c617661506f650101010100000d40496e73706563746f72506f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d27cb369656b59b3a2d7c5aa6f73b06dfc3f72288b99609976953f11ed014e38b63cc717e5d9e44": "0x000000000000000000000000000000000006736f6c617200000019736f6c617273797374656d6f6f6e40676d61696c2e636f6d00001040536f6c617273797374656d6f6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d4a0f8bd7262bf796b999767cece29bf12001df86d1355bea8fe46996aeb0ca149f309605794029": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31370f42494e414e43455f4b534d5f3137000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d5f7ebde4f481a866f7b3f3db597d3032c2d767568aa550249c946600a61276910b9c1d21a93371": "0x0404000000020000000000000000000000000000000005534b454e00000018486f6f646965534b4070726f746f6e6d61696c2e636f6d00000d4063727970746f736b656e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d8daac9c069e6c7f200d9578df25fafb6690614aa05052abc6ea28c886c52448f28c8fd1c2a2f2d": "0x000000000000000000000000000000000008576f6f6265656b1743726561746f72206f66204b7573616d616e617574731a7777772e696e7374616772616d2e636f6d2f776f6f6265656b001676617379617374617379614079616e6465782e727500000940776f6f6265656b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d8e7baeef66b6391e9b88072c2f8b8c9b5c730d2b0a65589ba2df45ceb9fec58d35814b2ad5a719": "0x0000000000000000000000000000000000184f55544c4554204152542047414c4c45525920494e432e0000001f73616c65732e61727467616c6c6572792e696e6340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d8ff74133df57ac367801ab22817ca7c25117923cdd6c62889a01c2bf01683cea29e279d14e3e48": "0x0000000000000000000000000000000000094269484f444c203200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148d901b92205a25ebbea06e6ad606b2a80822a72aaae84a9a80bec27f1beef1880ad4970b72227601": "0x0000000000000000000000000000000000157061726974792d7374616b696e672d6d696e657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148db172d8f1d1e04ea246cf4986a146aec95dd8a3670e957aa3f0cbfd70583be5b2e1c0ff7992a36d": "0x00000000000000000000000000000000000f616e616d656c657373666f726365045f5f5f177777772e616e616d656c657373666f7263652e636f6d001c7370656369616c6167656e74736576656e40676d61696c2e636f6d00001040616e616d656c657373666f726365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148dbef89e3ac0f0aad86c1cbcda487cd9e31a5e37b2836ebc1c3b3d86b2cd7596da91fae58e876b24": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ddffc86aaebc2d41e5c61cb6941b247d22fa14392fb8710a23493db5857c2904a76b3bcfda7d217": "0x0400000000020000000000000000000000000000000018576562332065647520616e6420696e766573746d656e740000001261686a7863727a40676d61696c2e636f6d0000094063616f5f6c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148de2cc2856d7fb2a8ad06fa44a5669702a29b394424560714a1af90ad9efb57f3864b93b1ff7961c": "0x040000000002000000000000000000000000000000000670686f6e670000194070686f6e676c657472756e673a6d61747269782e6f72671974706c657472756e6740676f6f676c656d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148df29185dccdeea1e881cd70793b3191b905aab3c659140f21d0febd037e0301235c14ca276d762a": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32330f42696e616e63655f6b736d5f3233000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148dfb7086a8af6a0f46a258564182e321ace7b23e06d109edb5fb9fdd7f25ff6693bc9e0fccac531a": "0x00000000000000000000000000000000000e50756e6b205661756c7420233300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148e029dc73c6ca9b6f00272047a1369138c7948e8d193757bd7d6319254926d2b91175398d8250e30": "0x040000000002000000000000000000000000000000000d52544920736f6c7574696f6e000000196a6f6e61736d6f6e64616c31393440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148e44cd35926bdb0bc6864e8808445baf40b99a5704ecdd47f7b0e609c5c4bcde4658fa8cecacfc3e": "0x000000000000000000000000000000000012446f676569737465722043726f776c65790d536861776e204d757270687900001a726f6d65734063727970746f65636f6e6f6d697a652e636f6d0000114063727970746f65636f6e6f6d697a65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148e5dd8f5ec2ae4f178ba8486af484a791ccc52be9aa844efcb97e88161ef3810ceeb4822cbe9297c": "0x00000000000000000000000000000000000a6465636f6d38383831096465636f6d383838000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148e60dc01fb6f9a204244242bbae9826963603e899b19812a4daae3f5bfc1c4c8fb6aacad2d274300": "0x00000000000000000000000000000000000772726967616e0000000000000b4072726967616e313137000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148eb1982dcbab9029e66b4a86783cae6a8ebf3824279bab103478b05ce04d2630e61a4dd9301d7b11": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148eb6988ffcbcddc884c62d27805ac9c7a62086e31dfae23703ac9dfb37fbd31bec95aa611c5d2c33": "0x04000000000200000000000000000000000000000000124e696e67f09fa4a6e2808de29982efb88f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ec37554e12de10ab08b555a5a3b2725e01ba15eb40aa32dc5b781532854b797808ed45e752b047c": "0x040000000002000000000000000000000000000000000742656e64616b0000001862656e64616b7374616b696e6740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ec91a2d2c36d0707a8b217ad8d80016336be124846210559ebf720aecd25ea0d0d11c10f1839e71": "0x0400000000020000000000000000000000000000000012706c6179696e67207769746820647573740000124071756970753a6d61747269782e6f726721706c6179696e675f776974685f647573744070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ec9e0f3e4ed8b00d6886dc9eaca691d9d893c4eb3132e31db7c0aee951805dd5eb463e783ca7957": "0x00000000000000000000000000000000000c417765736f6d655f446f740c417765736f6d655f446f74000016617765736f6d65646f744079616e6465782e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ee3802b033a961232477dcb6bcaad7e38477d8e0bbaee67b4534d0bf49a0d69f1f8051ca9c8206a": "0x000000000000000000000000000000000010427269736b426c61636b4d616d6261000e636861696e677572752e6170700000000011406c6f6e67626f61726466616d617261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ee5e7ff29bbc499c4826569e68b7eee1b5b93406e4951fcd7ab6b40be519a7db5c6732f66da1149": "0x00000000000000000000000000000000001d496361727573202d205374616b696e6720466163696c697469657320001f68747470733a2f2f7374616b696e67666163696c69746965732e636f6d2f001b696e666f407374616b696e67666163696c69746965732e636f6d00000c407374616b696e67666163000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ef014a3ff4856d97472058104d047d60672ab582ac3a345ec5d5d8f0292b7d237ad8aa4f9f93924": "0x040100000002000000000000000000000000000000000f537562737472614b6e6967687473001e68747470733a2f2f7777772e737562737472616b6e69676874732e696f001e737562737472616b6e69676874734070726f746f6e6d61696c2e636f6d00001140737562737472615f6b6e6967687473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f10571113e0ae6b447326399643ec639a0bfde97d8b37f8dd0ca9fcb3c74a1ce017f0476f3e2770": "0x04000000000200000000000000000000000000000000064b495a4f53000012406b697a6f733a6d61747269782e6f7267156b697a6f734070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f3ec1f0eb47047c3aa8cecefcce91950b7cade280f301fca12202043e06b20e1231ebb4fd331304": "0x00000000000000000000000000000000000c6d616e656b69747469657300176d616e656b6974746965732e706172617472692e6265001168656c6c6f40706172617472692e626500000d406d616e656b697474696573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f570a7114f41f2f9238a1cfd09a86d9624c562507c977082ab136ae4cd96747d618fadcdb7ecd2b": "0x0000000000000000000000000000000000054578657a0000000000000b404f6e64726150756c63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f7c8fc33a08b55c5e9e6c9b7fa123c1f3a714edd226b960cd2ea07faa969dac9e3e9e8bc7c6e24f": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000d456c6f646965207c205733460f456c6f6469652044696e63756666000017656c6f64696540776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f8156567d999f4b06c4a2d537ca65341ebf4d0573230514a60ad2d9d7a78339aa2b6a5e4c61250f": "0x00000000000000000000000000000000000464696501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f88e4319e34d2ea16476866c0074663b7d9046023a2b3fbf447c833f4fccfa3dd7a482235f1ec7f": "0x040000000002000000000000000000000000000000000a656e646561766f757200001840656e646561766f75725f313a6d61747269782e6f72671676696c696a61313936383840676d61696c2e636f6d00000e40416c65784b7269766f6e6f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f8a37e7560fdc95e6fdbbb40014567ab47740ab5e52be2492362e3d0459215d1ce3184a8689b42a": "0x00000000000000000000000000000000000d4772697a7a204b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f943fb275b495a03e3622fb285dddefdf8f9ac2ab59aa34e2abb5a316e9ebdc020317220e75f879": "0x04000000000200000000000000000000000000000000076b734d6f6f6e000013406b736d6f6f6e3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148f9b3eae413c2cb20cde84600189647d443f6318f068a9cfdf630b1ce842b1a9dbb74712866d7639": "0x000000000000000000000000000000000006626f6e796112426f7373616e204261677368697965766100001773686f6e79616d63636f793240676d61696c2e636f6d00001040426f7373616e3036373131303739000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148fb2b977b7be8246964685d439545f2f1805e498916d06ac142ed440f99ddd3543278cacfb1ddb3a": "0x0000000000000000000000000000000000104c6f792042616c646f6e20417274200c4b61726c2042616c646f6e2168747470733a2f2f7777772e6c696e6b6465636b2e6d652f6b61726c62616c64001962616c646f6e6b61726c6b61726c40676d61696c2e636f6d00000d406b61726c5f62616c646f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148fce8c937cb9835fae24164b69db56408ef6a9e9ba9549be17fb3bd4b88bdff92c06ea9df3776d13": "0x00000000000000000000000000000000000a7369726b6974726565000e7369726b69747265652e6e657400147369726b697472656540676d61696c2e636f6d00000b407369726b6974726565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148fda280bf14a4d9a6c87c1c4489f6b4199bacfb7cd427374374a9ddccc4658413564dc6c41a08938": "0x0000000000000000000000000000000000064b534d20320b526f6d616e20526f696b000012722e726f79696b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148fdc8a1dba69b4009a659fe431e951e6a30aa39a583f2b7f5b0540df31fc3fe126e7604f49479f69": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148fe45272324c1bfc323e890aa0b5c0616ae4ce73ef46986c6e822d9f212ac26528fcb36d70b83e42": "0x040000000002000000000000000000000000000000000753656e73656900000014696e666f4073656e7365696e6f64652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ff1a76fe565275c32f682cd110c69b9666ad45dc6735e18e6b790b524fe347df9fc6027ee9da94a": "0x000000000000000000000000000000000019446561642043616e61727920436c7562204675726e61636500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047148ff90052f96341279c107fbcac10f60dc1910e27210283c39f8d5951816f8d7c8f5f96d0c71dbb29": "0x0000000000000000000000000000000000084a454f2e52494300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490073106f69e036ffaba4f34d61e2defae2db1f7c712007824c194ad921959efdb4a65dd174a590c": "0x040000000002000000000000000000000000000000000f50524f4f462e434f4d5055544552134d6f6f7365204c616273204c696d697465641768747470733a2f2f70726f6f662e636f6d7075746572001a76616c696461746f72734070726f6f662e636f6d707574657200000f4070726f6f66636f6d7075746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149008545bc6b9104854dae13b8ee7c7b93cfe5d6e3db2a48ad4fd34ef6191684dbab498b234b9cb10": "0x00000000000000000000000000000000000576616c7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149009e250f366165b143b78432fda580e0996f00fce6f1ea8b2a38e4ddbe229eea3b839921eb4215c": "0x040000000002000000000000000000000000000000001df09f8fa2204d696e6973747279204f6620426c6f636b7320f09f8fa20000001778406d696e69737472796f66626c6f636b732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714900d5f104f49317a8ae668d3b1d7fd73a726263ac4a6454634d65f9c874ad7eede11184c6886bb52": "0x040400000002000000000000000000000000000000000a4c554e415220444f54000000196c756e61722e706f6c6b61646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714900f31199a5d4616161cc08adbd7742ba651fac7c0fe5057fa4ac37b16541bb7a20c903a1841907a": "0x000000000000000000000000000000000009726d616e7a6f6b750c52796f204d616e7a6f6b7500000000000a40726d616e7a6f6b75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714902842d3c37f4986a0b2fb0ff6a2effb882dc59e18d1717233e1142051304e76219f825b9da4eb6b": "0x040000000002000000000000000000000000000000000950616e6567616c690000154070616e6567616c693a6d61747269782e6f72671870616e6567616c694070726f746f6e6d61696c2e636f6d00000a4050616e6567616c69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714903daac85f2846d9f0038b583a9edb1847e77fd632f12053eb84e81cd17e9afa3abd4bfc56a30b24": "0x00000000000000000000000000000000000949726f6e466973680000000000000b40506c6f6e6b61446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149045f9ed16c20b3fee866b5a824a9620446b09bdab8191fe0ab8800e1fbe8185c4ce3488d81d5648": "0x0000000000000000000000000000000000084e696b69746b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714904ced744e494b84188e0101febd96c4801aa0f8df34142d9a5351e5bef51fccba8456b0a29d2030": "0x0000000000000000000000000000000000064e696e6a610000000000000d4062616c616e6365626f726e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714904d3bc15625b8b05c1e0ddb072da402a8732c1dd926dc9befc7e2c9159507a75563b4ac0a2ef347": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490552d7683a533ef8821dc119eb7790c050e97b61a8b93c5e06d7494057f6c773004af1939837a7f": "0x00000000000000000000000000000000000a546f776e437269657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490559a708d4b8f5b9691490b7b477dd3ee98a24ba795c474ac2655fb51c29c24016aea156460494a": "0x00000000000000000000000000000000001ce382afe382b5e3839e204b7573616d61204e696e6a6120f09f8c9e0d736169626f67756e696e6a612568747470733a2f2f7777772e657473792e636f6d2f73686f702f6e6575726f63010100000e40736169626f67756e696e6a61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714905772522f1ed5ae1c9f76582c41ce999555425dcb884e8baa51a21eb8ae524457431ac81431061f": "0x00000000000000000000000000000000000468696f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149060a3c80f6810d992b978cbfa629a5b3fecff0e348a6745690470ea9dc27674a56f757a14e59940": "0x0000000000000000000000000000000000064a6f7267650b4a6f7267652053656e61010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149061dceaf0e1f167f25386e981a22cc69a7bbddc7671e7e471fd95f49098d0f40ebd5bc79730fb49": "0x000000000000000000000000000000000016546865204b7573616d61204e4654204d757365756d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714906d83e2f26e70dd0ed88dff710092f66a4e3da59fa67674985976f493be21879da90be0c1f41476": "0x040000000006000000000000000000000000000000000659616f71690a59616f7169204a69611568747470733a2f2f6a696179616f71692e636f6d184079616f71693a6d61747269782e7061726974792e696f1079616f7169407061726974792e696f00000a406a696179616f7169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149073d801dfde2151c0d998fb9f36dc65132dd06a845548d564e1db500fec59a8926a8fc75a8ba446": "0x00000000000000000000000000000000000a416c656b73616e647213416c656b73616e647220416761666f6e6f76000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490762653147f44fb2479f5e0d2126d87a0ce77cd90278520ed58590d136b78586cbe5c915d5ff16a": "0x000000000000000000000000000000000007436861726c690c436861726c692041726f6e137777772e636861726c6961726f6e2e636f6d00146d61696c40636861726c6961726f6e2e636f6d00000a4063796e6f74797065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714909443962b28076bc4f174c5cd052a7aa222302c7e1c0af713bb28673a504ed1f6a07f03486fc90d": "0x00000000000000000000000000000000001046726f776e696e675a65757338323601010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490969d394746afac8c0cf875f18ab9ca0e60bfc13dba6b4216b74dddf84555ab2f10f0f3b265157c": "0x00000000000000000000000000000000000763726565736501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490a3a06bb6e41d8f1694cecdcc4a83985d1904e6d6709729459eef4a3bd8468f5b11a1dbc352af5d": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30360e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490b1c53cf7dcddbd8a320af9e031a3396f15acdcc65c43008124068226505ee7e12bbb0a12012e60": "0x04000000000300000000000000000000000000000000075061726974791d50617269747920546563686e6f6c6f676965732028554b29204c74640a7061726974792e696f000f696e666f407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490b34a3937b9efce6482a21b7e92055e74bc9b182ded5b0cb86e6f7706090c916f60e8235b8fe51a": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490b7f1fb67016ea9caaeb20361e77d9114bdd85dc196c33e15da72f4c28699085c388a3ecaa17f1e": "0x04000000000200000000000000000000000000000000034c560000000000000b404b7573616d614e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490bfa3ccf24689448eac08398a7441d30d6c48e1cce03d40c4ed1d8bf6764945925e5af4c3c4d362": "0x00000000000000000000000000000000000554616b6f0c53686962612054616c65731968747470733a2f2f736869626174616c65732e73706163651b4074616b6f736869626174616c65733a6d61747269782e6f72671d736869626173637265616d73747564696f7340676d61696c2e636f6d00000b4044616e636554616b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490cb5bb0ae9f291ede1c4c24739f2202961c22424816397b191bd85996985270375c21891d637f5e": "0x0000000000000000000000000000000000124249472d424f472d56414c494441544f52000012406e617465333a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490f5f7cf3f6d8adb903ebbf02f14c17e429da07dc1a372fdd67074849faf98fe93487ddf92f7b869": "0x00000000000000000000000000000000000943616e6172696e6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471490f89f28c98fdb9f9e14a9dd8d2928325d66d5987142ffd9209ea874b9a0d50a07492bd69e94c612": "0x0000000000000000000000000000000000104a616d657320536b7977616c6b657200000000000008406e6654555552000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714910e21740f651a39fa507c9a5d3879d4a7d6654c6a35fef974094bf5d16203d6312f9ea1358ec660": "0x00000000000000000000000000000000000a446f747765696c65720000001c646f747765696c65726f6666696369616c40676d61696c2e636f6d00000b40646f747765696c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149124e4dc6df447e792a0166ebf4b3f197986796419c48c9b61d29369acf5dd4a47ea2c7bd0393a61": "0x000000000000000000000000000000000005416c657801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714912655d634b54e9a086de7162fbfa0b91a67eee94b697646028edcf484ae78fdc0627e7eef1b2247": "0x00000000000000000000000000000000001353756257616c6c6574204f6666696369616c001a68747470733a2f2f7777772e73756277616c6c65742e61707000146167656e744073756277616c6c65742e61707000000e4073756277616c6c6574617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149155332d1321391214cd612ff7f390b9e90584767a00a4e9b740b61c0f2134698bbac79c6649764d": "0x040000000002000000000000000000000000000000000c6d7968656172746f70656e00001c40616c6578616e64616c6578323030373a6d61747269782e6f72671a616c6578616e64616c65783230303740676d61696c2e636f6d000010404c61626f6461537665746c616e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714915734949771ed554038aef7c58b83c4252c3ac69b38bf7d3df85ce136459a69bea073e24900423d": "0x00000000000000000000000000000000000c54696d757220447562696e0c54696d757220447562696e2068747470733a2f2f696e7374616772616d2e636f6d2f74696d75722e647562001574696d75722e647562696e40656d61696c2e637a00000d4074696d75725f647562696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714915d6c6518f7b5c4c0bbe78d8d6ec69c7ba07f331f2c491f94b7a53986caee31f97011905d5a9b5c": "0x00000000000000000000000000000000000c43525950544f4c4449455200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714915f093e86a67b73629b918a21dae886bcc5cc6f7dead2bb9bcf0a25e7e376ba138882a91d473e31": "0x04000000000200000000000000000000000000000000126b7573616d612d70726f64756374696f6e0000001c637269737469616e636861706172726f6140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149160a699257bae5812e991b50e700d1e52b37300ef0f51538197c0509d9d0b3d77482b4c1a3da566": "0x000000000000000000000000000000000008484a504b444f54104861797468616d204a6162626f7572000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714917bdd412b89d0510cce9e210c473fd1f20178fe889c178956ea1cf325c54b1a439a88bc62fe7851": "0x040200000002000000000000000000000000000000000ee29b93204e4f565920e29b9320054e4f56591668747470733a2f2f7374616b652e6e6f76792e707712406e6f7679343a6d61747269782e6f72670e7374616b65406e6f76792e707700000f406c6f73745f696e636861696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714917ee600d4ff956c28f9a4e7cff6010ad028c4cd82432afde4dd1269efafcd281016daebf7fe0e16": "0x00000000000000000000000000000000000757697a6b696400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149180662af89403432204f9f580904c74f61c9606d97ba4b8d3149d5a689173b3056a9bf43d003039": "0x00000000000000000000000000000000000673656d616b0753657267657900001673656d616b31383032383040676d61696c2e636f6d0000114067463138764f5639396d635972516b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149185893c3a05ff480488b1a94fa6c2e250d13576c5e3256b263ac9ce966a7ef6e7766921d8d61738": "0x040100000002000000000000000000000000000000000559616b690c53686962612054616c657318687474703a2f2f736869626174616c65732e73706163651b4079616b69736869626174616c65733a6d61747269782e6f726715736869626174616c657340676d61696c2e636f6d00000c40736869626174616c6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471491b543380b6013ea301ca9d61b74c9aaa1fdd9e53249ba415ee86fd4d15130e9dc7ee8d713456b33": "0x0000000000000000000000000000000000076b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471491b5f4bf2b18b9e7c01c495b45751393a71693e7abfae197cbbe0eae7233a463f7be2efd6f13444d": "0x00000000000000000000000000000000000554626f79044f2e4600001a7368696e6570726f6a65637431303040676d61696c2e636f6d000010405348494e4570726f6a6563745f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471491b6ef1b478c037f5a64d688b6d7eed3e5d25e0c69421de9a10db233c6635166a7be9b61ebb2a433": "0x000000000000000000000000000000000008526f746865727300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471491d6804bda44e439d21ffa34abd2709779ccdef7aa0aaa292c32a986ff3aa6faf7c0af56d47cca5c": "0x00000000000000000000000000000000000541646f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714921d891bcf4e728ce683743954d0cb555a54ab21cfb8161f74e689a051d1ac1dbbb94df70be3d81e": "0x0400000000020000000000000000000000000000000012504f5745525354414b45204b5553414d4100001740706f7765727374616b653a6d61747269782e6f726719706f77657240706f7765727374616b652e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714925643626036602a9a92ad7c6dcc51fec9f6d98f8316406ca42bd04dbb029d3ce454330a20fac077": "0x040000000002000000000000000000000000000000000b5473756b6920f09f8c9500000019636f6e74616374407473756b697374616b696e672e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714925e96c4a6796256c0374918863d100dcc69bcab798ce6d52ad129a8b35e170ba00ba414a7be5e70": "0x00000000000000000000000000000000000b487970657220436c75620b487970657220436c756200001a68797065726c6f636b6564636c756240676d61696c2e636f6d0000104048797065725f436c75625f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492688eaced7f4cc5baa8a189ca8c65b64a3fdb0dbeac6a7ca2c00b27ed799f8e5f61b8af0621a162": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149275654d23da48139280f3396e4673c4475c8ae2f041cac0fce02e2551e1beb6d80df55667c66275": "0x00000000000000000000000000000000000e4e6f7261436f646520f09f92bb001f68747470733a2f2f6e6f7261636f64652e737562737461636b2e636f6d2f00166e6f72616c69753038333040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714927911426652f14cf4492a28ead0b315fc68069bcc39470c409d12b4e48259384d63da411bad0129": "0x04010000000200000000000000000000000000000000184d61726b204372696e6365204b534d20636f6e74726f6c0c4d61726b204372696e63650000156d61726b6372696e636540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714927d23a251f0902d7c4f2330f182fd91474849a74d6c681264aeeb57213af82a90fca83248b37477": "0x00000000000000000000000000000000000b446f7453616d61487562055a335230000015446f7473616d6168756240676d61696c2e636f6d00000c40446f7453616d61487562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149297e19198fb83a580540a824b03b96ba36fd30af41f8de9de93ce30ef8a16299bb9d938e62f3f68": "0x00000000000000000000000000000000000667626163690000124067626163693a6d61747269782e6f72670000000840676261636958000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714929c071a7d0883d10a6fa0a39e064f33dfb2fb47e30e19aaa7bdd13291d582535703ba7e8b273528": "0x00000000000000000000000000000000001247726561742054656163686572204b657a00000000000011406772656174746561636865726b657a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492ac2b44e9df4524865ca05d8bee6d8b21d7c48b543c5a154f5cab3079deb6718a775707c86fff5f": "0x000000000000000000000000000000000008726964646c657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492b894b9740836cdce2e98564f421ca69a64608d68480080f5f317f4de4e400af3c065181e0c8a11": "0x00000000000000000000000000000000000d4c6971756964204368616f730d4c6971756964204368616f7300001a6c69717569646368616f732e6b736d40676d61696c2e636f6d00000e406c69717569646368616f7335000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492bd0d654a0b34ffb640b7373eb438306069706e984d4725d91690d4685648f2caf3d1aef39b4003": "0x00000000000000000000000000000000000a52652e4d61726b656401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492d3b8b7eabbcd46524842180999b774cea511715b38f557018c75b586d0fbebaadb52adf0a44447": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a5374616b654261627912536b696e6e7920426f74746c65204c74641668747470733a2f2f7374616b65626162792e636f6d0016636f6e74616374407374616b65626162792e636f6d000000001e68747470733a2f2f646973636f72642e67672f5679514558584564556e00", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492f879f180f6a02408b712a589f5cb71cd7094809785ab0a924358d3cb52b27efd4933b6efc14963": "0x000000000000000000000000000000000010446f6e446965676f53616e6368657a0000001c676176696e776f6f6469736d796775727540676d61696c2e636f6d00000f4053616e6368657a43727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471492fd5ac6793d3e958ea2f0d9cd27c799fe691f45c532865beab623b9225e078d980b1b2e86b3026a": "0x0000000000000000000000000000000000194b5553414d412050415241434841494e205354414b494e4700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149302748bb1f52508b2ed4e35c8a3e577dbd30e2bdc03b475588c236484315857088e86bc74df1b31": "0x000000000000000000000000000000000003594800000011796172636f6840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149306f9d2b20faa1224ec6e0f9e1ebb3e0a363ea3ad99d21dcc0f15b2c9587349d2e843d748f71232": "0x0400000000020000000000000000000000000000000007616c657865690000000000001040616c657865695a616d796174696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714930a2be4692e62f7e26e878810d319dd39d85e013a0cac3f232e6d9682b1d829bc3f7830ade12855": "0x000000000000000000000000000000000006736172616d0000001479756a756e31303138406e617665722e636f6d00000d406b696d736172616d313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714930c02ed2be38f57f8f51f44c3305ee50a92b2e1bac6b7103abbff664718d06dc10f3112c82bf61a": "0x00000000000000000000000000000000000d43726f6d6d2056617264656b0e437972696c204361726c69657200194063726f6d6d5f76617264656b3a6d61747269782e6f726719637972696c6361726c69657240686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714933b413030a2193b0e4d677832209548c8712ca7ba1e72a885bfea75f7c639552b20b7a395df3f70": "0x0000000000000000000000000000000000010101010100000c40446f7453616d614c6164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149345f7e620413feb30b15f14ec3f05e821524d0bce378ef332d19b60476d88870deddc5e9382af16": "0x0000000000000000000000000000000000115065746572207c2047656e736869726f0c457175696c69627269756d1868747470733a2f2f657175696c69627269756d2e696f2f164070657465725f7374723a6d61747269782e6f72671770657465722e7340657175696c69627269756d2e696f00001140457175696c69627269756d44654669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714934cae89366fc06960aded936fc747de820f80ae1ea2f02671395df2e87f5b8e296545d4b3d0bd29": "0x000000000000000000000000000000000006486f7368690545676f722168747470733a2f2f7777772e61727473746174696f6e2e636f6d2f686f73686900186b68616e656e6b6f2e65676f7240676d61696c2e636f6d00000f4045676f725f4b68616e656e6b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714935e5672d20bc186d483a43afa5895b93249e9cbd00ffbea478ae2fcc21f5aaefb6fd9cfe30f4a4f": "0x0000000000000000000000000000000000064e696b546f104e465420436f6c6c656374696f6e7300001663727970746f64696e657240676d61696c2e636f6d00000a404172744a6f686e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493641724f6b9e368deffe6c6afb3c290639377d7cfb16bf69dc9039b46014f6eaaa13b55a71aa606": "0x000000000000000000000000000000000004646a6200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149366d4cd051fda98c47741beea936cd81fcb6221e2f2f6c9d6b875ed92133706a4b8eb70271fd003": "0x0400000000020000000000000000000000000000000014f09f8d9320506963636f6c6f6e6520f09f8d9300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714937b9ba6877f7e80f80761baccb8c83580e6a9bcd98c05d11ebd9fd6c666fc09f00b055daa4d6e2d": "0x00000000000000000000000000000000000a4672656e636869654200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149390a024fbd35d6154bc9d96ec0ac259bb9cfadc33fe9ed4db3ab50168b329e86d68189e9ab1451d": "0x000000000000000000000000000000000017e29a944772756d7079204a61636b2046696e6ee29a9400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493a9c3c86003c444c4f1fdb0c67daf9e2302565a974d166ddc74b65219694369569eedd43e2bf308": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493c499446dff130948b985dae79adcb9becca19ca2eba2aada6416020dc01abd59f8b4419cd8a002": "0x00000000000000000000000000000000000b4d41442043524950544f0000000000000b406d617474756e636869000a6d617474756e63686900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493e08f85a76d37a7328b6e90d27539b8224a0ba4139f305a6bb2d97540a722e2ad470ecf43b4a341": "0x0000000000000000000000000000000000084d4c4e204b534d0e4d696c656e204d6172696e6f760000126d696c656e406d6574617079722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493ee60d0d680c677224705fc7cbd3f254286b3e9fa19a113267a4628d213884d6a83179c41206b08": "0x00000000000000000000000000000000000a507572706c654254570000000000000f405265616c507572706c65425457000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471493fa88b509112c5cc8310cf96893e0013bdf5ad21fbdec7cc9423de8ddc27c30022c47fdf4c3cf11": "0x000000000000000000000000000000000004e5bcba01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149401230589822c5d48efa32a0569824a03e7a969f40d50b2ec796164b4d774d20d0d488513f3eb1b": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000000e33394b7573616d6120f09f998f00001a406175746f636174616c797469633a6d61747269782e6f7267116b656e6c303940676d61696c2e636f6d00000b406b656e736572736f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714940d03ca7ec7ffbbecf9b1d2f50b9518f91e67d42a34bc73512d68f34a8371f5c45ecf9af2d8570a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149414b9a45988e9b186717d35d7cfe3c6fe1c4996268614f6503e8c2caf64521fd9e14b76c57a9b07": "0x00000000000000000000000000000000001047616c6163746963436f756e63696c001c68747470733a2f2f67616c6163746963636f756e63696c2e696f2f00000000114047616c6163746963436f756e636931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714943fc2ac54f4c37ccc10dd1946b0fc65c8993ff7f47052713e9aa4b1cb72c913bd397c34adf4f949": "0x0400000000020000000000000000000000000000000009416264756c62656511416264756c62617369742053616469711a68747470733a2f2f74686973636f696e6461696c792e636f6d000000000a40446f63416d6f6b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149446885b0b18680ae8e0ac0aa68a0c138a3aa84813f0accae4ed7d6ae4b4905495026f16eda4e069": "0x04000000000200000000000000000000000000000000097370617a636f696e000000137370617a636f696e40676d61696c2e636f6d000008407370617a7674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149464a51c61bcb648ee56126859de69a3539f0e8910ca7e775243f18c6257954a65e020eb229be912": "0x040000000002000000000000000000000000000000000de29d84e29d84e29d84efb88f00001740696365636f6c646e61743a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494673f91681becc4565d3c8cd1fcc93ed837d3f9830e333659cd0962ae7fadb7c87899d0b1431822": "0x00000000000000000000000000000000000e524d524b204d69677261746f7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149497fcfa74b9bd271c1fcc964adadc336e55f884716aacbe0bbf32540003b0279a158cd2748f3f75": "0x00000000000000000000000000000000001e59757269476969207c20524d524b2e617070204661766f757269746573001668747470733a2f2f7777772e726d726b2e6170702f0018797572692e6769726a616e736b6940726d726b2e61707000000a40797572695f676969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494e8a3699d4cfcb72cb3165d3c084782aa0a3fdd77a70596c63814b3fc1ac0999fdb2afb5e1f4f40": "0x00000000000000000000000000000000000652656e4f730101010100000a4052656e4f735f5250000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494ed5c295f9bfa2588f28e17671ba1808d7b02cd3caaf80113066a467127666f4d80afc50bfbc127": "0x0000000000000000000000000000000000097a6f656d63666f78000012407a6f656d633a6d61747269782e6f72670000000a407a6f656d63666f78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494ee9a4fadbb7dadbc5d026a7be48559570fc2a3a72d59b58d5971aec58530ab740c35d9f6a29416": "0x0000000000000000000000000000000000094c617373756b6b61064c617373651174656b6e69696b6b612e63727970746f000000000c404c617373756b6b616161000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494f3111594a138697873a3c888462af6d6717791ad60019b0b5fdbaaa5aae703c4cf9f95766c5479": "0x00000000000000000000000000000000000941657465726e757300000013616b32373530616b40676d61696c2e636f6d00000a40616b32373530616b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494f3132d9220bd5bda6eed44e320bc280e758203c8a184a3fb21e875e860be78e2c479bd7b851e08": "0x0000000000000000000000000000000000044b656d000000156b656d706f6c6b61667240676d61696c2e636f6d00000d406b656d7373737373737373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471494f5bc61099238f7c904f1e0902db076f8b1b593db28140bf6bace7d8ff5c7bf8968728098f13afc": "0x04050000000200000000000000000000000000000000124c696768744769616e745374616b696e670c4e65696c2048617272697300001c6c696768746769616e747374616b696e6740676d61696c2e636f6d00000f404c696768744769616e74496e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149512e7cebb2ab2b2206dd955d4ade8d59bab18cba031e664ae888491d173084bc9a0efabf0be195e": "0x040000000002000000000000000000000000000000000753616b7572610000174073616b757261746563683a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149525351d4777dc940efea838f312ff60ff62ce2914adfaaeb41d81dc4b81a8bf0a41be031e79c918": "0x00000000000000000000000000000000000e4a65737369636120416e67656c0021687474703a2f2f7777772e6a657373696361616e67656c617274732e636f6d2f00186a6573736963612e616e67656c40676d61696c2e636f6d00000d4063727970746f6172747379000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149538c438fbcd89d8988376cfad02f636e059969036a05034046bd3a59b97c57cf23b272c9e8b0d55": "0x00000000000000000000000000000000000a4672616e6e694265650b4672616e6e69204265650000176672616e2e6173656d6f746140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149540f12061c8ade9c0114150a79f0572d3d86fd1411ac282bd8b62beafdd7b4bc2d5cbacb48f3a55": "0x00000000000000000000000000000000000a42656c6f775a65726f0000001862656c6f772e7a65726f2e747440676d61696c2e636f6d00000f4062656c6f775f7a65726f5f7474000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495523a80019f8438ccd28a48526105f8ea01f27c133b3971a5d80c26ded2fe4a695b10ab9875136c": "0x00000000000000000000000000000000000642617a7a7500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495636345d78c41f24c9006835bd0eb918b1e1a7bad79b1bfc0f70b752acb9dc1aee47819e4df0f06": "0x00000000000000000000000000000000000a736a65766572657374055975726900001670637072696f726174736a40676d61696c2e636f6d00000d405375766f726f7659757275000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495bb65b41d18b99cacee95ed0e6c831a02112564c89d87a67684229e79a702700f91009c34f6e17a": "0x00000000000000000000000000000000000b6974734e6163686f373900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495e5354b81f0f460da9f7fd3d9612a68d2ead69dde53297b172b7db514d0d261e7c5be987df7f32a": "0x040000000002000000000000000000000000000000001453696b207c2063726966666572656e742e646500001540646576305f73696b3a6d61747269782e6f72671a73696d6f6e2e6b726175734063726966666572656e742e646500000a40646576305f73696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495ee9607d490e8687a1cc366cab83c63f1d8a6ad090b038ac6057e235006619bde17ac85597be109": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495f3f5d4f1926f98b2010431ca44985a2cb0950ec7564333c86983dcd44b85c093e16723fbe19031": "0x00000000000000000000000000000000000953616d75726167690874697a69616e6f000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495f941adaa91654a28322946bfaec48af9564e56ee4134655dc1748ffc206c3694a9c6bddbe8332f": "0x04010000000200000000000000000000000000000000136379626572627261696e2e6e6574776f726b001b68747470733a2f2f6379626572627261696e2e6e6574776f726b001b636f6e74616374406379626572627261696e2e6e6574776f726b00000d406379625f6e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495fb7c212eeb16bc3cbd5d669b224d75f6d54031abdac468efddba8ea48d4ec25f39996687e6bb23": "0x00000000000000000000000000000000000e6b7269735f616e66616c6f7661124b72697374696e6120416e66616c6f766100000000000e406b726973616e66616c6f7661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471495ff23600e669c4a60deb73d358494181a302d0ad149af4aa52df621afe024c6179d7d0b39929e15": "0x00000000000000000000000000000000001346756c6c4e6f6465204d6564697461746f720101010100000f406e6f64656d6564697461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149600c2a7db131074ea2f5d8d81a9e713040a65a058dbd3304f787f82be1b7d7fa7e136193ccdcb62": "0x04010000000200000000000000000000000000000000074c4950454e4715e5b2b3e588a9e9b98f204c6970656e67205975650016407975656c6970656e673a6d61747269782e6f7267147975656c6970656e6740676d61696c2e636f6d00000b407975656c6970656e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149629ea052725c3692cea1b9d395f1497930efb3c25135fff46e120b747d490cfd62c66f4573e976d": "0x04000000000200000000000000000000000000000000134554484943414c2056414c494441544f5253000017406576616c7561746f72733a6d61747269782e6f72671d6574686963616c2e76616c696461746f727340676d61696c2e636f6d00000d404556616c696461746f7273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149639866340f488369cb0d4ddd32f9332dac7059de238b8e489afb55502d1756d7f50b78b58e20c70": "0x040100000002000000000000000000000000000000000b72656470656e6775696e0000174072656470656e6775696e3a6d61747269782e6f72671a72336470336e6775696e4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496466553cdf2029286f520b752675b6242f1b3c6e1dcd704058e3f74f81fba9afe10aa8113dc5068": "0x00000000000000000000000000000000000c4d617374657272756c61780000000000000d406d617374657272756c6178000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496627741b7418892667eb6da0231e2e63b881d8a8936e6bedadbf4a4f3900e5e657301d410c8bf02": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714967dd10b13066df77243fc7f5f476ee7c5fad9de673f1ccfdf59c3e92530c09d6d584ff19452c87c": "0x0000000000000000000000000000000000115361796564406b7573616d613230323100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714968689303d5e0ea80686d249850c389953211c7ecd77d76f031bc8e9e0289b51f602fc8097122324": "0x0000000000000000000000000000000000086f7461626c656d00000000000009406f7461626c656d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149688ac8c5537830f120207cc128159479d48c4bd2213274517c13fda02c1783d2f38232ff1feb11d": "0x00000000000000000000000000000000000e4f6d61725f5365616c7469656c0e4f6d6172205365616c7469656c1c7777772e61727473746174696f6e2e636f6d2f7365616c7469656c00176f6d61727365616c7469656c40676d61696c2e636f6d00000e406f6d61727365616c7469656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149696dce1ccfdcb0910908d002661d99caef8f6cc090f6f3f9853dc554b78dfada32b219398840c0d": "0x04000000000200000000000000000000000000000000147468697369736e6f746d797265616c6e616d6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496a0953ddf0eeb24d71c3176c00b028a841880392ba8cd903836b938a971ad12857ca842ba29973b": "0x04020000000300000000000000000000000000000000114163616c6120466f756e646174696f6e001668747470733a2f2f6163616c612e6e6574776f726b12236163616c613a6d61747269782e6f72671468656c6c6f406163616c612e6e6574776f726b00000e404163616c614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496ad8bee6040ef3c5b473ba833712cddcb59d2569e9f2523d66f2ac183c8470e74077682262eb486": "0x00000000000000000000000000000000001a4e554a4120484f4f44207c20534953204f46204d592042524f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496cb59db66691c528e583eded93da9417b2c0b6dc1446ed4704f3553d065b4d20efed3a1e0c93626": "0x00000000000000000000000000000000000e4b726970746f66696e616e636500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496d9cd4e5f65d9cf821ba83ece24cfead00c045d6873d0f80cf12503a812e285afd007a6a9d81328": "0x0000000000000000000000000000000000087365616e5f66620a5365616e204368656e147777772e666f7267696e67626c6f636b2e696f155365616e40666f7267696e67626c6f636b2e696f157365616e40666f7267696e67626c6f636b2e696f00001b68747470733a2f2f747769747465722e636f6d2f565365616e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496f4aad0cdd32c3e8a6d7fd62a2ca5609d25c2574a275de76a6fc5322482aa0b0d29f0a8f8f83b53": "0x040100000002000000000000000000000000000000000d706f6c6b61646f742e70726f001568747470733a2f2f706f6c6b61646f742e70726f001368656c6c6f40706f6c6b61646f742e70726f00000d4070726f706f6c6b61646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471496fde7fff7b4278c8adee5c0c1d45c80592e817fd4914806f2929fbb1c80e8687faa8ad632c32e6a": "0x00000000000000000000000000000000000b5175616b7a204c6f7264000000147175616b7a6c6f726440676d61696c2e636f6d00000b405175616b7a4c6f7264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714970399168fc6b4bcf20436bc406afae9bb15efd905cb4ab40b338e14a2bfda1c174859cdb06c9b6c": "0x0000000000000000000000000000000000087846756e6e6579000000147866756e6e7930363140676d61696c2e636f6d000009407846756e6e6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497087a3a72f4f8b4c8f553a628a3ef2534f91452ee33fe84549dc8ce3fe330f07828af345f52f849": "0x000000000000000000000000000000000010636f746f706178692d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714972eb164c7f5e4f208a0291a4b1bafb431607e66865c9fc5538a3eec1e9e859431a2265b701af077": "0x0000000000000000000000000000000000094a61737a4469617a000000146a61737a6469617a7a40676d61696c2e636f6d00000c406a616369656c6469617a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149733ee530cd28230b8745db0b5f85fae7e64f061d3d4c058cb4f51af12097a6fe666bd81b8251d7f": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497389e32ef925ccd6c0197856b35c7f631f5aa8d9cfd83f7e75202b0d821e67d2f344e4e4b5fc10f": "0x040100000002000000000000000000000000000000000d506f6c6b617373656d626c790d506f6c6b617373656d626c791968747470733a2f2f706f6c6b617373656d626c792e696f2f001668656c6c6f40706f6c6b617373656d626c792e696f00000a40706f6c6b5f676f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714974bb4bce2ea42e09224219c0ac40ab90370be268d128fdc9528fa2effc0e28e39ed400a14536e08": "0x00000000000000000000000000000000000953616769747461570545474f52000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714974c91f6b33b06ff9437d00e9bdb34a8bfebb9a526f16a3eec890d0003c6d5f9080a10b04c00b112": "0x000000000000000000000000000000000012506f77657220486f757365204d656469610450484d00001c696e666f40746865706f776572686f7573656d656469612e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714974f1452190fc371fada8b71c5d2906a12a63adb35dac00d22349528af0d39e9dcf9e8d43d828878": "0x000000000000000000000000000000000004504a530000000000000d40504a533034313239383932000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149751a6b5ec392a79700407f5904c7ad8b610fdb40d1a8a1047efa8f00e0f2320791b6d7da8a69103": "0x00000000000000000000000000000000000c61316b616e646175726f7700000017616c2e6b616e646175726f7740676d61696c2e636f6d00000d4061316b616e646175726f77000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497890c1341c73b0186f0b4a93947c72764f0bf771a5652371344df481a206d2d25e9b5af88a0690f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149794f920c8bc28ab34e5e97e6921f126dce794b8122543bc3923d7c7abec719405f5822d8818677a": "0x000000000000000000000000000000000009416c6578204d747a0000000000001040416c65784d617274696e657a5f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149797b884384074cc4c0f34840840d39f88e5d7d2a55caa7416961c17c29ba9552206e5a0bd54093f": "0x00000000000000000000000000000000000a4c75646f63726f737300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497b2a64b241954e9a2ee169c829a65fef4ebadc97883a35a3694c2f2995a3cc61abde4fc9412a91e": "0x0000000000000000000000000000000000124272756e6f207468652043757261746f720000000000000a4062697466616c6c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497b7c5b692c6ced4162ad78b4445890bb6f135b583b9775a5979a25d0065a55310943c8d090cb97c": "0x000000000000000000000000000000000007564943544f52000000136d657461766974694070726f746f6e2e6d6500000a40566974697265756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497c4bf937bc625125ade8b34a0f0a1a7975476df53f96cb3b0fc5c4043716af5bc833b4c194bbd79": "0x00000000000000000000000000000000000a616e6e69655f6b736d00000015636f6c616e6e636f6c6140676d61696c2e636f6d00001040616e6e69655f736f726f6b696e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497ed1dcda161ffc758eaac5ecb89b593ea486a2581dbb2df07745b96a7d49125d3bc33c654015243": "0x00000000000000000000000000000000000b4f7a796d616e64696173054f7a616e000000000011404f7a796d616e643737333635373636000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471497f069f11577b05c5414c8bde77dbaa6324c3261025c2d46399d615712a539723ab89fe736577a05": "0x000000000000000000000000000000000004416c690000000000000e40616c696d617277616e693130000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149814eae07bc4079400da54310700ec4bd026010c3ec89737129446f75a25c0daf55cf6d432f6437d": "0x00000000000000000000000000000000000c4f6e6976657273654e46541b4d2e205665726c6579652026204d2e20426f73736368616572741b687474703a2f2f7777772e6f6e6976657273656e66742e636f6d001c6f6e6976657273652e6b7573616d6140686f746d61696c2e636f6d00000e404f6e6976657273654e465420000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149837c343b899ac37125ab2fe5c8d89a80539712b54765ee2e8414f15d23e96f9d1413ed04bfa151b": "0x04000000000200000000000000000000000000000000116c696768746e696e672d737472696b6500001440736d6f6b6532363a6d61747269782e6f72671d616c6578616e6465722e73686174756e6f7640676d61696c2e636f6d000011406c6962657274617269616e313937330012616c6578616e64657273686174756e6f7600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714983aa5b573c0b22174017a0c081a6b17c99ae305b6a0df072a6786bea22d7c9eea7da4cba2938862": "0x00000000000000000000000000000000000b416672696327417274730b4166726963274172747300001461667269636172747340676d61696c2e636f6d00000a404166726f4e667473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714984b0aa6953965fc57f62eb53f8a94086775a809b67bfab4ec5127e8fc6d0e9b92901d40e4536f8a": "0x00000000000000000000000000000000000a4e696e6a612042697a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714987646fbabf7f0564a67865ebf0419d4e5cba04612864fac7999130a5294e4687512bb8c9bf35b35": "0x00000000000000000000000000000000000a4b696e6720506170690000001530786b696e677061706940676d61696c2e636f6d00000c4030784b696e6750617069000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471498844ce2f37772c214f96c193e11618ef9d1991cf06367361e5a5e2d1a91eb44146ea15c240e4819": "0x000000000000000000000000000000000010746573742d706f6c6b61646f744a5300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471498ccb53a68ae0b0f4caaec0669936d9c7e402ec3c4ccfa546ffd288f015cde72f99b800dae71e932": "0x00000000000000000000000000000000000650617272790000000000000a4050617272794e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471498d79f063b9276569ebeef0150a33357023e678bfff549602e6943b5b85d8bfdb58473992fcfaf63": "0x000000000000000000000000000000000008546869626175740000124074626175743a6d61747269782e6f726700000007407462617574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149925e4c33888e571eca22b1d356b4618e38499b2c2616bccb048c2a835af5cb142b77ca799622f59": "0x00000000000000000000000000000000001043727970746f5f70656f706c6555411043727970746f5f70656f706c65554100001567656d696e693834353540676d61696c2e636f6d00000c4067656d696e6938343535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714995bf0301d5a832de2be45f0061ce0bfd9ef023a354bd1beaa9bad14345aa18c95f9e05043dc1641": "0x040000000002000000000000000000000000000000000d4b495241205374616b696e67000015406b697261636f72653a6d61747269782e6f726716706172746e657273406b697261636f72652e636f6d00000b406b6972615f636f7265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714996507482af7276afedae0f19e624e485c0a2b8a9aa4b65608c89cc9908f0f90aa5567ea384cfe7e": "0x00000000000000000000000000000000000c536f6c6f7665692e44414f08536f6c6f7665690c536f6c6f7665692e64616f000000000c40536f6c6f76656944414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149975fbaedde7756e12840f0626ac847d41089c4e05cf0719c5698af1e3bb87b66542de70b2de4b2b": "0x0400000000020000000000000000000000000000000005733063350e446176696420426172696e61730014406461766964623a626c6f7175652e7465616d12646176696440626c6f7175652e7465616d00001040696d6461766964626172696e6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714998ba9677cf5170c0e987cae440058064c72c16ad03b745e151a1a33f62d51f011f7888efa22605a": "0x00000000000000000000000000000000000470383701010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714998cd9a07d23d28d50ef3cbba6eefa5127e662a1286c69c3f8cd10aa328d394df9e69919af449b45": "0x000000000000000000000000000000000010496e73696768742046696e616e636508676f7374616b651368747470733a2f2f676f7374616b652e696f0014657269635f64776a4069636c6f75642e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714998d2d283f44bf3e5e034f68b3255263d1b64c5d02c720da4748d990576a032dcf42e6e8b02dc658": "0x00000000000000000000000000000000000744617679637a000000000000094044617679637a5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471499928322b885a79b32f055569357341d406869cefbe52ef0ea059834a52e4de30b7e9306b364c56f": "0x0000000000000000000000000000000000074f636172696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471499ad9accdb6256f3d8783497b4c06f05dfa6ca91a0502e77ea7ffbc5c33c7142a5d9d1f0322d783b": "0x0400000000020000000000000000000000000000000007535041525441000018407370617274612d636c75623a6d61747269782e6f72671b7370617274612e636c75622e3230303040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471499adee9a95267a606aa596e011820c7af6fcc90e52499158d286106baded690924651f7c9a4b8114": "0x0000000000000000000000000000000000044b48520a4b6e7574205261656e0000117261656e6b6840676d61696c2e636f6d00000a404b6e75745261656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab870471499d69c79e3dc754e8e80ceded3cf93fe205a4e71d4bfd6b8419cdf12d85244bd7fe7c82733417b51": "0x00000000000000000000000000000000000a4d696775656c616f6a0d4d696775656c204f7274697a000b406d696775656c616f6a146d696775656c616f6a40676d61696c2e636f6d00000b406d696775656c616f6a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a1921d6885d9479040279d8f4ad6cdcf1792ac373cf6d44ecef27e6ab4a61a9057602b37b6dd028": "0x000000000000000000000000000000000006497a7a795f0101010100000b40497a7a69706f656c5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a217f9388c8f902d66ac04ad10dbb5ac16a6a477dce727d647cbfd809d18b150cb402ae1569b555": "0x04000000000200000000000000000000000000000000066d63666c790000000000000e406d69676874796d63666c7931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a224cc249859b470efa942be958c4d368e9a0564ce34aa652a9c11727669dfc841dc73e8403497c": "0x00000000000000000000000000000000000949686f7220322e3000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a24c66abe29ea3716d5b643fdfb1b22d5dfd3a50157104df0580c910d2754987afc25fe0aaf5827": "0x040400000002000000000000000000000000000000000b556e69636f6d62617365000000166e616f6d6174657469383140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a27fdfcf005531660a973fbc6b1a63e1db41101515df4eecb19bf04ad29e9b5d46b37c919c10975": "0x040100000002000000000000000000000000000000001754686520446f7453616d6120457870657269656e6365002168747470733a2f2f546865446f7453616d61457870657269656e63652e636f6d13403238646179733a6d61747269782e6f72671c767240546865446f7453616d61457870657269656e63652e636f6d00001040546865446f7453616d6145585043000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a359c8738cb74379c4731457546007a4ad4e09ba0ff6cc40477c2c2984833245706d8ed2cbeaf61": "0x00000000000000000000000000000000000a6d616b6b616661646102530000196d616b6b61666164614070726f746f6e6d61696c2e636f6d00000b406d616b6b6166616461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a3e5bfc049b0f4a20c4f3295a3fee34bc398fa31f6efea34220772fe18bbe8dae6db750f531e847": "0x040100000002000000000000000000000000000000000c6b747a2e6f6e65204b534d11476975736570706520436f6e736f6c691068747470733a2f2f6b747a2e6f6e6511406b747a653a6d61747269782e6f7267116769757365707065406b747a2e6f6e65000007406b747a5f65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a55a8f4ff0cbfb7d01ba1d7366983e4c464bdf4eb0572ed51599225d503fd0cb750fbdc945c244e": "0x000000000000000000000000000000000007657a7a656b6c08457a656b69656c15696e7374616772616d2e636f6d2f657a7a656b6c0116657a7a656b6c656d61696c40676d61696c2e636f6d00000a40657a7a656b6c636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a60ad0be33cf6b14e533a2fd6a6ff9987c6dc0659b6b20de1ae31461bea7171518a927287b1fd0f": "0x000000000000000000000000000000000007e9a39ee9b8bd07e9a39ee9b8bd0101156733393433323039333740676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a6f18c4a47ae9cc5837571d1c2bb8e45ce2913ac68ae693a05769b8396a68663457f3e186c4ea20": "0x00000000000000000000000000000000000a524d524b5f4d4152530c4d6172696f2052657965730101166d6172735f39323036406f75746c6f6f6b2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149a80b9fad3bcc75d94b26c1afb14feaf0a625a144350b10268e91f2a4e4c615cdce69fe17096453f": "0x0000000000000000000000000000000000044d415800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ac6c20f1672e23e22680983f848c5191bedb6f13277b5c078f54cce890f70aa0578d20652ada058": "0x0000000000000000000000000000000000085061756c20486f0b416c657373616e64726f00001a63727970746f2e73616e64726f373640676d61696c2e636f6d00000b40416c6543616d6d3736000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149accca3fde6b92f7ac7f6c84e2930d1ccd60d6a317040f1ffba1c704dbf5a277a324262eb3854c1d": "0x00000000000000000000000000000000000742656e204d6f1442656e6a616d696e204d6f747363686d616e6e1c7777772e62656e6a616d696e2d6d6f747363686d616e6e2e636f6d00106d6f696e67657240676d782e6e657400000c4042656e4d6f696e676572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ad5a4ebb0ba372da6abbcd974cf24668c6e67a248f1f84c54f1737cf8d5547148e0c5835e61ed69": "0x0000000000000000000000000000000000074361707065780743617070657800000000000e4063727970746f636170706578000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149adc88690451f27780ab25ea34cbc164f9bb13a28523b162cb4ed572b57e7c957f868c3d486f326b": "0x00000000000000000000000000000000000856616c686f6c6f034a41107777772e76616c686f6c6f2e636f6d010f6a614076616c686f6c6f2e636f6d00000d4076616c686f6c6f6465636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149aea00c445f734edbaf3f15b9e83dcfc18b50fe91e601fdf446c008c72c3d17799c21a64877e8d3a": "0x04010000000200000000000000000000000000000000125374656562657220536f6c7574696f6e73165374656562657220536f6c7574696f6e73204c4c432168747470733a2f2f7777772e73746565626572736f6c7574696f6e732e636f6d001b68656c6c6f4073746565626572736f6c7574696f6e732e636f6d0000114053746565626572536f6c7574696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149af67195cc171e66489f12b69a3d689791aae4d4f8fe89d35e1acb4bab87327360bfbd13fe8a324d": "0x00000000000000000000000000000000000a562e4c616e204172740d56696b746f726961204c616e2168747470733a2f2f696e7374616772616d2e636f6d2f7669696b615f6c616e5f0014762e6c616e2e6e667440676d61696c2e636f6d0000114056696b746f7269614c616e5f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149af8b5e8cfc8bafef815a7da50a69bdf81fa99c2681c3ac41eac9d1a9ced9467f210b26740af3660": "0x00000000000000000000000000000000000753616e6f756400000017636f6e746163747275626279407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149afb96de5bd6c558f6b21d624832094b03aa672e016462a020e217cc67b1434785b99114a2b4fa5a": "0x080000000003010000000200000000000000000000000000000000054a61636f1644616e69656c204a61636f627573204772656566661a68747470733a2f2f6769746875622e636f6d2f6a61636f677219406a61636f67723a6d61747269782e7061726974792e696f0f6a61636f407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b04176b93f2fc32d6b7b9e28c90ba6d9d96a6a65201e7b6d068289cfdccb14a87e3647d1be27f73": "0x040100000002000000000000000000000000000000000b4a616b75624879647261000000116a616b756240687964726164782e696f00000d404772656775734a616b7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b2b73f74e0bcbe48098003566e8882540368bb1facdab06615168afd78758bb5b2cb3609be94851": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a416e64792042656c6c00000015616e64796a7362656c6c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b3023cfe38b696b623d04580e847693a8fca215668f44c36ef4077074c0d96365480597afaa4265": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b38ffd646249ff7cc705f0ff73e771cc660a57a9540e469edf5ace2219b1f8452cf66382d915f07": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b4583306b0319a120e484544431d1f4a52f2e1be4a2493c8e4f5214d4c8c0e45f88c443efbefd7e": "0x040000000002000000000000000000000000000000000e414c45585f41524b4849504f56000016407361736861313938333a6d61747269782e6f72671f616c6578616e6465722e61726b6869706f76383340676d61696c2e636f6d00000d405361736861313830383833000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149b5c7c3faa653236a262d4db5b43d634096d43710d9eb3976fad629dab987b894e92cf3d5b66e978": "0x04000000000200000000000000000000000000000000094772696d66616365000015406772696d666163653a6d61747269782e6f7267126e6f7461746b6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ba6a520a92802ba82e71c97217b0299f2ffaa8c4d6c1856fee7046a5e904a542d8c17ca8bb95510": "0x00000000000000000000000000000000000542594c49001f68747470733a2f2f6769746875622e636f6d2f637572696f73697479797900163234637572696f7369747940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ba746407882e793d49fca4c127d246783d23e388e34c09446b624d2d5e1f7773c9590823d451019": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bb030d576315e075272318422a6be3bff308aef9c12a0a9304e65fff73541c82f67f03ec757355f": "0x0000000000000000000000000000000000096d617269746f6f6f064d6172696f0101166d6172696f5f66616c40686f746d61696c2e636f6d00000d406b696e6573696f66756c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bb1413da54b080a2691d8004aa9a03212cd950a811d53cb31fc736fe956d2fdc814e44ac0aaec2a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bd02aeac53e527cb85b79dfde710c26c2e5b70de5cafb49213d6c867d92d4c5eef5ce9d79c72c4b": "0x000000000000000000000000000000000007506174617465135049455452554343492042454e4a414d494e00001a63727970746f2e70617461746540686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bdad91263f2376dd46eebf8bfc22b8c7a156472e9630e85a3733a5441d305c7a11e85f2533f8d2c": "0x00000000000000000000000000000000000644657765791a427579207374726177206861747320696e2077696e74657221000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149be10627200d7958fa65ad25c6a51ba28504fe803d9e3d542135924ba9fc0736cd3f1d9b83901778": "0x04040000000200000000000000000000000000000000094a656468614e6574000000176a656468616e65744070726f746f6e6d61696c2e636800000b406a65646861686f6f6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bfcf61c34036fae141755f3929b5c0b0f20c64648d7f04e6b2e87e513cefdd8a1a882ba47081a37": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a7464696d6974726f76001d68747470733a2f2f6769746875622e636f6d2f7464696d6974726f76154074737665746f6d69723a7061726974792e696f00000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149bffd90013482c8a841d14814b8a9f5b29cf42401b098442706e254e5993c19225b420f31f37164c": "0x00000000000000000000000000000000000e4e6f626f64792050656f706c65000000146e626470656f706c6540676d61696c2e636f6d00000b406e626470656f706c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c11f75a37508012e84d6f02ea5a833165a345080deaa9777eff59e32c3ea2dda077f0964220ac72": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c2836ee11edbc0342bbd23dfc82edbf3cc9770f902c0165492b1ddfa03f3bad07a2b8b8c1736a49": "0x00000000000000000000000000000000000a61726368697465637400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c3652738d9db765c02ac0e3b7a5063502ecc00937811834207d4942585ebc50d2380f27dbacc932": "0x040200000003000000000000000000000000000000000d5068616c614e6574776f726b0016687474703a2f2f7068616c612e6e6574776f726b2f12237068616c613a6d61747269782e6f7267156d617276696e407068616c612e6e6574776f726b00000e405068616c614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c753b3833f46cecb47513040660e2e37de135835e13289e6a632cd6b7156bf16680d55895c08834": "0x00000000000000000000000000000000000a4d6f7573657944656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c7fedf2907893262a57aadd6bf7482891546cbd398277759854a920bb413299ea04093bd5588d2b": "0x00000000000000000000000000000000000e4f204f204d2049204c20552044086f6f6d696c75642068747470733a2f2f7777772e626568616e63652e6e65742f6f6f6d696c75640000000009406f6f6d696c7564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149c880ae2409dd46de8d7a76e2c92c53b569cd53fd0e51f5c97f8bec55686bd56d2bafae3ad7c0753": "0x00000000000000000000000000000000000c446f7473616d616368616e0000000000000d40646f7473616d616368616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149caba676d9ddf7d068ce96d86c921ccd2cf48357aed5b53c12a7db332b3d2c2d49fdcdc4fd92a355": "0x000000000000000000000000000000000006354e504c5900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cbcd9f3144633ac5eb0f44e687b84fa4126f5aebd57e66c8f92a27df1f3f0ec260719841b3ad70f": "0x000000000000000000000000000000000014426c6f636b636861696e2052696f20323032320f426c6f636b636861696e2052696f2168747470733a2f2f7777772e626c6f636b636861696e72696f2e636f6d2e6272001c6672616e636973636f383231363235303140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cd04164b151c8211a903015b9ceaaf0f183eb409d3a38c4f0c9a685066ed90b32c834940c689e1c": "0x040000000002000000000000000000000000000000000d43727970746f6772617068790000001963727970746f677261706879766c4070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cd0ac122701f28d7ec5e89c029a05224b2759566042a94c54966d125934a8ff8beb8e0b017cbd67": "0x04000000000200000000000000000000000000000000074b594f52595500001540656967656e626f743a6d61747269782e6f72671b6b796f7279752e76616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cdc08512e255b7738f6a9fcc82174482d492015b744f81cefaaa03e88a005508ed10f5936bff335": "0x00000000000000000000000000000000000942696767776f726d0000001862696767776f726d4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cdc46c29a406ad85cc9959fbf01495ec080df904dda709cbef65932c5007dacbac2125eb92cd371": "0x00000000000000000000000000000000000956616c6b797269650000001776616c6b797269652e6e66744070726f746f6e2e6d6500000e4056616c6b797269654e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ce78b12d1a5f4bf8ca62534073e8f15e51dc72040064bbd6ed63db5636fa6e57c40c00a9a5a7739": "0x0000000000000000000000000000000000036e6f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149cffe130a8fe4c1636a0843c25944887176cece9b16aeb480c7afa88f5e8048db2b43a8c63918425": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d0599596e6697cb7a1662770d7b3161c9ad84c07463893ee9da4cd45ba01cccfada15540e411a37": "0x000000000000000000000000000000000008556e6e616d656408556e6e616d65640000184b534d50554e4b534070726f746f6e6d61696c2e636f6d00000b404b534d50554e4b535f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d0cae984350fc7374bc1a01463386774ad67d8a822d4896a7603fc322eb4c6991a0ac38aef50b20": "0x0000000000000000000000000000000000134b6f6e74726f6c206761746f726b6f7270730000000000000a40676b31385f646f67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d0d5a898faa577da8b91ecff4a3016e6fd4172b9119fbba17c3bbf61dbee8269c17583296038553": "0x00000000000000000000000000000000000b4b6f646154657374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d1991a04d10dd3ac08fcbab8a091bafb08f6d2264738fd06178368a93f75eb50d45c43c8272db60": "0x00000000000000000000000000000000000a636c61726b3230323600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d20d76620b47fa66610405d8ddaba4dcfca1fe4d14f83496de1055fe97efca594f2813a82900e40": "0x04000000000200000000000000000000000000000000164e6f7a6f6d692053746174696f6e73205374617368000015406e6f7a6f6d6968713a6d61747269782e6f72671373746174696f6e73406e6f7a6f6d692e616900000a406e6f7a6f6d696871000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d28492b2214a8bf7c286d9263ab3205e13208aade05ad50ec0d73b338649a630029e7f86e99d145": "0x0000000000000000000000000000000000155361746f7269204372656174697665204c616273075361746f726900001c7361746f726963726561746976656c616240676d61696c2e636f6d00000b406368616f5f73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d3098889f53b6da26b0a4bc93447c5ec3fa281302974ac3669c0f534fa4a3a8f98954e2633c1e6e": "0x00000000000000000000000000000000000e4f7377696e5f4576726c6f6f74000000126f7377696e406576726c6f6f742e636f6d00000e404f7377696e53686966746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d34cfa440b95864d3754204488186b41e90a93d0607992b9cb992932ff66c2faef8a984dfe4a234": "0x04000000000200000000000000000000000000000000054d696c65000016406d61746865726365673a6d61747269782e6f7267176d6865726365674070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d406c203f1082a2c0b248917ec51942009e6cb18f634b944827d04edee517c29deab27d755cd100": "0x0400000000030000000000000000000000000000000018f09f998df09f8fbce2808de29980efb88f204a757474611244722e204a7574746120537465696e65720018406a757474613a6d61747269782e7061726974792e696f106a75747461407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d41368f1d880a3b3ef88f51188ea054ff03b902d8706c6d9b1ea56c119b34e0b88e915b5d02da5d": "0x040000000002000000000000000000000000000000001a506f6c6b61646f745f506f6c616e645f56616c696461746f72000016407374616b656e6f64653a6d61747269782e6f7267166b6f6e74616b7440706f6c736b61646f742e6f726700001140706f6c6b61646f745f706f6c616e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d4747c2dff0bc7f50997acc48aaa0cc73c966cb01023e4c220e62285f41e92f293e0dcc3dc81132": "0x00000000000000000000000000000000000950656e41726a756e001b68747470733a2f2f70656e64756c756d636861696e2e6f72672f000000000a4050656e41726a756e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d4b6496be09200b2009101253005ed413215bee9fa78987ba1a5d9edcc9e80b341b621ea976d218": "0x000000000000000000000000000000000006546565627300000000000009407465656273696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149d5e6e9ef7bd98711e7745ab2aae1c51e0588fbc7a5978fb0cad1e2521b9e16831422d3814868f2d": "0x0401000000020000000000000000000000000000000007426572727944000000186b6e6f776c656467656e75676740676d61696c2e636f6d00000c404265727279445f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149db8704940c3089460bd998bd01ce669f92bbaf2ffd60e0e332e8932dd20bdc825a6293032d1cd49": "0x0000000000000000000000000000000000084e79204861726c000000146e6179616861726c3740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dbbb4d22419e712fe2ddf82f8499b6f21a96fb3718b3e596c75e11f8c411bb564812ffd5ebd4702": "0x040000000002000000000000000000000000000000000b476f6f64204b61726d61000016407468656d61726375733a6d61747269782e6f7267196d6174746865772e6d617263757340676d61696c2e636f6d00000b405468654d6172637573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dbf1ea1fc3bfd2c58ed982e21ea95d74df1bd6901b6b088babae979b24aa93a205957e1e75ee90c": "0x0000000000000000000000000000000000086f64696769747900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dc1bbaf5f8b85cdd40a52fa2efbe7929910db51addfc222ceaa46fffc82d601f6cfb7289596f609": "0x0000000000000000000000000000000000084c6f6f6f6f6f6e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dca516239778ea2ee3e62db730d5ded66d818668d4dad82f6e026703e9fcbaa91d06fb8f6678b44": "0x0000000000000000000000000000000000064974616c7900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dcc277753735b96e04ca25cf1cbc516ed1c138492a7f2e606f60c5a9ac96cb405eaa3914fd12973": "0x040000000002000000000000000000000000000000000b626c6f636b736361706500000013626c6f636b7363617065406d7761792e696f00000f40426c6f636b73636170654c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dcee803646fe05ab0ef511fbed15d88d75933d12bb50b56d1bbed109380b2fe0c7ec72d44119152": "0x0400000000020000000000000000000000000000000008414c455353494f001d6c696e6b6564696e2e636f6d2f696e2f616c657373696f6f6e6f7269134069726f6e6f613a6d61747269782e6f726718616c657373696f2e6f6e6f726940676d61696c2e636f6d0000084069726f6e6f61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dd0a74dfe9045f7184d701295be7bb38b2c0c58a35bf8edc592671c53d149d206e037dc7c9beb7b": "0x040000000002000000000000000000000000000000000a48617368517561726b00000015636f6e746163744068617368717561726b2e696f00000b4048617368517561726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149de7b0783ac120f57e2653c8926623f3abcb7862638240e78d978128f73749a2b533c89e25d54f03": "0x00000000000000000000000000000000001043727970746f20497368696d7572610c4572696b205461736b696e0000157461736b696e6572696b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149def61665adc4306fec2c5ffb46bfe1dbc7935f493a5c9323520878aad74b5a32276a7a268abdb32": "0x04000000000200000000000000000000000000000000076e616667363900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149dfcb7c9db5d6bcdce2f88fadaaf6505b613082d0f8ceb04c8c0016c7b6afe57ec0c5226f45e5c45": "0x0000000000000000000000000000000000067374696d73064672616e6b000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e091d0dc11bd3ea62bcdbab2bc3f7e3c40b6c4a0f619b63ef65978d6ec0427651e83a59fea6f658": "0x0401000000020000000000000000000000000000000007415a494d555407415a494d55541e687474703a2f2f7777772e617a696d757470726f6a6563742e6e65742f1940636173685f5f617a696d75743a6d61747269782e6f726717696e666f40617a696d757470726f6a6563742e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e10ac134fee62edcea1f1014266a2b187ff31427aba732be9c6856099354ff536469087226b8453": "0x00000000000000000000000000000000000b50696b6b6f6c6574746501010117746f6d696f6c6179696e6b61407961686f6f2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e13c3a754009d072cddea2ece3afb01311814e16109d213b56d56de1e4299f697689e5f2a155f5c": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31350f42494e414e43455f4b534d5f3135000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e21ce449387a9e130d6f231bc79dc0b10d4b09c38f9deada991ddf9234054b5bf8791a576c18a50": "0x00000000000000000000000000000000000d6320f09fa59e206c2065202100000013637874726f6e636f40676d61696c2e636f6d00000c40636f6c65735f5f626167000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e5255a8d274d43c14a2c525bcba9a332c97d2d18c549fd3f134bfd9b8cf73837472fc66909e684b": "0x0400000000020000000000000000000000000000000006766974656b000014406d72766974656b3a6d61747269782e6f7267186d7263727970746f766974656b40676d61696c2e636f6d00000d4063727970746f766974656b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e57d4958a2ed9c63484f547d8726bb31f014613b3e2bfd4491f67b8c56a7e585b7505f9498addef": "0x000000000000000000000000000000000010506172697479205365637572697479105061726974792053656375726974790000137365637572697479407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e5b705cbdcc776ab4410d33f13c053dca87be657a0ae3cc87655baf43f7efdd454ff74e3a9d8a2f": "0x0400000000020000000000000000000000000000000014f09f98bb205374616b65204b617420f09f98bb00001340666d6f6e7a613a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e60cb268814889cd4fcdee494cca404d6eaf8c4293efef5159df2957859f2ef2c4b35c231911f7a": "0x0400000000020000000000000000000000000000000015f09f90bc50616e646157617272696f72f09f90bc00001a4070616e64615f77617272696f723a6d61747269782e6f72671970616e64612e77617272696f72444070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e738312b74520571ba583787c302d270bf87c9febd2fa4b471cc951c73400270789d5193bede10c": "0x040000000002000000000000000000000000000000001f4368616f7344414f205265666572656e64756d20436f6d6d697373696f6e0000000000000a404368616f7344414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e94efbcced786be9ad97bf6cfb3fb36b24b221c27ea22cbdbfb4dd4b2c54f80d8235d490be9113b": "0x040000000002000000000000000000000000000000000a416c6578616e64657200001040616c65783a7061726974792e696f1d616c6578616e6465722e746865697373656e407061726974792e696f00000c40616c65787374796c696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149e9aa0898cd6f4e764c3926d1b9f9d44e8a2533c9a4df185d087a06601c49b7cbf12a8448fb45976": "0x000000000000000000000000000000000006737872737200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ea440de636efc37dab0b013939f1b243f4674d76815ce2059fdc16425b04de7b01065e40d1dc46e": "0x0000000000000000000000000000000000126c617572656e7463617374656c6c616e69134c617572656e742043617374656c6c616e692168747470733a2f2f7777772e696e7374616772616d2e636f6d2f6c617572656e00206c617572656e7463617374656c6c616e692e61727440676d61696c2e636f6d000010406c617572656e7443617374656c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ea68c0718a528a6f62e96783cff0b94caad6a13634ffd527d6d02d45f2cb810424cc47904ec284b": "0x040100000002000000000000000000000000000000000b6166726f7373743030390a412e2046726f73737400001a6166726f7373743030394070726f746f6e6d61696c2e636f6d00000c406166726f737374303039000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ed6094855a6dc83081c465a655cf27eaa73bdf9554abcb46ca2d56fe7fb0a20835c1a5ddec4a325": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ef6562b57d1a60490c7f4e84347dc6e4e176f9156b2347378faa9b538a857b404cee3e341706305": "0x040000000002000000000000000000000000000000000f6d6f6f6e6269726469652e636f6d000017406d6f6f6e6269726469653a6d61747269782e6f72671a6d6f6f6e6269726469654070726f746f6e6d61696c2e636f6d00000d404d6f6f6e42697264696533000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f053c2746e722456610a5024c2a5db3d02056d4344d120ec7be283100d71a6715f09275167e4f38": "0x040000000002000000000000000000000000000000000e5374616b65776f726c642e696f001668747470733a2f2f7374616b65776f726c642e696f17407374616b65776f726c643a6d61747269782e6f726713696e666f407374616b65776f726c642e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f06ff187af4df40163022143f2dff082630195ea8c8518036f5fa8110c90eabd2ef5cb4fc0c4235": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f1fa798d8345173525f464cc5364f7f7852731d5cd9b78500f1c43cfdb92c9eede3f5a0eaa03f25": "0x0400000000020000000000000000000000000000000006566f76696b000000156b73756d61726b31323340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f461d99d2f7b43efaef36db79bfaff596eb52fcd57f5231c07548f88cf3149a6c5e16fc8a02fa56": "0x0000000000000000000000000000000000074e756c6c657809566c6164696d697200001366726f6e7478323540676d61696c2e636f6d00000b4068617269746f6d6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f4efbdd6555e0b768a449eb95cac957070a045678b83a9eb272296d2d6a73fc8fb32c1d3bf34967": "0x0401000000020000000000000000000000000000000008266e736869726f0000001366656465746f636340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f52902e443180208cf503bbe53110bea4f9fc4db5c69cc297d5468dce978b2c16babacff8dd686a": "0x00000000000000000000000000000000000553746176000000194564646965313032344070726f746f6e6d61696c2e636f6d00000a405374617634303936000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f5b73b14b74941844028623ab4774d78118028619961cc7ff178f9fac433b80d4f59761c60b6110": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f7946d98858bbac124a3f9569f9ff89daea4ccf602d528f8da44f34ecf48bc6973eed3b5165ff10": "0x00000000000000000000000000000000000b54726173682e4865726f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f7c71dd97969da5263df801610ab2b9d7d2f33089b6bc0309ff8b8dd03cd5c7ed6a63d7a3c1f962": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149f8de5a4034454281e984e6d5e51685cee9d5281a4cd1a8ac5cc9885941adce24e5aa7c3c52dc664": "0x0000000000000000000000000000000000064a49534f4f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fa09da6038a3e69bae09878d7a9b24afaedfc8f7583489d17b8f8f960f2d568e23b235fde2c3526": "0x00000000000000000000000000000000000b69736f7669746578696e0000000000000c4069736f7669746578696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fab1af956c8e372583b27d0269f0d86d9c19a74eaddbbdd6885d999c9a4d4defc2697e294c1e722": "0x00000000000000000000000000000000000c446f7442756c6c7344616f0c446f7442756c6c7344616f000016646f7462756c6c7364616f40676d61696c2e636f6d00000d40446f7442756c6c7344616f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fb9d67d9f4e2fa2ba72901b5cad51e0d3f0b63845f17d071a84abdcbf78a3ff56c61ffbaf02d56b": "0x0000000000000000000000000000000000086b696c6175656100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fcaf6c7a62c9137a6299b602cc853e89ea284f820806f4451609c9912ae6d975263344d5a840752": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fcbffeac9a335a1b4959a54c2ae7ea7b9200d5e5c1584654ff2d18e88e50265474b2d3888bc740b": "0x00000000000000000000000000000000000f44656d6f6420506f6c6b61646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fd3584b98fe6bcabc5aae116c7e9946559d10511d4782e36aa971ff50e4b7a3394208a2a68a087c": "0x000000000000000000000000000000000007686966756d6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fe4058d2daf1d0ac63b1a57aae969fc1d0796ce63d7f2175b568b461ced1ba46679b5e51cd13d30": "0x0000000000000000000000000000000000096368616f73626f6900117777772e6368616f73626f692e636f6d000000000a406368616f73626f69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ff692371ae01a939a033ac371b5adcb02ce6f22dbfc953767c2f4ff6140f2fcb18125eb4cff9820": "0x000000000000000000000000000000000009506572736f6e616c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149ffd1362c0ca2353c85cebb3f21b5e97737a7bbc14d8376a79dbba9c2849a28edae77c776d1e4a08": "0x040000000002000000000000000000000000000000000c7072656d61747572617461000018407072656d617475726174613a6d61747269782e6f7267207072656d617475726174612e76616c696461746f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab87047149fff764f278ece0638008b23e7763fadc90d6a0b5d1ebbf8b930e95ab5eaccc3d4cbad41df8f726d": "0x00000000000000000000000000000000000b537562737472614775790000000000000c4073756273747261677579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a004ed215b6f26ec367a414bdfb35809b2ab3febb46b75abad9a72cac29918e5501f080841af412d": "0x04040000000200000000000000000000000000000000055472616c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a01290fe5b06995f4c17ad2c0a71fbae7beb3bed91a1e8f90289ffdcd7089c881ff247b3b70fb03f": "0x000000000000000000000000000000000008415254204445580000000000000d406b7573616d615f646f6773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a026881ddc77059cfc793f88c007467e78399bf6490ee2c84bf2679eb27ed13a86e0399d291e8525": "0x000000000000000000000000000000000012536e616b6573206f6e206120706c616e65000000116d626279753740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a028e921c9041581bef3f1aa71b32bba775b3886b900a2e3fb4f4163d58c1bce0aaecfe0b55c1b5f": "0x0400000000020000000000000000000000000000000016f09fa49620526f626f7420486561727420f09f96a400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a039f5a44265aa6630e02b0b9846874c53f5fcc3f9260a60f0b27c7239102eb97ab13f5ad29d2273": "0x00000000000000000000000000000000000970696e617475626f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0476abd38ede3949653bcf18e30531092fdc1c52afe06cf61f56fb1fa5d719078cd6914d395ed0f": "0x04010000000200000000000000000000000000000000114d61737465726e6f64653234f09f94b10d4d61737465726e6f6465323418687474703a2f2f6d61737465726e6f646532342e64652f1540616c65786b6964643a6d61747269782e6f7267176b7573616d61406d61737465726e6f646532342e646500000e406d61737465726e6f64653234000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a058a0c0476768208476db8162516f3ed29a4227dbc9cff53d4f2c342907a499e9517cc16f94356a": "0x0000000000000000000000000000000000154d6f726f6e6963204d75746174696f6e204b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a062138be3539cdbd8876695e0680719107b9ccb595ad5d8bfdc4ccc8e8e4656091fcfe652c0f155": "0x0400000000020000000000000000000000000000000009564c4144494d495200001a406772617465766c6164696d69723a6d61747269782e6f7267196772617465766c6164696d69724072616d626c65722e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a06e8fd58cbda126387bb92ab860d29d43aaa2f6a9a97d658a52291111654489f8e294301171f908": "0x00000000000000000000000000000000000844722e204d75700000000000001040676f72696c6c6168696768646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a078de63f42f4d3d89abf449cfb7d9b862b775abe556bccbe647820fd4d7a50b63872b657c96506f": "0x0400000000020000000000000000000000000000000010444f5453414d415354414b452e494f00001c40646f7473616d617374616b652e696f3a6d61747269782e6f7267156e6f646540646f7473616d617374616b652e696f00001140646f7473616d617374616b655f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a091d0f89a15b5c8260bedc3bc39a4394c59b58e3adfc89b23caca4cdf695fb96fff3e0a556f8a00": "0x00000000000000000000000000000000000948616d69645f6d6d0f48616d6964206d6f68616d61646901010100000a4068616d69645f6d6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a09342269424baaa12ec709076fedbe0737ed2b7aa80e029f5de68e2faa5a303fc55cef3b1ca5a4c": "0x00000000000000000000000000000000000a42616a6f717565746101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a09af68755800aad94ef44028b5c2649905e23e0abe33d4542688a2ed40bcc0f169f0d535816f43e": "0x0000000000000000000000000000000000094e656f4e756d6973094e656f4e756d69731668747470733a2f2f6e656f6e756d69732e636f6d2f0015737570706f7274406e656f6e756d69732e636f6d000000000e4e656f4e756d6973233733313600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a09f49890c6bdef1acbfbc894060d93d772850a601b3f4b69d02c8026b2e7d99433b4067feabeb29": "0x00000000000000000000000000000000000f4a756c69616e6120436162657a610000001b6a756c69616e61636162657a61407961686f6f2e636f6d2e6272000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0a5afe895a38848e60eab4376491bae1381d70519031e7dcba87563353d85d4553ed98102882c26": "0x0000000000000000000000000000000000074d696368656c0000000000000d404d696368656c6c6c6c5f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0b881b0063a363a02bf32e061073c44300056b416cd66a4fde1e6c120dbc0089bb65134f5693a3b": "0x040000000002000000000000000000000000000000000a6d7564646c6562656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0be3d88f3ec6175e4a17c9a02776b617e255d70b32ffa9313bac0f99e7f1f376e449bd51816901c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0c7bc8aeaa262f14ac4eaed36e5c54f045b46cb54f533b2d3949c0ca7137e89ef03ee3f56f8155f": "0x040000000002000000000000000000000000000000000c477233336e4861747433520000001b477233336e4861747433524070726f746f6e6d61696c2e636f6d00000d40477233336e486174743352000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a0c8c65147c2d821f2259af2c52fcc70ca4e85fc39b56d87ffd4411fcebc547e9f92f3314a25c112": "0x00000000000000000000000000000000000d4461766964205472656e647a114461766964204a20576f6f6462757279157777772e7472656e64796368656573652e636f6d00176461766964407472656e64796368656573652e636f6d00000f4064617669646a757374696e3834000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a107be39dc1d3e29e461904b1a914a11bfcd4ea252c04de536dcc0af7fc36de82431af75f08ef13a": "0x00000000000000000000000000000000000b42697463682054697473001d68747470733a2f2f7777772e6d617968656d6e6f6465732e636f6d2f000000000b406170656f6e61636369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a10e77c34a7d9ba5b8a2a7e1c5807c9b5241a00382d483537eeaac2fc756dfde564af6a368fbc275": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a117fdeb44584c3b762311603c2642b9de046bc7b653733b25cb40e98871ce9835c65a249e735533": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33360f62696e616e63655f6b736d5f3336000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a11a320b9a8feb01f857311106c8d7b0daf6e096db9a0d759b52403e439ab23fd6559780a8b1c803": "0x04000000000200000000000000000000000000000000095374616d70656465000000197374616d7065646563727970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a125e781d83ce9a1a8fdbb1c5950c16c8e725a857c3834b8647b1751fef78079de2976fe5516176e": "0x000000000000000000000000000000000011416e746f696e652045737469656e6e6511416e746f696e652045737469656e6e650000000000114065737469656e6e65616e746f696e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a157ecf5817eb51ef005d960b7bb25e0979b9533817cff27aca11f7bec09a69235d17622aaa7776b": "0x040100000002000000000000000000000000000000000c6c6c6f7964732e746563681d4c4c6f79647320426c6f636b636861696e20546563686e6f6c6f67791468747470733a2f2f6c6c6f7964732e7465636818406c6c6f7964732e746563683a6d61747269782e6f72671174656368406c6c6f7964732e7465636800000d406c6c6f7964735f74656368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a17318e09fa7855318d059728fac3dabd4b7058c455c4cd0c636520da4d9ce4e6cab9932b23a3a3d": "0x04010000000200000000000000000000000000000000076e616d72756e000016406d6931332d3563346e3a6d61747269782e6f7267156e616d72756e2e6b736d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a17e7770b29efc26845498df40e85e2ba9d9e213d1f476e7b147aab6a9098f1bb250e00251ef8f5c": "0x0400000000020000000000000000000000000000000015436f6c642053746f72616765204361706974616c0000001d6a6d617a6140636f6c6473746f726167656361706974616c2e636f6d00001040636f6c6473746f72616765636170000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a18d4df5394e01a8d23bddef5d1f2e9b9d3a49363d6ff94c517aff97ffbe186acb22564a4dccc94b": "0x000000000000000000000000000000000007436f7a6d316300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a19b37e844707d72307183930b2264c5165f4a210a99520c5f1672b0413d57769fabc19e6866fb25": "0x000000000000000000000000000000000006537a65676f0d53657267656a2053616b616300001773616b6163737a657267656a40676d61696c2e636f6d00000d4053616b616353657267656a000740737a65676f00", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a1c8d0175e914150ac13bb5ebe1fd2af47758b14ed5f26987831f053be20293e20064a68393dbc6d": "0x00000000000000000000000000000000000e54696d656c657373204172747a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a1cf23b5be0cbaf3f43436557ab3a98460458c52dc9e8795303af2f3772122c712af60e530592d4a": "0x000000000000000000000000000000000005446963650000000000000e40646963655f696e5f64696365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a1e3b34bf1f2c1ce6abdcbbb3d328d87db10f5948e4fab5d12e7470826c4fa9ede73f40bd4ae1721": "0x00000000000000000000000000000000000a4d65746170756e6b7a00127777772e3864646f67636c75622e636f6d0013696e666f403864646f67636c75622e636f6d00000c406d65746170756e6b7a5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a20215acf2cee769a26f9a811e752199217945e52bb96fb08229d7904bc030f6df73b5b4e6bbdb6e": "0x040000000002000000000000000000000000000000000c4a6f686e5f43616e617279000000156a6f686e62726f73734069636c6f75642e636f6d00000c404a6f686e5f42726f7373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a209cd26c6c53911aab241100ccfed63c10453f0772355250fca0a4bb826afec2692f11416e0392b": "0x00000000000000000000000000000000000b4272686e4b63627936310000000000000c404272686e4b6362793631000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a20c478424158a838edfbe8841fb9f9571f356320c1cd5df5b6365e25f83305141940b25a2bddb03": "0x00000000000000000000000000000000000569686f720000001a70616c616d6172656e6b6f69686f7240676d61696c2e636f6d0000114049686f7250616c616d6172656e6b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a215c23d3f30e28acc4fac060bf7e92c94836df38993b1851e3c2a9728335340fff42ded89ea2326": "0x00000000000000000000000000000000000a53757065727269736b10416e647265612056656e6472616d651768747470733a2f2f6269742e6c792f334644766b6757001f73757065727269736b2e74686573616e64626f7840676d61696c2e636f6d00000e4076656e6472616d655f616e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a22b2644a532020e102cb9e9982a073c22c641fcf04338ccaf8f34047acfd430ee0490488c85201e": "0x0000000000000000000000000000000000175a6569746765697374205461726f74204d696e7465720c5a6569746765697374504d0d7a65697467656973742e706d0115636f6e74616374407a65697467656973742e706d00000d407a6569746765697374706d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a232fb94a5267854b2fe1d9da0178b40163865fe41c0a593a6444ea39efea4325cf3a8a2ad2ad279": "0x00000000000000000000000000000000000a4379626572446f6f720101010100001140417274687572573630303532353036000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a26e21db13bc9cb6d4afb112d3a3a1ab9e8e99dade99ee8afefbb7547f8bb862100557ceb9fb9047": "0x00000000000000000000000000000000000b48756e74657272723739074d757969776100001a6d75796977612e6f6465696e6465406c6976652e636f2e756b00000f404d75796977614f6465696e6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a27174c44291c2200c27409c0741df6780a595424f9e421ffdc6da847a45b0d382d6797e30371213": "0x000000000000000000000000000000000009506f6e64617475730000000f706f6e646174757340706d2e6d6500000a40706f6e6461747573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a298d0b8580cdd4b2075be44eab367537b65f751a9198164e4b7c80790015494216465284b9e422d": "0x00000000000000000000000000000000000e496e66696e697479204d696e640e496e66696e697479204d696e641f687474703a2f2f776f6c66616e677279636c75622e74696c64612e77732f001a696e66696e6974796d696e646b736d40676d61696c2e636f6d00001140496e66696e6974794d696e644b534d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2a6a1ee046288c04ef671d2efdd37b165d0cf115e33450b96ed967d730b3c3e6b89e649ffda7352": "0x04000000000200000000000000000000000000000000097461696368756e67000015407461696368756e673a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2ae90c382196439e01757b530f7bdc77daf168300e833e402c73828d934814e124e9b14df068a21": "0x00000000000000000000000000000000000f4645454c2054484520465255495410416c656a616e64726f20476c6174741163727970746f706170617961732e696f1040616c656a616e64746f676c61747413616c65676c61747440676d61696c2e636f6d00001040616c656a616e64746f676c617474000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2aee766ebb6fb7c4edf81ba4fbeb6ea13cd45ba93cc1d689a6e2e5c6dfc35a458a971823a324218": "0x040000000002000000000000000000000000000000000b506f6c6c7320636f696e000000176c69636572696f73686f727940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2b8fab3ba0aef26c86c5ec7bc852b2bf9b5847ca343f9117c1edbd761cc6e40a5233e5764020579": "0x0000000000000000000000000000000000064b6f626179064b6f6261791c68747470733a2f2f6c696e6b74722e65652f6b6f6261792e6172740101000007406b30626179000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2ba603094678fe1c650925980e670634900f8e902da89bed9c9702ac51aaf08cb5043eec1f10345": "0x0000000000000000000000000000000000084b756273616d61084b756273616d6100000000000e405365637265745f5f53616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2c470192fbbe716643b60a34e88347c82257693d4429296b7822293c9a7bfdb2b08341529513c67": "0x00000000000000000000000000000000000c4a696d6965204475636b7a0000000000000c404a696d69654475636b7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2e21db14ae164a8ec94a820c5dfc7420392ebb42e844a853016ab1310838a42e7ee315c7e07ed7c": "0x00000000000000000000000000000000001053756e7368696e654175746f732d4300001f4073756e7368696e656175746f736e6f6465733a6d61747269782e6f72671c73756e7368696e656175746f73696e666f40676d61696c2e636f6d0000114053756e7368696e655f4175746f735f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2eb6257919dedbd0297ceb4d82f5843b3339ce0ecdb2a76c041eaf00c60e3b1c069f34111c7c967": "0x00000000000000000000000000000000000b626c61636b6c6f64676500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2fb598c76f739aff4f2348bd92ca853d527b99144ad3f1d62b1ccab25e646b052dd5a3311773f76": "0x00000000000000000000000000000000000659796173680659796173681a7777772e7979617368736f756e6464657369676e65722e636f134059796173683a4b6f6461646f742e6f7267186e65636b63656e736f756e647340676d61696c2e636f6d00000c40427562626c65626f6969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a2fef89bd91c048c8b37db52b514d523a0fac84ec631db132c7532f317bbfa5ecd094c891bf65c81": "0x000000000000000000000000000000000009462e492e522e4d2e00000000000008404649524d335f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a305800a21679f161a0dc738566c0d456e72772f31b0df32843245857dfc5fed13f2780a3e785771": "0x040000000002000000000000000000000000000000000a7374616b657468617400001640616e647265697369643a6d61747269782e6f7267167374616b6574686174687140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a30ff791ba0dd28618c7f5a8530d6aafc1b191156294a9e27bb674128607896f3fd5914282fb196d": "0x0000000000000000000000000000000000064b616d696c104b616d696c2053616c616b686965760014406b616d696c73613a6d61747269782e6f7267146b616d696c7361313640676d61696c2e636f6d00000c406b616d696c5f61626979000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3122414b52a0a0e18e0e8642a07089983ff62c55ab6f151c2ad58f43a4cb9f995cfaa5769fa9568": "0x040000000002000000000000000000000000000000000a456c7669732050617a00001240656b616d693a6d61747269782e6f72671a656c7669736775737461766f70303340676d61696c2e636f6d000009403078656b616d69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a319bb2ed17a3f850374c8228c74fbe266e3f5612322de99d130666ccc639162034c6b0ab135bfe1": "0x00000000000000000000000000000000000c4368656b6f7620524d524b001668747470733a2f2f7777772e726d726b2e6170702f000000000d406368656b6f7638736f7570000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a31e75d5b109bd2528a94bbd46b41a6c7e7d0c776bbfdb48c6d72886fadf7ac49c62f014959f2852": "0x040000000002000000000000000000000000000000000b636f6c647920f09fa78a00000018636f6c64636861696e40696e746572626c6f632e6f726700000a40676574636f6c6479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a32760f6427ce1809aed8974aa64c7f31f4f0f60e863eb811ad1a6c75fd32dda92b19645fe5b0f47": "0x00000000000000000000000000000000000a4469706c617469636f0000000000000b404469706c617469636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a327ed779367e66e9a283ffd707bcb531dc655e2a4d42124a6366355f088936f05d181aa469e2e0c": "0x00000000000000000000000000000000000a50726f6d6f5465616d001e68747470733a2f2f70617261636861696e6d6173636f74732e636f6d2f001c706f6c6b61646f7470726f6d6f7465616d40676d61696c2e636f6d00000d4050726f6d6f5465616d5044000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a331b5a5d1eacc6ad6474ace9590159e08525e3c7273256016a640e300eaca921ce88713b44c9a5b": "0x0000000000000000000000000000000000044d524b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a35762ac0f6b70b004028af3547c1c24c7b1d6ade70e4b20a94cd829457bc0d126f8d05b8d298775": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a35b58e91836d05e60c6e940d5c74596755e6bb1b31ec98958db10d841dfaf66954b5542c95c462b": "0x0400000000020000000000000000000000000000000008414252415241440000154061627261726164693a6d61747269782e6f72671861627261726164694070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a36ad1dff06875450ed3eb9c7be61e0f8e13abb04857d82be899c1d7c3203998e02538720052ad34": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3833fe87343f3df36b5dcb29928d8a462f493e0250e895158fc4fc54eb5d00a2a6701fe36a4283d": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000b5069636f6e62656c6c6f0e5069636f6e62656c6c6f204f551768747470733a2f2f7069636f6e62656c6c6f2e636f6d0017636f6e74616374407069636f6e62656c6c6f2e636f6d00000c407069636f6e62656c6c6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a38ea7997f350d35d66d89d096c73b1d834e6d3114051cce2f13dc14014a103e9a61a97f4db2a818": "0x00000000000000000000000000000000000b50657065204b756e54610b4b696e67204b756e54610000176b696e676b756e746132343940676d61696c2e636f6d00000c406b696e74796472656164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3a4e6df5615cbd134a3f0845fecdf74f7aeb569953da8cf8f8217a9a167a4e7d6b3438d8bb6d828": "0x040000000002000000000000000000000000000000001c416e756269204469676974616c204d61696e204964656e7469747900001940616e7562696469676974616c3a6d61747269782e6f726716696e666f40616e7562696469676974616c2e636f6d00000e40416e7562694469676974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3a7ea9aae156340321d4124142f13d96092f57fb2635388bbd7337f2ef526abda0d3e011c361627": "0x00000000000000000000000000000000000b48656b746f7273616d610f47656f726720547369726f6e697301011967656f72672e747369726f6e697340676d61696c2e636f6d00000f4047656f7267547369726f6e6973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3aa8a884996480b8041562016f6a47fe5d5a4ef7a3e51e71c399b5d7c03850f381b278867e08207": "0x00000000000000000000000000000000000c4d7242617468696e4170650000000000000d404d7242617468696e417065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3cec71a40cb80cfd692990e340f0cd542caf9eced5e6bbdaf269fb9637fdec4cf1c30156f451e24": "0x00000000000000000000000000000000000453616900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3d3732bc41feae490f0a6ad888e6a209c647f9c7834ecef87df797be3acb971708e8b73dc64236a": "0x00000000000000000000000000000000000f486f757365206f66204368616f730000000000001040726f6d65686f7573656368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3d7c54c6084b5aa5ed235ac2a5c0f5ea70c3c75169e1c0439f5e6a56005ae7aeada55080d512944": "0x000000000000000000000000000000000012407068726f647269677565735f31393836135061756c6f20482e20526f647269677565730101117061756c6f5f3139383640706d2e6d65000011407068726f6472696775657331393836000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a3f10cae030a6d30b0c42cd546571a3529880973bb9be4952a9bd568d57e55fbdefae7614187ce5c": "0x000000000000000000000000000000000006736e69666600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a409a5b38e9a0943eceb07c477bd40d22f83b08cce78f2375bc1e4cf188c0de1ffef592570383e59": "0x0400000000020000000000000000000000000000000009496e66726170697800000013696e6672617069784070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a40bc803acf9306792a118b2db66b83b0687645ec1283b836ed95f3646db15ff4a2fb0f05a4d237a": "0x00000000000000000000000000000000000442434111426c6f636b20437265617465204172741568747470733a2f2f7777772e62636165782e636f10406263613a6d61747269782e6f726713626361727440626c6f636b6172742e76697000000b40426c6f636b61727436000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a41965f505d4d7b50cdccfda77f98ad5ee49c1056eab38e6dbc2028e5ef46d90618e2ebac4cdf249": "0x00000000000000000000000000000000000741726e61656c0f4d696b65205a676872797665747300001241726e61656c6d40676d61696c2e636f6d00000a4041726e61656c4347000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a41e44784a9e830d2e47391ba4e18c5aeb3978bc6104d9d4d99453b16cb55150d10e590bdebde066": "0x000000000000000000000000000000000005416e6e6110416e6e612053686368657262796e61000017616e6e613230313476696b7440676d61696c2e636f6d00001040416e6e5f53686368657262796e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a42050992f99e93b160719558ddd4f7497ab5e4be273872a6ae0ef556b87ce5a246a927f417ba278": "0x000000000000000000000000000000000008447572706830390e436f6e6f72204d6168616e657900001563726d6168616e65793940676d61696c2e636f6d0000094044757270683039000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a42a7f2fc85a4d702255f3051ce179f64c735c4f46438bf790faf9c1e295e068bac569b80ac23961": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a42dd34ade18972444a9743d676ca9759f7897d55fd7fa240058fc1b2e0cdf37d49e588036213a50": "0x0000000000000000000000000000000000074131363030460000000000000840413136303046000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a443701cf93179113acdfb6cd734dd3e624b6512e0903724c1c90a516c03c81a9af756491ea8e15e": "0x040100000002000000000000000000000000000000000a5374616b65666c6f77002068747470733a2f2f76616c696461746f722e7374616b65666c6f772e696f2f124069373439353a6d61747269782e6f7267127465616d407374616b65666c6f772e696f00000e4073665f76616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a45f60fb1fe385b96a39514d62c18e0f36ea214a5d6e772c653af20e647ec87f0f6985fdeba13752": "0x0000000000000000000000000000000000154b6e75636b6c657356616e42656172646875697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a46019660a76ac1f5889dcc187231dbcba0bc0dad136d1ecb09633bc7cd5e27e04daa0277009ff2f": "0x040000000002000000000000000000000000000000000456444100001440766461303339303a6d61747269782e6f7267127664613033393040676d61696c2e636f6d00000b404456656c657368696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a461cd7dfddc684c664b2886e95f12e168b420f06b90c11d8cdfa7ee747bc12e235a6d5efbae6e12": "0x040000000002000000000000000000000000000000000650697032340000134076656c616e613a6d61747269782e6f72671572617a69746f7431323240676d61696c2e636f6d00000b4056656c616e61563036000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a467ece912d3a063167e362d3f5635ffb7527605a5e9004e8691b954f19a34ab86f4451cb0be6956": "0x04000000000200000000000000000000000000000000095354414b452e5355000016406d722e6f776e6167653a6d61747269782e6f72671d7374616b652e736f766965742e756e696f6e40676d61696c2e636f6d000008406567726d7368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a47a994958e0ce59ae58ba526977ac8c888aaec71da2be93459c2c6ee4a33f0881da7bd585b43a66": "0x00000000000000000000000000000000000f546865204b7573616d617269616e002168747470733a2f2f7777772e796f75747562652e636f6d2f6368616e6e656c2f00185468654b7573616d617269616e40676d61696c2e636f6d00000f405468654b7573616d617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a48bc4964ca9af844480a961c77e6771723cbb95384839f9a287779affeba7b7651d748927c2901e": "0x00000000000000000000000000000000000c447261676f6e73746f726d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a495a0a3926f96507eb86c4dfcd61617f0896775d0b2094ccb49ada7914e044e532760feef32d85f": "0x00000000000000000000000000000000000970616e6a696e616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a4990b5c0a8a5952088513ec07599b212d37b1cf18eee0538759ab65ca3735d47d1c5433e3297e02": "0x0000000000000000000000000000000000057261696e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a4b9e382b3c28c9432fe137591e4faf75d462ae5769e8b08a138fcc920ac9387c4a7ab86cb87be23": "0x000000000000000000000000000000000018537562737472614b6e6967687473204d65726368616e74104d65726368616e742057616c6c657400000000001140737562737472615f6b6e6967687473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a4ddec1e6dbcf011629c17f4f4a24ec53f85a7beb1c70b13379fb8e4f969560704d2c25133ba8d24": "0x08000000000100902f500900000000000000000000000100000002000000000000000000000000000000000d416c7a796d6f6c6f6769737410416c7a796d6f6c6f67697374204f791968747470733a2f2f7777772e7a796d6f6c6f6769612e66690015636f6e74616374407a796d6f6c6f6769612e6669000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a4ebe0825e5d7b90e20a9ef731e714cabd44479f1e39f9877a8480eff0ffc05e0d4dd701f7dc8650": "0x040400000002000000000000000000000000000000000a657269637a68616e670000001265726963406c6974656e7472792e636f6d00000e40657269637a68616e67657468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a530449273055581500359c0429d00c60d1da56e08054690497c0537931717f462b454362d363e08": "0x00000000000000000000000000000000000b67726f6d62617264757200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a53864ffd30a765388d1505492274985d6049cfae833ce8ce11597aca19d0f06a29ddb0a7a5fb97e": "0x00000000000000000000000000000000000756616d7073790000000000000c4076616d70737966656172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a54fac6210e70b7fb8d7d63b5e953e9004bc94357dc2f2b11654c220d871bd3c8b05b8047faa2a6d": "0x00000000000000000000000000000000000a53686565702052617000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a558ac2b375bd02bacd4501a1fc78e38cfc3b45660c9487ea36fc5a85aa7a7ecd3fc7c31dece0d43": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a57f9bacdb1086c63892e43e9200a587c535ada26933f3f8279e2d75e7e77cb9d3ce33153e5ad973": "0x0000000000000000000000000000000000104b7573616d612041706520436c7562001c6d656469756d2e636f6d2f406170652e636c75622e6b7573616d61001a6170652e636c75622e6b7573616d6140676d61696c2e636f6d00000b404b7573616d61417065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5856810995ea72550ddcd537dceb0e95c72a9e2984c8703f4d9d76e8067305f365905a909ae3a47": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000547473136000018406c7562616e7979797979793a6d61747269782e6f7267136c7562616e7979797979406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a58931525b3ed3cb1024d5c7c359048f593fac90652e61b58cf9cfceab4f2828ab77743735bc9611": "0x0000000000000000000000000000000000096772756e746c65640000001a63696e6f63727970746f4070726f746f6e6d61696c2e636f6d00000c4063727970746f63696e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a59acabf7cc5c2db3a0b67c6e4b35133a18ff9c3b56d6cd28662f9e47f38afbfc508543087966870": "0x040000000002000000000000000000000000000000000c43525950544f4e495441530000001e63727970746f6e697461732e6365727665726140676d61696c2e636f6d00000e4063727970746f6e697461735f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5ad0e5d9fecbb59ecbd732a91bbca19dcbcd8339644f8a6bdb752229a861140998663eafaa8f871": "0x0000000000000000000000000000000000084d6974737572690101010100001040636f70706570616161616161616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5b9b36d9ffbd7602c527cb7d17e0fe6df0e0da303a71f3eb46ea5bd309858389666ce6dad8efe15": "0x040000000002000000000000000000000000000000001cf09fa6bff09fa4962057686974654e6f646520f09fa496f09fa6bf00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5b9eb0c3f28851660f981f150d72abe1fe2f48f8e825f32baadd440d5114b0242b7d5b85044da07": "0x04000000000200000000000000000000000000000000084e61636869746f000000196e61636869746f2e63727970746f40676d61696c2e636f6d00000c406e61636869746f657468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5c4abc52a115cbd5a3a2cbb4e72978f14e758e1ecf46d1d98cc080f7c7213ef9fb5fffdfeca6c11": "0x000000000000000000000000000000000006416c6f696406416c6f6964000013616c6f696464313340676d61696c2e636f6d000009405f416c6f69645f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5db7a2686e7ec402cbac2d6ac81d2169fa6e455b0497cf0389bd5dd2a11b24a53e6d94053765a77": "0x040000000002000000000000000000000000000000001be29ca8f09f918de29ca8204461793720e29ca8f09f918de29ca800001140646179373a6d61747269782e6f726714616e746f6e406e6f766177616c6c65742e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a5edded3fab580ac0e330ec8982011f9e4c1b0399335eeaadf410f721def14cd16df28e905af3905": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a60b4b1b2473719caeab30137868944fe970131f3d1882ed41e526020e9429818e90649413f94430": "0x0000000000000000000000000000000000064d617837340000000000000e406d617837345f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a60dad8905663a8126acb4e6372fd11f9cf419b845964385848977d6e37b6221ea9d69d58d27d623": "0x0401000000020000000000000000000000000000000016444557205374616b696e6720536f6c7574696f6e73001a68747470733a2f2f7777772e6465772d7374616b652e636f6d1440646577706f6f6c3a6d61747269782e6f726716646577706f6f6c406d61696c66656e63652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a61e7bfd7e80c927d04063c17aa00b3f0a378bf91acaa686257ce04972b6ee190cb6a6f16327d37f": "0x000000000000000000000000000000000008496e7641726368001868747470733a2f2f696e76617263682e6e6574776f726b000000001040496e76417263684e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a64992f36040c17f4866f45ae7b07019c03464e3c8c1324e96d3f05a2c5205e889fe597b0af2a70c": "0x040000000002000000000000000000000000000000000b46524553484e4f44454b0000001a66726573686e6f64656b4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a64c3dcbca109f3eac1d2d82c4a69b16c3ce9eb5d0b6f34f948a34efe62488879a514bbc837e0e50": "0x0401000000020000000000000000000000000000000010f09fa49620506f6c6b6153746174730b506f6c6b6153746174731668747470733a2f2f706f6c6b6173746174732e696f16406d6172696f70696e6f3a6d61747269782e6f72671a706f6c6b6173746174734070726f746f6e6d61696c2e636f6d00000c40506f6c6b615374617473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6505dd741382407a681b32afa58ec5134541c0f960edfe5d8dd9a94d792d191e238c5a6948c236c": "0x040000000002000000000000000000000000000000000473657800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6654b740dcbab2288acd34d32a3874f7eb5682060fe570c8100554c401bbef2c49dc26ddb1d6d77": "0x00000000000000000000000000000000000933444368656c6f73064368656c6f01010100000a404368656c6f733344000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a67945dd518154113c6767288e0013ce7231aa2c1d5e76c7275e1ccd380392e8bed9ec6fc5445a6c": "0x0000000000000000000000000000000000086d617474736b69054d617474000000000011404a65727a6577736b69747765657473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a695a70bdbfc2aca60f79791d32f2f1d2c352b68b114c682dda46f4ea5f0bcdb891312b6faff670b": "0x00000000000000000000000000000000000454756d0000000000000a4074756d697370726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6e070a349b0a057e037d692951f268505d48389c9ffc60e38b126f3eb8e9adf17fdf6c8961b9323": "0x0000000000000000000000000000000000084c5549354b534d0000144077696c64646f743a6d61747269782e6f7267000000084031784c554935000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6e2ddb0c0dffe479051cb07cf440e1d0d26c6bc80c568a2f4d91367d76fe3bb0bcf215a7753196a": "0x000000000000000000000000000000000008476976657237350000000000000b40676976657231393735000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6f2d5d4c23323f8aa91fc0201f26b713a018669bcd269babf25368eee2493323b1ce0190a178a27": "0x0401000000020000000000000000000000000000000007696e736970780d416e6472657720506c617a61001340696e736970783a6d61747269782e6f72671464657640616e64726577706c617a612e64657600000840696e73697078000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a6fa620b4d132dd76691ffb1fea3613197fdf95dc2d850f7ce48d2bb458810e81b47aed4997ea262": "0x040000000002000000000000000000000000000000000c4869746368686f6f6b6572000018406869746368686f6f6b65723a6d61747269782e6f726710746f6d6d69406e69656d692e6c6f6c00000d406869746368686f6f6b6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a708d9865081ec8abe4bc35b26cdc006c69c1f827d4bfa75e4bfd4ac0094ceaeec8ac70469cac51f": "0x040000000002000000000000000000000000000000000e54656b69742048616e636f636b001368747470733a2f2f68616e636f636b2e6973124074656b69743a6d61747269782e6f72671174656b69744068616e636f636b2e6973000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a71676abeb9f57f44a2802e70326441f6dafa719f9debd8141431a532066f7233b8d5ebb25428e72": "0x00000000000000000000000000000000000c7370616365736d75746a6500000000000010407370616365736d75746a655f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a71bb03524b3e99ae4c74212b31e0efc7f5f271a6636fafea840cb1cc318631b64788543ed12d02b": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000095372536c61796572095372536c617965720000187372736c617965724070726f746f6e6d61696c2e636f6d00000b405372536c617965725f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a729fbef766dde7fd6a0b3f61eb031d847fb2d7d262b7d0e409c01042b2872ebd6c673759c93ef7b": "0x00000000000000000000000000000000000941726d696e5261750841726d696e617300001541726d696e617372617540676d61696c2e636f6d00000a406b6c656261733364000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a72db66667b370238e0fa6d4c1b60eb068b64c965c9c5aba29266a793c130c9b12a1003f01b09d07": "0x000000000000000000000000000000000008536e656d65736807536572676969000012736e656d65736840676d61696c2e636f6d00000940736e656d657368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a7543bc341341829e240ebdf6a3eb4882a6ec2284a2b886071cac52c92dde637b7d8e45b1cfc4a59": "0x0000000000000000000000000000000000044c6f7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a7565e1dd549d62a4e7a56a7e64fd0c4c1d42d431e9ba7749f3a6c733fde04072437b2940338707b": "0x00000000000000000000000000000000000d4d41582d52455741524453430000001364757a6972796e6140676d61696c2e636f6d00000f406972796e613235313432303332000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a763d7749a6cd60306fa1c58ca428edb67bf43766f26256a70bb171428f72e7502f582efa8e4146a": "0x04000000000200000000000000000000000000000000084873696e636875000014406873696e6368753a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a77985bb6c007252867ed88f416454578da3d92589383af4698e89ac93642e6b0aaa2bd8eeba1f02": "0x00000000000000000000000000000000000849726f6e6d616e0a416c656b736579204b000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a794662671bf6a9b2c0ace75e5847f22bfcdf0fdb1ee5a9fc15fe32756572d7c685fba050445b143": "0x040400000002000000000000000000000000000000000758696e797565001368747470733a2f2f78696e7975652e64652f1b406361707962617261676f706865723a6d61747269782e6f726719736f66746c69706173636861726140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a796b643a26045c59c0e1507051438eed8a85c64953a88ac670df8459d30d0686083f56dc1943d53": "0x0000000000000000000000000000000000084e4654636f6e6711496c6f6e612047656c69756e656e6b6f001540696c6f6e617669703a6d61747269782e6f726716706172616469732e64697240676d61696c2e636f6d00000d406479626f7661696c6f6e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a799abc18a65974508cc32a0f27384c6ec57d0318d34e9f90cdc1ed6a2218a630bd57c2465fc661b": "0x0000000000000000000000000000000000064161726e6101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a7a78778d8ac8668c6488a5a0f937b633f9db3046dcb765909e508ac70bad487c614e1002e2d9b2c": "0x00000000000000000000000000000000000c537472656574426561737401010114736861646f76765f636174406d61696c2e727500000c40436174536861646f7676000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a7af572908447d41c05e32ccc9a75ec27b5be1c3f1d00b038e63a487122cd18aa7253b19ec2e6411": "0x00000000000000000000000000000000000846697265466c790f416e647265792022416e645a6f2200000000000b4046697265466c794747000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a7d81691bdb191cf96fbd4b6d115fa19831f56d19076161af05e75f5eae031543e0f52eee0fed57b": "0x00000000000000000000000000000000001a43616c616d617269206279204d616e7461204e6574776f726b1143616c616d617269204e6574776f726b1968747470733a2f2f63616c616d6172692e6e6574776f726b00000000114063616c616d6172696e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a80bd3d653629195e0bb2043610b76d08387a24e267e36bf9a98d17c1958c93f6e4bf35139475877": "0x0000000000000000000000000000000000074e65336c707300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a815c482c3ce0537682c870c88abd2e7ea14e124ee19177b04629a51c7de560038ae850b8707ca4f": "0x0000000000000000000000000000000000054e61636801010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8178389a74a7e720cab3274e2045c86d9dcb81708c13df2a3dd4db5665e9dc64dd9dc148d89955c": "0x0000000000000000000000000000000000054b534b4e154b6f6e7374616e74696e652053687574656e6b6f00001e6b6f6e7374616e74696e2e73687574656e6b6f40676d61696c2e636f6d00000c406b6f7374617362796d64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a82e5a53d12a09aab42563a17307b5666d9a19a03d819884c58f14aaa5c7955eabb0373cc51df56b": "0x0000000000000000000000000000000000064e65656c6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a834d4f336c27b55eed1f0f53dd77141b7e14c986f47952c83bceaa85330bbb79bd5049c02c6002d": "0x0000000000000000000000000000000000022e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8640543b19f19a84ad9207cc7c637de005975cbd7a18c25678fe0539c72da3aee5e481107214e51": "0x00000000000000000000000000000000000954776f506f696e740101010100000c4074776f706f696e743078000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a86cb47311794162923cc59f21372eacb629a4237273e3c7b70e38b7ee6fe2943243577fb3dd5927": "0x0000000000000000000000000000000000076c6f6c6f6275076c6f6c6f627501010100000c405072656d536f6c4d6161000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a88614383e45393734feeab011852aa4af8789a515e9fcf699fe44efc4089da2aeb9b3180f55db22": "0x00000000000000000000000000000000000a4261627920426561720101011662616279626561726e667440676d61696c2e636f6d00000e4042616279426561725f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a88877471b8c0203f6944b2b5f590f132203e5dd4f04c56e594f43b5681a48b210899382c3880b4e": "0x04000000000200000000000000000000000000000000114255454e4f2056414c494441544f524f000017406275656e6f76616c69643a6d61747269782e6f72671a686f6c61406275656e6f2d76616c696461746f726f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a89d5309de30e31c3a10656b4d5bcb51a5c28fa791cfc445c03dd331b1a4201fbf3e7682fbf7ec63": "0x0000000000000000000000000000000000085265737970746f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8a003d6a2d0177ca664f354c48dde8ffb75856a2a6d476cf4759eb2cba712f5f34d24da87a33119": "0x00000000000000000000000000000000000b616c6c636f6e6e6563740000000000000f40616c6c636f6e6e6563745f6672000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8a3ea9a9a3cbf30d21eb80113b2f57759d263c0eb1f02291dbc81a41d5a98029ad55f941eea3153": "0x040000000002000000000000000000000000000000000d77656233616c6572742e696f001568747470733a2f2f77656233616c6572742e696f164077656233616c6572743a6d61747269782e6f726712696e666f4077656233616c6572742e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8c0fe4965a9220bfa0873857fb6d7ea4167b7176e459f3ad4f9a84d9d32c37c97cc07ef71021c3f": "0x04010000000200000000000000000000000000000000094e657762616e6b730f4a616d6573204e657762616e6b730016406a6e657762616e6b733a6d61747269782e6f7267164a616d65732e4e657762616e6b73406d652e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8f89080f3d629d01e069328eb826785f0f58f3f42d0921da45c2c8f60230bc7a6d9f23e420f6524": "0x00000000000000000000000000000000000c44524147414f4e4f5254450b456c7a6f204e65766573000017656c7a696e6e6576657340686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8f9b83743f647ef6aa99658e2b0755ca9f1ead5bde1ff6249f25d37cf1e7b5214dc31ce2d67e35e": "0x0000000000000000000000000000000000063031656767000000136b73616e6164757540676d61696c2e636f6d00000d4065636e6c6f535675726576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a8fb89fb3cff01fbb8a042528b36775f3f2644ef54a2f4cf34ad33ebbe538ef1112af09244428d71": "0x0000000000000000000000000000000000094d6973746572334400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a916ff8cbaa3dbb2e048fd6e69598e9af4aa6bdb31c470c5350cb29433bdaadd05fac776f7447e24": "0x040000000002000000000000000000000000000000000a5374616b656c616e64000016407374616b656c616e643a6d61747269782e6f726716616c6f63686b616d696b6140676d61696c2e636f6d000011404576616e4d6f756b68743232303034000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a922ab100b50050438ee604a9f82f3f702f49b4bc794c684e7097aafc63b4c2ec3f579110fc77102": "0x00000000000000000000000000000000000444525900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a93c6e207f351cebc5c184f0565e2192d6aedae584ee736cef875f0e1c558ee3ede26869acd0b4d6": "0x0400000000020000000000000000000000000000000013f09f8c8c204e6f766173616d6120f09f8c8c164e6f766173616d6120546563686e6f6c6f676965731568747470733a2f2f6e6f766173616d612e696f2f1140646179373a6d61747269782e6f726714616e746f6e406e6f766177616c6c65742e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9420133b7f85dd418af8d860e3138ecbde8349b7062c6ea5e440850c028e9c1625253890f1e5628": "0x040100000002000000000000000000000000000000000b5a616368204a616d6573000016407a6163686a616d65733a6d61747269782e6f72671d65786368616e6765696e717569727940747574616e6f74612e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a94e1e206d46f06cf451d9aea4d117a8724a9d55c25c968a7a8027a0912bbee2543e3a38eaabe94c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9541c4772f19bee9cba8900744a61a81cecd63e84ba19aec07dbfdf0dcf8e649daa9b31545f2e7c": "0x000000000000000000000000000000000012524d524b20506172746e657273686970730009726d726b2e6170700011636f6e7461637440726d726b2e61707000000940526d726b417070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a96b781a4270f369de797dd6265e5d3b12a9701b7cf7612c6104610fd35f6c61b5d760a5cebc327d": "0x00000000000000000000000000000000000c4d617a656e2053616c6568154d617a656e2053616c656820416c6a6f68616e690000116d612d7340686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a97f5e4fe69abc071c3c0915fe5c823928143e78ebe2046676d0c84a9dc73a51df007e094fb4046b": "0x00000000000000000000000000000000000764657673756200000000000008406a696e786338000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9939a663235c70ad2b5076d5c090233682d61cf1b2668d1466255e2030bfce0e38eeea730a1ae75": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9abc96ba1ca531998d97c7f257bdc631d5a9a10e639a7a3402177a67669f01bfce163abdc14bc11": "0x00000000000000000000000000000000000a7665726f7961746e6f001e7777772e696e7374616772616d2e636f6d2f7665726f7961742e6e6f2f001e7665726f7961742e6e6f6f6f6f6f6f6f6f6f6f40676d61696c2e636f6d00000c407665726f7961745f6e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9ac2596fb290717a4f1e970b856afb2bb1ef07cbdc9308267d54033c1d602da5939c46ff3decb10": "0x0000000000000000000000000000000000046e6d6300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9c0101f5bde7e255a47dd2d6aca2d7373c5bf19ef5f771ce1646f0b869d0f34271785de8e44e51f": "0x04000000000200000000000000000000000000000000127374616b652d6d616368696e652e636f6d001a68747470733a2f2f7374616b652d6d616368696e652e636f6d1140616b6d653a6d61747269782e6f72670000000e405374616b654d616368696e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9d5aef332a19f2e0ceee7d84f1e2c0f6b4d3b29eac3a3c5b2586d3fd13f12e2c90427f5208e610e": "0x040000000002000000000000000000000000000000000a686172766573746572000000176e6f6b6f676972692e73727640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9e8d7579b6c63d09c994bd7ab2ac6093f2a3bae11b36c1dadabcfae55c21afc9c823239c151bc59": "0x00000000000000000000000000000000000d50756666657220426c75647a00000016707566666572626c75647a40676d61696c2e636f6d00000d40707566666572626c75647a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9f08d3911f890e17a0625bffca33ce094f74f399580b16674ae3e0cc8ef259cde618e60e927ae53": "0x040000000002000000000000000000000000000000000d4b525950544f53434841494e00001c406b727970746f73636861696e5f79743a6d61747269782e6f72671b6d61726b6574696e67406b727970746f73636861696e2e636f6d00000e404b727970746f73436861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714a9f9ca9189790e6d984a272e9701a4280010de2ca4b6a8036ad527f4f8a4d3f8568dd40ca4bbb929": "0x000000000000000000000000000000000006526164656b0000000000000a405234646f736c3477000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa006ae101e5026b0e76e3ac1594a10ba3ac43455a6195b9ade199408127ed344a12e1feb4c1fa1e": "0x040000000002000000000000000000000000000000000879616e6777616f0000144079616e6777616f3a6d61747269782e6f72671179626461626140676d61696c2e636f6d0000094079616e6757616f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa02456a3c239f66f43c777cb76a32b1cabdf02bd5ad1ec330663043d33917da9151323f3a846023": "0x000000000000000000000000000000000008455845515445520000001765786571746572646976696e407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa06495c700f98f1f446b0fa660760f015c4fc7cd39c89deb69ed5f7e8b9652f6b14516bb2698517": "0x00000000000000000000000000000000000b4c6f75696520524d524b06627265747400000000000b406c6f756965616c7473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa31b7d6b6c621c5280c01b232926c260a77f08c52e13c6b87e56e6172b6cb767a9274ce15b7f254": "0x000000000000000000000000000000000007616d69726b6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa5d460a7e61942d6c05e68f748e5a4a68cd353ddf96dcc22395722e9a03cd814a9c5bb964d7aa30": "0x00000000000000000000000000000000000950697869446f74730000001470697869646f74733140676d61696c2e636f6d00000a4050697869446f7473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa66c809e7c7caee244a202cd6b29e2026b65a07c3fb32422138a122e581a627e35791da331bc905": "0x0400000000020000000000000000000000000000000008566172656a6b6100001440766172656a6b613a6d61747269782e6f726718766172656a6b616c657661796140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa73eb5624e30cd3ce8d12b99ce263a7d3c6ef0e361551a4fcc80e777b61ef1866ffb47a288dc15d": "0x0000000000000000000000000000000000086375746661636508637574666163651e68747470733a2f2f796f75747562652e636f6d2f632f6375746661636501156375746661636570726f40676d61696c2e636f6d00000b40637574666163655954000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa755f1de043396afa3a43c08b6d2eb836c98ffe0e3936f50f54bbd2a31e5a2b4686c6ce187cb479": "0x000000000000000000000000000000000009636f746f7061786900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa76e80be7235fbb9404ddc2d30b821106b545eabb8d22b38ceaf86ed56a37f9f14a37140050bb4d": "0x00000000000000000000000000000000000a4f6c6568204d656c6c0000000000000d406f6c65686d656c6c5f7561000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa7bbf43874b9d190c0a3067cabf39e1a8bb185fbd95b274aa838916e6adcb968cbe99fcc0b0c779": "0x0000000000000000000000000000000000044e54200101010100000b404e617373696d543932000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa92e5948766b8968e3b5643d507e6af52fe12a5b4d4d095881e687cdba55e9d0e9f81600ab30b18": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa92eeacb2f4017c0a409ce1eed912358015a8139383b02292284b392bf23ef9eb89c7f31ed7e10b": "0x040000000002000000000000000000000000000000000b47616c6178794e6f64650000164067616c6178796d656e3a6d61747269782e6f72671767616c6178796d656e34363140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aa96f99f2185e3646069548e7913a106991a40988bd63d25996d6788f9302ef0a86ec40b4e6bd36f": "0x040000000002000000000000000000000000000000000e426c6f636b20427265616b657200000019627265616b626c6f636b706f73744070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aaa3cef8c09f417f2a807fc9b3748a0d6b964bff11360e00040fb5fc569a9595532f935286a45f47": "0x0401000000020000000000000000000000000000000011e2999e47616d655468656f7279e2999c001668747470733a2f2f67616d657468656f72792e6d65184067616d652e7468656f72793a6d61747269782e6f7267136d61696c4067616d657468656f72792e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aaaaeef2f5df648fccf47a2ac8ff8fdf1511044e5040f946f617915ab09a35a4d2b7f16b60bdba1d": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000001a55542046696e74656368204b7573616d61204163636f756e741e556e6976657273697479206f662054657861732061742041757374696e1368747470733a2f2f7574657861732e6564751940757466696e746563686c61623a6d61747269782e6f726712636573617265407574657861732e656475000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aacd06621bc7fa58402c5a21657ed72700a7b5b18773b060eef6d8fd448a86a01138dfcd9a41677b": "0x0000000000000000000000000000000000085343414d4b494d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aad10b10ac673adf84354a60e57e717efbf60e05a7f8df7982a6054f48fa6c34b2d66a1f2f940f4e": "0x00000000000000000000000000000000000e68756d6d75736f6e7261696c730e42656e20477265656e626572671968747470733a2f2f62656e677265656e626572672e646576001862656e2e677265656e62657267407061726974792e696f00000f4068756d6d75736f6e7261696c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aadb474af3b7652ba4e3fe06c7686f779f50f956b9a36486107808a86666a1105c598abf0cdd9020": "0x00000000000000000000000000000000000b43726f636f7a20426f790000000000000e404b7573616d6143726f636f7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aae05b931631df4deab5016cd6102b4684337646ad1c880eccc696a5279bfd1857a4033f418f014f": "0x000000000000000000000000000000000018546865204372656174697665204d696e6420576f726b730000000000000a4075676c7970616c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aaeed3ff5f7c6546305106e806e5964b54882b0253bbe6bb25fc4437dcb7d162551b2114a86ef81b": "0x0000000000000000000000000000000000105370656369616c204167656e74204b0f4b6576696e204b616d696e736b6901011b7370656369616c6167656e746b34303340676d61696c2e636f6d0000094073616b31333337000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aaff4d5a3b6c0d71aa7880fe9ca2bbf331fc13e40525dcb0da661f143df506fed76d8ada3db8f551": "0x0400000000020000000000000000000000000000000008536b7974726f6e00001440736b7974726f6e3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab090ef5db55f2a2a6a50a55a5a9ae7f9b80282cd64afb109232a94ff5402785e6174c77f5364740": "0x00000000000000000000000000000000000c427564646861677563686900000016627564646861677563686940676d61696c2e636f6d00000d406275646468616775636869000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab15b2cfee5d067cfeff500e183af7ebb6c66d217a35540bc99f91f5c8ca745f189c7a8e02523263": "0x00000000000000000000000000000000000a6176655f766c61647900000015617665766c616479313140676d61696c2e636f6d00000b406176655f766c616479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab1b531c27836eb194fe1c5670fe87032f21aef7ab7089328f0014a104085c9ec123a18fa46bf23a": "0x00000000000000000000000000000000000d4b5553414d412046524f475a000000166b7573616d6166726f677a40676d61696c2e636f6d00000e404b7573616d615f46726f677a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab2f26fdb66b7e0f02603a8ccfffd5b74a929869750a452583b36782928fbb4d21d467d31ca5912d": "0x00000000000000000000000000000000000f706c617374696320736e697463680f706c617374696320736e6974636800000000000f40417274556e6465727261746564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab47f5a74f1518f11e3a86311df89c922a9fa04ce93d9233ae6ca68e9a4e84514c833bc62b98ae57": "0x000000000000000000000000000000000012477261766579617264204275646469657301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab4cfabd58cd57c4b057b598310f90e7b899cbaea0bc1866fcbf3af525641e40b1b1a983bf840f30": "0x00000000000000000000000000000000000a73796e636c75622d350a53796e636c75622d35000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab6c59cef8a0b91fb0bace3fd1908d2fd2894c39d218b13c2095285a9b0f8634e12689ef0963186c": "0x000000000000000000000000000000000008547261644172740b4e465450726f6a656374137777772e6e667470726f6a6563742e74657a17406e667470726f6a6563743a6d61747269782e6f7267136e667470726f6a65637440616f6c2e636f6d00000c404e465450726f6a656374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab727efb89c9f962a44b893b7b290c0e65eef94bde35efc9dda666544da7c59843c64db46850e915": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab7ded53df100477da35e75473c26344448602f4c2ae540e1a28dbb2772529f06930cf61a3b7ca19": "0x0000000000000000000000000000000000064c55524f420d4c55495320524f424552544f2168747470733a2f2f6f70656e2e73706f746966792e636f6d2f6172746973742f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab7e3e98c718729f7a895955042cb3fe863f3564e7b30e9130e37b6d905be11c0cf91064de1cd83a": "0x040000000002000000000000000000000000000000000853544b442e696f000015406672617a7a6c65643a6d61747269782e6f726700000011406672617a7a6c65645f64617a7a6c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab817fd9c538caa7e615d6d583a7c958db2c97347de2c8830e3f6246e9b7adc272f28e373be3366c": "0x00000000000000000000000000000000000a526f6d616e6573636f001568747470733a2f2f726f6d616e6573636f2e6169001368656c6c6f40726f6d616e6573636f2e616900000d40526f6d616e6573636f4149000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ab8afdd8f0ac6b745e7b0fb60cbb96d9e6325a80e8e14ae76826a53a944f299d3408337436a69631": "0x0000000000000000000000000000000000084861776b69736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714abd298c8604cc4203058bc565c6c6fac47bf50cb3f14df3f7e0da993b4e8be978963740ddd96a52f": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30330e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714abd8088ba391de8242245c83d3a57fb95b74c05157a15cef637c0c64573b1ae493f8f3c3df13714e": "0x0400000000020000000000000000000000000000000007414547495332000013407369676e79393a6d61747269782e6f7267117369676e7939407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714abe7caa62e5fc36ae6d808f3c2107a51d89762cd838ca246c9b4fe83d15077732694fe9dc9279165": "0x000000000000000000000000000000000012496e73696768742066696e616e63652032001f68747470733a2f2f6d6f6c65737761702e696f2f63726f77646c6f616e730014657269635f64776a4069636c6f75642e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac3727c0a32917e62c5bca9fd4c92b051e35c47617175d8f28aba000ccf921cb24bdf555662f2d41": "0x04000000000200000000000000000000000000000000056b6f7a750000114067757a6f3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac41f4731ee7b7d67058b4f0cca3807c138068a8c98af65745d8ce4ce287c704a113c80bcc19874b": "0x00000000000000000000000000000000000e54686520496e73706563746f72000f61626f7274696f6e2e726f636b73001561626f72744061626f7274696f6e2e726f636b7300001040646f6162617272656c726f6c6f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac5da0493129f685f005964968c50de1ad4514e1453fbed546bcae7508185f8f6f116b98df392c3d": "0x0000000000000000000000000000000000154469676974616c204e6f697365204d757365756d154469676974616c204e6f697365204d757365756d176469676974616c6e6f6973656d757365756d2e636f6d000000000d404e6f6973654d757365756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac6f1c6373257f1a4284fa7c290fb6052b9437610cfb2e19b3b37081fc72140e444d5b57ca01924d": "0x040000000002000000000000000000000000000000000e576561616b204361706974616c00001a40776561616b2e6361706974616c3a6d61747269782e6f726718776561616b2e6361706974616c40676d61696c2e636f6d00000e40576561616b4361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac7dc49ac8e1155e3ebc5e567e66f61937449b0c00ca928ae0b2c45e6331e426b756fd5787c73036": "0x00000000000000000000000000000000000e53686964656e2047726f7774680000000000000e4053686964656e47726f777468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac8c20eece56914de20112991cc5c6843ed49189f02b5665847d3e408202737bea3fa2d01a69a10a": "0x00000000000000000000000000000000000c5468756e6465726b6f6e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac94e97916c4c22f789becfbaf6d1af5ce67bd164e99eb01d0d677f830d54db4b6aae25543857465": "0x00000000000000000000000000000000000c4b5553414d41204c414e440c4b5553414d41204c414e441868747470733a2f2f6b7573616d616c616e642e636f6d2f001a68656c6c6f6b7573616d616c616e6440676d61696c2e636f6d00000c406b7573616d616c616e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac97e11542df6e0b98c7819c80977d8895f62907d6f2583177ee7ff77c6c661989b43f834d534d7f": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ac9c3b250f38c666aa4f9b4fe0e5591c49e938bee099a2462e7d1b274f652ff14376b6ec37c9e335": "0x00000000000000000000000000000000000b4d617273684d6344616e01137777772e6d617273686d6364616e2e636f6d010100000c406d617273686d6364616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714acb114a0152b1c7e2e6bfbe96e1c1a46e86a7e085fe5d748c8d0f38dc0d721378d8c9a55fc27c446": "0x0000000000000000000000000000000000074665726162670101010e62757263756740676d782e617400000c406564697a6b726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714accc7e5f392e9a0c9e758090b4cf20c4ffc9b30b07e41823bf447634b448c7b12bd011631735c814": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714acdafe2a83e3f2dd48f9d09659267bbe934aac85662d64591bae57d22266311f7fb8dfd458bd9338": "0x000000000000000000000000000000000007616e6472657910416e647265792042616c6173686f761768747470733a2f2f6e6f766177616c6c65742e696f2f1240626c7368763a6d61747269782e6f726715617762616c6173686f7640676d61696c2e636f6d0000084062616c736876000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ace3fb0f376c313f2ee247d45c4d034caf805fa22e3bf529b78d04bf33b11ba9a1cf10f7275c4c08": "0x00000000000000000000000000000000000d487970657220536861706573055065706500000f7365736f6d406d61696c2e636f6d00000b406d696e75737269746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714acf521c66337a1c992aa2496da20d35abf5407fcbcfa62741358276109b86ef2d0bf3774838b9649": "0x040000000002000000000000000000000000000000000b4d6178496e4d696c616e000000196d6178696e6d696c616e4070726f746f6e6d61696c2e6368000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad2218b3decc8eb22eccf3598b22853bd4de4a8340363f1af10f217a578892b569c76e7368253734": "0x00000000000000000000000000000000000b706f6f6861746e63737501010101000011405061756c5061743534323133343530000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad2c753ff14dd79164820bb673da18602df1750a214ec8e3ab14815994de12d01bcc46e9a6de476d": "0x00000000000000000000000000000000000e4d6564696f63726574697665730e4d6564696f63726574697665732168747470733a2f2f747769747465722e636f6d2f6d6564696f63726574697665002073696e67756c61726d6564696f637265746976657340676d61696c2e636f6d00000f406d6564696f6372657469766573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad2d645b1ffcbcd23afbbdfaee3e5ed51710c3aa8147b4c28f5260c8bb94e75735e8c4004452d555": "0x00000000000000000000000000000000000c4c617356656761734d616e0e526164656e6b6f204a75726f730000176a75726f73726164656e6b6f40676d61696c2e636f6d00000a405261794a75726f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad342401c1554edb98299ef0de2ffb12a98370326e70ac683862c78d592970f7294244c1fb370d4e": "0x04000000000200000000000000000000000000000000074e6f6465733100000018616c6578616e64616c6578324072616d626c65722e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad35c1615f01572956d629a2c80762d412fad9c15d8cc973b463f600895170d43a10ca504b4f454e": "0x040200000002000000000000000000000000000000000852594142494e41001368747470733a2f2f72796162696e612e696f144072796162696e613a6d61747269782e6f726710696e666f4072796162696e612e696f00000b4072796162696e61696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad8ddc0ca11a0cfc2cc3c4f5e22e3a59a0ca34de4ed55e532bb842ea36626ccab7a01378dbcffc31": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ad968b9e29de99cf0c705f5ccd12c95bddf10c698f7cbb92d224b099fc759f5f9e1ebf220a685972": "0x00000000000000000000000000000000000753515541445a0000001873717561647a636f727070726f40676d61696c2e636f6d0000094053515541445a5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adaaaeb1d3993c798ac9852f42ff7fde06bd98fb2c2c4b3f18ecc0d7117cefc3acffca60a86a395d": "0x000000000000000000000000000000000006454a56494900000011656a6463303740676d61696c2e636f6d00000940454a4443417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adaacbddd276fad892b68c8f6d36b8ca3bf3f31c200750ef773419b294216127f2aaeed9834e8f12": "0x00000000000000000000000000000000000d414e494d45204c4547414359001e68747470733a2f2f646973636f72642e67672f416743557a44353737760019616e696d656c65676163796e667440676d61696c2e636f6d00000f40616e696d655f6c65676163795f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adb4fe3a15170520a6659e4c3f22c2aa97d54a36e31ab57a617af62bd43ec62ed570771492069270": "0x040100000002000000000000000000000000000000000a525454492d353232300f5261756c20526f6d616e75747469001c407261756c2e727474693a6d61747269782e7061726974792e696f177261756c406a7573746f70656e736f757263652e696f00000b406e6163686f72747469000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adc1094f94b7e6a19e33f55832314d732b6201019a34e6bee2d0050d05e48792f908927004807d4a": "0x040000000002000000000000000000000000000000001052656420446f67205374616b696e6700000019726564646f672e7374616b696e6740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adcb6799f01113f1147f672b1be04ef277b6175efd27a5691d4589944175985e37fbd4a50fc49e1f": "0x0000000000000000000000000000000000086c7563696f6377000c6c7563696f63772e65746800126c7563696f637740676d61696c2e636f6d000009406c7563696f6377000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adf6f4946cd7e9bd36d893f519ad2ade0e563049a74f7f4a629c664344e294f12dcf295dcb9f134b": "0x040000000002000000000000000000000000000000000850727a656d656b001968747470733a2f2f6769746875622e636f6d2f727a616470134070727a656d656b3a7061726974792e696f1270727a656d656b407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714adffa60d83e2d26fd63749b70cd25854d6accabefa8939f92bd2034e19b32deb67130ab0141c3228": "0x000000000000000000000000000000000003494f00000016494f37384f494070726f746f6e6d61696c2e636f6d00000840494f37384f49000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae0f2e475df6cdca56b0bce13b96ed2d2e3d93cb0b96d21117352df2d473fdd111ac7febbd721a3b": "0x000000000000000000000000000000000008416c69736177790841627562616b7200000000000b40616c69736177793031000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae19368d93e1a11446ac55edf7126c062f60ddf13c421406126155fe5377abc33bec6e7ec9b98f54": "0x00000000000000000000000000000000000a4c6f7942616c646f6e0c4b61726c2042616c646f6e2168747470733a2f2f7777772e6c696e6b6465636b2e6d652f6b61726c62616c64001962616c646f6e6b61726c6b61726c40676d61696c2e636f6d00000d406b61726c5f62616c646f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae19ce23547ca726ec822a69ea8e95513f81967b0c048386598a107c88c49dae54f1d94b0cba802c": "0x00000000000000000000000000000000000e416273747261637420536563740b54796c657220526f776500000f746a726f776531406d652e636f6d00000e40416273747261637453656374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae1a5c36a02b18e9103a9ebd690d8e1dd5e8f3cb43b05586bbfbd8c36ce3e976b6f45da4a60ff01d": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32350f42696e616e63655f6b736d5f3235000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae2793d04574eccc063443a7dc2c49d6256a61c92bb0515ce6a641bacf9b42c9ec78b913f72c470f": "0x0000000000000000000000000000000000075069706c6f70075069706c6f7001010100000a405069706c6f707070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae29da2b825c96019285049cf1f37e3e312e2367a3768fb066598d309d4a4ccacfb70137714a4404": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f31380f42494e414e43455f4b534d5f3138000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae2ca4581ebd097944e0753f9e387f2ad25607a94c8e17afe7fc505d65bf7de78d4e87d4a8804414": "0x0000000000000000000000000000000000184b7573616d6120447261676f6e7320547265617375727900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae35f46bc40f624a76488519b246e6c8fc7ddc438a876db42446cfbe25ee73a873e696775821615d": "0x00000000000000000000000000000000000f546865756e69746d6f6e7374657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae37ed4115e2f104feb895bf0e5923afd22e8edecfb4a9ce6263d447ba45375dc4d280ec0d3d1a16": "0x08000000000100902f500900000000000000000000000100000002000000000000000000000000000000000a41554449542e6f6e65001268747470733a2f2f61756469742e6f6e6516406c6974746c656972643a6d61747269782e6f72671068656c6c6f4061756469742e6f6e65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae47ffa8b83cf8eb1cfd7bfee0e9629e1fc2a35a40fedf43436915a1d1a14604d788eb0a5cd12442": "0x00000000000000000000000000000000000c64656c616273747564696f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae4964a1652132ffe242bf627ae3347d67991e1b2ebff0a013bcf27ddb96c5cc4c09f1720bbf8471": "0x040100000002000000000000000000000000000000000847616e6a616c6601010115617269735f6b6f6e3934407961686f6f2e636f6d0000104047616e6a61496654686547726579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae81b3857066f7b0202a4b121f7c19db32d07246ca42ba38faaf82f5d7fbb929d6c35ace78f4d521": "0x00000000000000000000000000000000000a4f6c6568204d656c6c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae93bd56eb26fefac88b7d581246140ac334a9701a6b63b609c0e4d1e0a4dc7ed518093e7977c265": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae9b31f551254fb3ea1751759b8191b2b400bfe38b56f0442edb875c3390c2af3c1edeb2892f300a": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000008436c61697265650000001a6b6c61616161726b61614070726f746f6e6d61696c2e636f6d00000f4044655f6c756e65436c61697265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ae9ba12db96645e32c24642cef14e77315bf467c00917c749a19c3e5a6df705548a67aa7ad0ad138": "0x040000000002000000000000000000000000000000000b504f4c4b41574f524c440b504f4c4b41574f524c441c68747470733a2f2f7777772e706f6c6b61776f726c642e6f72672f1740706f6c6b61776f726c643a6d61747269782e6f72671c7869616f6a69652e70616e674066786861736862616e672e636f6d00001040706f6c6b61776f726c645f6f7267000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aea617318e829b5f12ae4cc150cef3f9e224d7b6cb10383e91a355a9c9052e21c1c638dbebab9921": "0x00000000000000000000000000000000001d57696c6c69616d207c205061726176657273652054616c69736d616e000016407265706c67686f73743a6d61747269782e6f72671577696c6c69616d4074616c69736d616e2e78797a000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aeb7ceb911a5fe458c2f8f1570391214b89f82df1e2e0c12f9e2e814cc8e38b3d8baf3692724a311": "0x040000000002000000000000000000000000000000000b44656c6567612050726f0000001c7061756c6574746576616e686f6573656e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aebcdd1a0eab5430c284a353b40066c06ccde4c573083785d245d5b2838c1ee1281f09c14f0c4b3e": "0x040000000002000000000000000000000000000000000a50757261205669646100001c40707572612e766964612e6e6f6465733a6d61747269782e6f72671a707572612e766964612e6e6f64657340676d61696c2e636f6d00000f4050757261566964614e6f6465730010707572612e766964612e6e6f64657300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aebd88238d3a6853e4340b480dc1067cc6eed90dbfbb55eccbf4b290860eac100caac06cf7bfe50f": "0x00000000000000000000000000000000000c536c75675468756767696e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aebfc4a3abbe2861e2b2f3f1826834a30b035da7502c657d702287f295c944292ceca13436f2525f": "0x00000000000000000000000000000000000b6a6a706f6c6b616465780000001a6a61796173696e6768616c3230323140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aec040a9a30c2fa408dda0877b73535dd8e892916397ac9ceccb44b8441122bb434b17e2db376d03": "0x040000000002000000000000000000000000000000000c636172626f6e7a65724f33001768747470733a2f2f636172626f6e7a65726f332e696f001c7374616b652e636172626f6e7a65726f3340676d61696c2e636f6d00000d40636172626f6e7a65723033000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af08e5f294e1dbf3e08ca157a6b33c275a3141a8f1d0d26fdb69cdfabcd9bbbc04121009ab9eac6d": "0x00000000000000000000000000000000000c416e647265772044697a7a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af0f194ca5eedf8696cfb23cc08b9267a778c38e9aba684d2708786813c14ced80a51c32014e8c17": "0x00000000000000000000000000000000001067697073797472616465722e646f740c6769707379747261646572010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af17ae08f9526c52d2eeb4ca57167ef272dd79a7e07be6b9e0f825932c46bc21e64c9d4d96c80f47": "0x0000000000000000000000000000000000074b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af1c32392abb5cec8884900b83686025314b36118c490de387482dd7aa54c1fe3ae3f3b74cd0f347": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af26cecf04b0d6f91a48da57cd9e71d434c2c4c043d7304ab2d0b4f04db9194f6bcb1a7d5cc7b822": "0x0400000000020000000000000000000000000000000007726f64696f6e00001a40726f64696f6e706170613030373a6d61747269782e6f726718726f64696f6e7061706130303740676d61696c2e636f6d00001040526f64696f6e3034373039393331000f726f64696f6e303037233535353300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af2cc3fd6d2f53af265f0277528dda506dfc7451261a78f74b159bf1032d917b8622657d0fcffc4f": "0x00000000000000000000000000000000001d526f6d65726f2074686520446567656e65726174652041727469737401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af36192670e89a839ecb437788f1e911c3a324b0d377b46bc2e56ecd68cdc11f827f3edf81e7a23f": "0x0000000000000000000000000000000000094a616465204b6f6101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af36a552655d8727a03a7d4a2e5b472c56e6282ab563aa3c9dbe1fcd82f2d954ef86d8c67c89575d": "0x0000000000000000000000000000000000106361727465697261206b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af64089eb873bdca2ce5f06beaee8b512f2cbb5192296ad4c2ff3359fdc2cea9cd613903a7c8360b": "0x04010000000100fc8d0e800000000000000000000000000000000000000000000000000000000d506f6f646c65546f794e46540d506f6f646c65546f794e46541f68747470733a2f2f6c696e6b74722e65652f506f6f646c65546f794e46540017706f6f646c65746f796e667440676d61696c2e636f6d00000e40506f6f646c65546f794e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af8778444f4de017a26dac20e5b6200fcbbd2fe377f3db8101a7ac0f97dcd30cf21a9ebef4728d2f": "0x0000000000000000000000000000000000084570697374656d000000196570697374656d6963726973697340676d61696c2e636f6d00000d40496361727573526973656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af92c79ba730b3d974494d37fcd7c5ba35a87b4d9a5c86a890b4b10e0c00e935ef4a8d0853428637": "0x0000000000000000000000000000000000084e464b2044414f001e68747470733a2f2f646973636f72642e67672f355550763242475565530000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af98277273da6e43692f87b14dc9169f22bbe981d976de2d7fc7495c361dafc154eb21a03c5035a2": "0x040000000002000000000000000000000000000000000d4c494e4b45523639f09f8ead0000001530786c696e6b6572363940676d61696c2e636f6d00000c4030786c696e6b65723639000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af9993b81e5473d034a31d751a0ec52fbf411513a3cee3c7c6c1a2c2bacc3f809f3ead9eb9bae348": "0x0000000000000000000000000000000000064e696e654600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714af9ae6e4f434181d9c322cfa42b80ffb1fa0a096ffbbe08ff44423ea7e6626183ba14bfb20c98c53": "0x040100000002000000000000000000000000000000000c456e73526174696f6e6973001c68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b2f1840656e73726174696f6e69733a6d61747269782e6f7267166c7340726f626f6e6f6d6963732e6e6574776f726b00000d40456e73526174696f6e6973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afa63c93073adc978e06bfc989509d6d625c085209adb405867bdbe4f167ded7e61ec126c683165d": "0x040000000002000000000000000000000000000000000653617368610000000d68694073617368612e696e6b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afab87883b2986dc6ee5ad3ea0da40510f11f42c3281fd543f5a6bfad54ebef7381a7320bb509a0d": "0x0400000000020000000000000000000000000000000010477572755374616b696e67f09f91b3001868747470733a2f2f677572757374616b696e672e636f6d1840677572757374616b696e673a6d61747269782e6f7267167374616b6540677572757374616b696e672e636f6d00000d40477572755374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afc3bdc7245962d07c9f7a1b77cd672ba9c9f01a933ce98effbc36bb57503a4f671bc6f01e25f335": "0x00000000000000000000000000000000000862796e61745f5f114e6174616c69612053616c64697661721968747470733a2f2f6c696e6b74722e65652f62796e61745f00000000094062796e61745f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afdc8afb93fda6f506a3316928fa06115766132478d1e7b9385bea8e0e411a8c6056f12b3d13ce7c": "0x000000000000000000000000000000000014395374616b652028436f6e74726f6c6c65722900000017397374616b652b6b7573616d6140396761672e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afddd653b3cc45ff4036da32f7b6ae9df4e3f7e29f2f0c3e42d893976c993633b952bd8c8754d408": "0x00000000000000000000000000000000000b416c6578204d616e74610000000000000e40737469673330385f74727565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714afdded1663a63773142eba87db082b693b5f35e88d7a70409b0ddb61d430abf218884d4467af1024": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aff1fbb6c9b02bcf8213f1a5a5efc5379fc21131f5c9425dfef0f628cc858c2d54b713e96b1f607b": "0x000000000000000000000000000000000007436f6666656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714aff2ef9eab1786a6a680f1d3b6abc1351b6b0afd91a54c1d466b7820abeda0bb7e059513a4d80c04": "0x040000000002000000000000000000000000000000000b4e61706143727970746f00000013746f74657374656b40676d61696c2e636f6d00000b40546f74657374656b31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b009963bd6cf7f553e3fedc679e48594357377ab604693db948db02922e5f7f1740581d1d6fc3608": "0x0000000000000000000000000000000000154b75626942697420496e64657820536861726573000000000000104074686567616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b05ea025efa6e1a0aac311fdc8e841ba529158c0da3b3b0e1efabbeb980b2186d7f6194388da6131": "0x00000000000000000000000000000000000668756f626900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0726c73592fd7dcacd0b478fd9586fcfde7d71aaf49bab9777e0e1ccfeef5d5922bfe68fe68c96b": "0x040000000002000000000000000000000000000000001053756c74616e4f665374616b696e67002168747470733a2f2f7777772e73756c74616e6f667374616b696e672e636f6d2f204073756c74616e6f667374616b696e672e636f6d3a6d61747269782e6f72671f73756c74616e6f667374616b696e674070726f746f6e6d61696c2e636f6d0000114053756c74616e4f665374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0a155d537be68bc40c46bdf410fc4998d2413619de53b7cf4619abca4e8ad87d8a3adc50ec73f2a": "0x0000000000000000000000000000000000086b75736d616d61001c7777772e696e7374616772616d2e636f6d2f6b75736d697465636100146b75736d697465636140676d61696c2e636f6d00000b406b75736d6974656361000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0ac057a255285ea7000a09ee477781f180c3ce5ead45d6ed8d92d24a5abcfec3f24837c38ca1a40": "0x0000000000000000000000000000000000085348525553484100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0c27f90ac9d10a58adc4e19e79b3d2c744f88fa5aca47ef05ccaae141f6435c2d50df824433ae48": "0x04000000000200000000000000000000000000000000144859504552535048455245204449474954414c001d68747470733a2f2f68797065727370686572652e76656e747572657311406876616c3a6d61747269782e6f72672076616c696461746f72734068797065727370686572652e76656e747572657300000e4068797065727370686572655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0c82179e29e010760c9cc0b9b314c31215486883e1b0ee9faf0a64ec4c9abbde63e53855bdc2219": "0x040000000002000000000000000000000000000000000568696d65000018406c696768746e696e6773623a6d61747269782e6f72670b73624068696d652e616900000e404c696768746e696e675f444e000c4c696768746e696e67534200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0e8c1857841459cc005652d40096e4fe6d2ac773d8834e30e31ec39e455f5116ab76176f2b30166": "0x00000000000000000000000000000000000757616c6b65720c4164616d2057616c6b65720000186164616d77616c6b657238344069636c6f75642e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0f0b3ac307cd751749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b757": "0x04020000000200000000000000000000000000000000094b6565704e6f6465094b6565704e6f64650d6b6565706e6f64652e78797a11404472756e3a6d61747269782e6f7267156472756e2e6d6167696340676d61696c2e636f6d00000a404b6565704e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b0fe6b98334d7d6cc4516751df2e5803bac3bf9cf7b6d55cf4acbd76f861ad0a2a2b71b7a5ed8054": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000010626c6f636b6461656d6f6ef09f988800000018737570706f727440626c6f636b6461656d6f6e2e636f6d00000f40426c6f636b6461656d6f6e4851000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b10065a77e52723a249ac734e3c93c449fb84dc63e3305a8bf8280ecb3fce23f8b59fc4d22695264": "0x0000000000000000000000000000000000074b734d6f6f6e000000146b736d6f6f6e70726f40676d61696c2e636f6d000009404b734d6f6f6e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b11058f1454ffb44d2d09f95d0f12add7c3917ee547d24ed7e1f11bb5d93a1c59fe79c1305604128": "0x00000000000000000000000000000000000a5472757374426173650a5472757374426173651a68747470733a2f2f7472757374626173652e6e6574776f726b000000000f405472757374426173655f4e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b11aaa4195d2ac6dce35dca783c5b947a69d789c5d3f10e3e2a5177321d1e6bf88a7e7b46c57d329": "0x00000000000000000000000000000000000f546865204461696c79204d696e7400000000000011405468654461696c794d696e744e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b16947c55a8fcdca9cee29ac72489e226911a3e13cc12e83655f3b2ba98c72760cd8e066c5f6bb1c": "0x00000000000000000000000000000000000b4d725069c3b1614b534d00000017636c617564696f70696e616340676d61696c2e636f6d00000d404d7250696e6170706c655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b171be44e280759d380e0679794d9d5b8202444c893a17cff2cd2e65e76d095eeefaaa9362a3cf42": "0x0000000000000000000000000000000000057065706f000017407065706f6f7370696e613a6d61747269782e6f72670f7065706f4075707274636c2e696f00000c407065706f6f7370696e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b173257b17c32ecd724b7e940995b11d1e65f91a3ce3362429f941dacb9ad3e278acce9325308213": "0x00000000000000000000000000000000000841727563616e75000000000000094041727563616e75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b181c04016578e69dcbc0885fe08b19fc1a3c71b5a62c5710b6da20a20b3730c58a52c51ac567e30": "0x040100000002000000000000000000000000000000000c57616c6c6574792e6f72670c57616c6c6574792e6f72671468747470733a2f2f77616c6c6574792e6f7267174077616c6c6574796f72673a6d61747269782e6f72671268656c6c6f4077616c6c6574792e6f726700000c4057616c6c6574794f7267000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b19b71d671b6baa2aad8e905d4c09ac501fc3f74833019107288077bdaa77291588b5e021330657c": "0x0400000000020000000000000000000000000000000010534d4152542d4b5553414d4120535400000015736d617274617034303640676d61696c2e636f6d000000001440736d61727461703a6d61747269782e6f726700", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b19c3eac0c4c1de9dcc1c3cc78ba39c3d7b416dd47da6dd8a5fde83f454a55157caa477b5fb0c734": "0x00000000000000000000000000000000000b44617277696e4475646500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b1a4415d3fe3b73f4cd5f7ee69df1d1fb53e664569fef68fcb2d7dfd9113107d6b108e5c27e2a725": "0x00000000000000000000000000000000000f506f2d4b7520547265617375727900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b1b49b2e110517e354722d3648065cb3c0ee5de9ef5d7161e707e317fc897b2b109b062520f0ed23": "0x00000000000000000000000000000000000a4952594e4120322e3000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b1ef8d6360daf3d016f1f5077a316bcc580964e83ce2af8c24574233aa13883fd4c9e37425fe5671": "0x000000000000000000000000000000000010524d524b2041756374696f6e656572001168747470733a2f2f726d726b2e6170700011636f6e7461637440726d726b2e61707000000940526d726b417070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b1f5b788e8cb3020222f4af632639b2a6c24dfc4532b82a49c4d1010cb324bc98c8223ee2003cb6c": "0x00000000000000000000000000000000000e3120666f7220746865204b75730000000000000f405468654b7573616d617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b1f8cc3f226516048828d861f59282edb359070315c4b6e20be9ddd0ef58de47512c3d98b628c72b": "0x00000000000000000000000000000000000d4c6974746c654f6e6770696e0000000000000b40636f72746578726164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b21612d15cfbf7080ec594c4b9d16ea738e3c034498ea20655423f3861fd2df568ae379751cca262": "0x040000000002000000000000000000000000000000000d636c6f75647374616b696e67000013406d6f6761616c3a6d61747269782e6f726713686940636c6f75647374616b696e672e696f00000f40636c6f75645f7374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2315ce9bb1e5e9af89ed17c957b4a6de1ee5f3a36f7eeff3b5e53aba13792e64e471ee8775b6b31": "0x000000000000000000000000000000000004496b7501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b243ac33f5105fa6c01379a41a162af5a91e480a73369c4dd773a1ad16759a44cd3bb6935cd67e3e": "0x040100000002000000000000000000000000000000000b4b7573616d61204d4841000000196d686163727970746f4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b246a1c9081ca716a86d962e9922cd2213f9ea746767e3513957f86a335d940c8529d8357c106413": "0x040100000002000000000000000000000000000000000c5a4b5620436f756e63696c001868747470733a2f2f7a6b76616c696461746f722e636f6d001577696c6c407a6b76616c696461746f722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b25006accff8cd9d064ee3e94e269dfcf8d09d4e0980bb3123ca16dc734304128e328bb5a40f575f": "0x0000000000000000000000000000000000074d6179776169000000156d61797761692e6b736d40676d61696c2e636f6d00000c406d61797761695f6b736d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b257cc47df162822949b344d8706a170108f20aa5457fb62d19ac4d1edd7bb450b07f6790d16283d": "0x000000000000000000000000000000000007446573796e63074d616e75656c00000000000c405f4d616e75656c5f4c5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b260711c449324e13e1a3571a435d9e2de0a5336428458e38e0e0c84179450ebe4466b5db8efea76": "0x040000000002000000000000000000000000000000001949204c6f76652043726970746f202d204375726163696f6e0000001e616c62657274706f6c6b61646f74737061696e40676d61696c2e636f6d00000f40495f4c6f76655f43726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2850a82780da820548a3bc51f5f2ff006d0dd63d17248752bd6b46800314a689f69ef9f3570937d": "0x04040000000100902f50090000000000000000000000000000000000000000000000000000000a4d6967617373657473174d6173736920496e766573746d656e742047726f75700016406d69676173736574733a6d61747269782e6f726713616c6578406d69676173736574732e636f6d00000c40416c65785f4d61737369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2a0c16700350d52421185b141843818f93549a95880537b331573bad5cddc5b42856740ef3d2546": "0x0000000000000000000000000000000000085a7a2e2e5a454e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2a2c140593529fde6d8480e3a48bbdf79da217e7e017b06513f25276f3474773d5cac5ccd7eb96a": "0x0000000000000000000000000000000000104c6f76656c792043617472696e6173000000196c6f76656c7963617472696e617340676d61696c2e636f6d0000104043617472696e61734c6f76656c79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2aa0fcea34ca1baca3fe10047d713cd9fab0a5e42e48ca47378781652f40f19edc6cd1fbe815e60": "0x000000000000000000000000000000000012636170656c696e686f732d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2ac9fe1e9a7f5470ec778d2cc791b2d30c6d1986418f864b5c5f9032b52c59083e48f77d8618001": "0x00000000000000000000000000000000000879646473626c6c0879646473626c6c1468747470733a2f2f79646473626c6c2e6f7267001f79646473626c6c5f7374616b696e674070726f746f6e6d61696c2e636f6d00000e4079646473626c6c5f4e504f53000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2ccbd867d990e4d2c17be94b5327001650a4bb5cea4a3673c99c9c55b1ca911ab72703b50d8a742": "0x000000000000000000000000000000000012446f744b7520506170657257616c6c657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2e76be759cb39c0f6a250b388d7fb1233e530d1d2a904ecc28ddd85d0c642e2012f9163cd496c65": "0x0000000000000000000000000000000000084167656e74313301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2e868baf7804149e881c372e5f6f2b82da4e8a08dfb2a2b463a02ee2228f4c3abb5515ca6a7ff1c": "0x00000000000000000000000000000000000b5468652042726f6b657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2f651117e3fd34c84bda1949a2b78bfc3b12dcc8f2c8e8822912efe0c693a23effaf7f3b54e9a5c": "0x040000000002000000000000000000000000000000000b4279746520766973746100000019636172646f6e616a6f636162656440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b2f76aa3ff10a37e84fc49ce30071ea611731838cc7736113c1ec68fbc47119be8a0805066df9b2b": "0x04010000000200000000000000000000000000000000134475646f3530207c20506172615370656c6c0d447573616e204d6f726861631d68747470733a2f2f6769746875622e636f6d2f706172617370656c6c00166475646f2e6d6f7268616340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3074442a3a8a9ae98e9edd65f5caf8136db93b2f8213f4f91637ee4facff286fd491f904d691f75": "0x04040000000100902f5009000000000000000000000000000000000000000000000000000000086d657472696b610d4d657472696b6120496e632e1768747470733a2f2f7777772e6d657472696b612e636f0010696e666f406d657472696b612e636f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b30a0d7012b77142a86620314a174486a9938856e3b939de3bcd73458780f542388be0cd66379e28": "0x04010000000200000000000000000000000000000000124b52414e412e5620f09f9a8020f09f8c9900001b406b72616e615f76656e74757265733a6d61747269782e6f726717737570706f7274406b72616e612e76656e7475726573000010406b72616e615f76656e7475726573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b341499a31d863421ebbb4642a0056d17938932a9c46aec001297bc51e0b4a9dc2a1eb730a9fe521": "0x00000000000000000000000000000000000101010117353275316a79737437327969406f706179712e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b342eacf1a7bb7924440fa58f447b221d6353497312ea0c1596f7d688b84fd0f55e68ed89c3f1827": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b34bc4a4815f0a13cde66d4751e5ba025658b0f605dddb25a3ed08c9dd54e597304ba7a139706e00": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000c5375625374616b65e29ca8094b796c65204c65650015406b796c65796f6f6e3a6d61747269782e6f7267116c6b796f6f6e40676d61696c2e636f6d000000000e4b796c65596f6f6e233339313200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b34d53e3735a0db2c0c2bbf240b3e8306ffe68dde3373cd1446bf162f8a09e2f259391f2764d0d39": "0x000000000000000000000000000000000015444543454e5452414c495a454420656e7469747900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b357e4ead78873ac2aa53f55efa82a9820f3c2569d4e52dc467475a1a11cfc9861ce5440316edb7a": "0x040000000002000000000000000000000000000000001056656761735f6c6966655f6d61696e001668747470733a2f2f76656761736c6966652e696f2f1440636372697330323a6d61747269782e6f72671876656761736c6966656d61696e40676d61696c2e636f6d0000094063637269736c76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3581561695f63fabce0e8afbf04533cc92ee13d29374cd930e1b65505e2b5d9d3ea672bb4512c1d": "0x00000000000000000000000000000000000a486920496d20426f62104a656c6c65206465205a77617274650000146a64657a776172746540676d61696c2e636f6d00000c404869496d426f6244434c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b35c78d2f5f8365e32df05004fe9cc14f3b60a5afc3533aaa519399dc75d5b65d338f3f497ffe156": "0x08000000000100902f50090000000000000000000000040000000100902f50090000000000000000000000000000000000000000000000000000000653796e746800000015796173696e2e73696c4079616e6465782e636f6d00000b4062757977696e726172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b35dce1f552fdc17f6e6c46211d81310a08c8b683a6cca98743ad98bd21447687b9f55aebaa9881c": "0x00000000000000000000000000000000000e53706972616c20536f757263650000001a73706972616c736f7572636531303840676d61696c2e636f6d00000e4053706972616c536f75726365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3873b7b002e1c99ee60b67ca3f293af1531a28c25fba9f970bcf4bdcf77181a4a707454d252ee47": "0x0000000000000000000000000000000000076d6c6962747900137777772e6d61726b6f7a7562616b2e636f6d0012746f5f7a7540686f746d61696c2e636f6d00001c68747470733a2f2f747769747465722e636f6d2f406d6c69627479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b38b581ee35eb27176d688692159d622d85ab2deed48eafc143c9678d34bc8e6b080f7676187f105": "0x0000000000000000000000000000000000084e594d45545641000015406e796d657476613a2e6d61747269782e6f726700000009406e796d65747661000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3a116ce56e09a4ad6166cf88da98fb2caa21af4f23c89b489c65faf585fb0015f74bbaafca8ff01": "0x00000000000000000000000000000000000b7374616b65617765656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3bbe235e317bb0ec8205518d8e268b0ff306b684cda2b22bb68c4ecbeea54f377fb9d1481699b3e": "0x00000000000000000000000000000000000666722e6f6d001a7777772e696e7374616772616d2e636f6d2f6e6f6e656d7963000f6d79636f6c40696e626f782e6c7600000f404d79636f6c4e65706574726f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3f32eef5a4f87c32658b40ec2b02f94d22dc082219558da0be0a3a902a9e33445a81fe75fd41e43": "0x00000000000000000000000000000000001647656d2048756e746572207c20524d524b204f2e47074b696572616e00000000000d40646567656e646f74636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b3f50e5d25996acc8c6c261024db524af0eb5c2f6a913875a2b1be99ae03f2e7ae461f1a62201648": "0x040100000002000000000000000000000000000000001053706865726520f09f87a6f09f87ba11454f53706865726520507479204c74641868747470733a2f2f7777772e656f7370686572652e696f1540726f7373636f39393a6d61747269782e6f726711726f737340656f7370686572652e696f00000d40656f7370686572655f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b40191c2f127f31a083c4c20b076d878baa0815fcfeb5f93a60d9ca7861413d6295ceced417ab876": "0x00000000000000000000000000000000000d4e69676854686f75676874730000001c6e6967687474686f75676874732e6e667440676d61696c2e636f6d000010404e6967687474686f75676874734e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b40757a983c744376e2a534e0403f363633ed63219a73fb31ba077f03fcc1a4818ade82dd77f9077": "0x00000000000000000000000000000000000d6e696b6b695f73756e73657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b40975722af3500702088d2b822148eedc93dc55bd7b4e890a44b783233aa936e9ff714df1fb2351": "0x000000000000000000000000000000000007576574657a32001568747470733a2f2f7777772e776574657a2e696f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4113e7993545da1482bd6f002eaa6a7affb7e570fbff9878771a213873c31dc6f5c20d15c10ce64": "0x00000000000000000000000000000000000c5577652043657272726f6e0016687474703a2f2f757765636572726f6e2e636f6d2f0014757765636572726f6e40676d61696c2e636f6d000007407577656365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b415242948e48c4af65b2541075f4ab6dd22df200f9a5d19a3c65ee8e16f10a04d390a33f9550c7e": "0x00000000000000000000000000000000000742726f736b6901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b42bd9796193505f78f29bdb93bce99ebfaf2d05f45e3b0cc5e20cc3655b00c7a87efd0714b6b221": "0x00000000000000000000000000000000000a677265657a626c6f67000d677265657a626c6f672e7275001361646d696e40677265657a626c6f672e727500000b40677265657a626c6f67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b444a082a34087094c1dbf673aeb1c17f8f51c2fdbeef84d02a33a8ed3f558ccd48b744a3a7dad7c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b448e5a7e01085b6d6f077ab8fa173ff524e3b4a8f7c4216cdc06bc76c3b620547a929b5ec6ea834": "0x00000000000000000000000000000000000c477265676720466972737400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b455b694dad128e9722c9b4173ba6950b862740bf60abb3b081012e3a5bed9e7ec139666f0690f1c": "0x00000000000000000000000000000000000f4d65746176657273654368696c64000000196d65746176657273656368696c6440676d61696c2e636f6d000010404d65746176657273654368696c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b46f79823607ed8672ded8001e89fb9e5f2e7a9eb1913ab57211a7efc262a58b68c0af4db193f05c": "0x000000000000000000000000000000000012696c696120524d524b2047616c6c6572790000000e696c696140726d726b2e61707000000b40696c69615f6f6e6963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4736827e2622569824651190f1d20237fea2d5953bb53ec59df25d581e54f291d6978c9a8017741": "0x040000000002000000000000000000000000000000000d536d6172742043686f69636500000019736d61727476616c696461746f724070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4763e158852db7edea87703a49b3e2cd535dbb0187c3dc240dc585cedc7215d31b6f5b5e6be1309": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b47781cbd1ef364b044921f1a8a44f37ee55978961047fbeecc19c2529c73d367847ef04dbdfb852": "0x000000000000000000000000000000000007427562626c330000000000000a40536562636c653339000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b48b1b8f79a7433f88b9f3a722747e8f637b2583963ea7f1215adc8c75c3957554fdf92fcbfa5034": "0x040000000002000000000000000000000000000000000858616c616d75730000144078616c616d75733a6d61747269782e6f7267136b7573616d614078616c616d75732e78797a000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4d902a5e3ceaacbe2c0be196404087dd756eb35190f731531a6e66ab6a157d9e8755a0b1ce8157b": "0x04000000000200000000000000000000000000000000093832344d616d62610000001b3832346d616d62616e657665726f757440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4dfa73f600178ff3a9e64ec8308c39b8ec28ac2e7bb6e6eba1ca2fb8a87dc446e0fa3b232f84648": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4e729082bc0effa0c691601793de060491dab143dfae19f5f6413d4ce4c363637e5ceacb2836a4e": "0x04000000000200000000000000000000000000000000064c65656d6f000000166c65656d6f407468656368616f7364616f2e636f6d000009404c65656d6f5844000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4f035960b0d010c102ecd1c98119bb49b5fdcdde4160e597892cb30aa1aa3a40dafe3717e59a74a": "0x040500000002000000000000000000000000000000000e4e494b48494c2052414e4a414e0e4e494b48494c2052414e4a414e0000156e696b6c61626838313140676d61696c2e636f6d0000086e696b6c616268000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b4f0c4c16f8fc06e34d5e51cae79df0f3ee7229078ab968d7f9948de296c0fa8b5d92d574f269506": "0x00000000000000000000000000000000000a41746c616e7469636100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b52e4d96f225ba523ed709144add542687b9827a767b3291f991d568f2cb27662f0ffd5f55c74945": "0x00000000000000000000000000000000001243616c69737468656e696373627261696e0753696d6f6e651d687474703a2f2f7777772e76756c63616e6f6669746e6573732e6974001b696e666f4063616c69737468656e696373627261696e2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5421b6506f7f790ac59122f8bc8c527a8efde87156403558ea66ca0ef049cf3fa4f671f98517d61": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b552fbf6f1a1b77a86c3585c906e4928f030b4735d375cee0410db104908788133281b53533b5633": "0x00000000000000000000000000000000000853616e6368657a0000001473616e63687365706840676d61696c2e636f6d00000b4073616e63687a657068000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b56cbcafeb6c89004cd9ac314578bf2f172acdadfb93f39a59794ac258b7de50c38814f4187a5d35": "0x00000000000000000000000000000000000d6265726e61746665727265730e4265726e617420466572726573010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b574900a55849d7c2c30c7923251b4c2b6ac0a13589e931912e35672c525d05a9ccb48bc19a7db4c": "0x00000000000000000000000000000000000a43727970746f5349440000001563727970746f6f73696440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b584e1a4194b9d21fea234d679d4dc45e5e2373fec6e40659bf0e6918ff73502cea99ee7e7e9f750": "0x0400000000020000000000000000000000000000000010726f616473776974686f7574656e640000001774617469616e612e6d6b686e40676d61696c2e636f6d0000000015726f616473776974686f7574656e64233331303000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5857832389789b78af348b187a2e94f7dfcacc1de5c71b55f6ab8a50e75f0ac1a15baeebfd92e03": "0x0400000000020000000000000000000000000000000010472720457870656374204368616f7300000015672e756e69743234383140676d61696c2e636f6d00000b4067756e697433313234000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b59303ef0c9246ef0e58776f7b5ac468803ca692cda97289cbc6412e2c8dd832f30d74bd480f7529": "0x00000000000000000000000000000000000e736c696d74726164792e4e46540e736c696d74726164792e4e4654000018736c696d74726164792e4e46544070726f746f6e2e6d6500000e40736c696d74726164794e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5bfb9c15abda4d344fd0dd3c86f7bac5e3c502d08bd06add439cd568af4ae1399ad617764c84349": "0x00000000000000000000000000000000001a446f7473616d61204368726973746d6173204368617269747900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5c8f247935e6ce99e0bb283b2d2522a090d71d9c8fb484c7966d3e28b21bc513419ef7f70d6a563": "0x040000000002000000000000000000000000000000000a4a41434b464c415348000016406a61636b666c3473683a6d61747269782e6f72671a6a61636b666c617368374070726f746f6e6d61696c2e636f6d00000d404a61636b666c6173685f56000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5cbc9967f19afa3e295650fdd71d7046633b1fafd0881a3207719c573f17725fccddf854a8b5628": "0x040000000002000000000000000000000000000000000744617276696e0000184064617276696e30303532343a6d61747269782e6f72671664617276696e323238313640676d61696c2e636f6d0000104064616e7961706f7a6e79616b6f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5d2b4bc4d7b8aae7673bd5e6320b489eeefbfb7fc372b5aafc3955acdab0592bd1a5dd63b581376": "0x00000000000000000000000000000000000641544c303700000016646f6c61706f746f6b616e40676d61696c2e636f6d00000d40646f6c61706f746f6b616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b5dece0984444d31a0c077265fa8ebb05329c968fe13efc415460cc5c379fb392a652ac07c9c2f7d": "0x04000000000200000000000000000000000000000000125a6574657469632056616c696461746f7200001d407a65746574696376616c696461746f723a6d61747269782e6f72671e6f70657261746f72407a65746574696376616c696461746f722e636f6d000010405a6574696356616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b60b504a11ae006d8a26b6e4d6934f03e3f094197206bf224c8e863582b77c794141eef1719b2f60": "0x0000000000000000000000000000000000084d6f6f6e4d616e0101010100000b406d6f6f6e6d616e3831000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b61c69cf9ed79934d275000318be3386cdc343eb0d5dec56f65b8954a6946576b773e6eebc27e169": "0x000000000000000000000000000000000016425241204355454e5441204445205052554542415300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b62acaa32f7e218efcc5b90bc1891b7d905423f7a00ffb4e8f3d59aa97491b5a1d45b82548639936": "0x040000000002000000000000000000000000000000000a547574694672757469000000156b7573616d614074656c7574696f6e732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b62b777d8f1d409cc2533fecb62aa788edf60c15825bc7ecdb4516096007dd24b8a858d5c4434920": "0x0000000000000000000000000000000000054641444500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b63533e1e147f27d823265fcc4b6ca5e77e4fdeb4c6ff019564e3afa70a44edc1cbeb13a175dc365": "0x0000000000000000000000000000000000125374616d7020466f7220556b7261696e65125374616d7020466f7220556b7261696e65000000000011405374616d70466f72556b7261696e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b643ba1f89b73794ea3fb9aa4efc85db2a51959b1654caeb11576dededff098bf4692440e75cbf2b": "0x00000000000000000000000000000000000d43726970746f6d6973686b611cd09cd0b8d185d0b0d0b8d0bb20d0a0d0b0d0bad0bed0b2d0b8d18700001763726970746f6d6973686b614079616e6465782e727500000e4063726970746f6d6973686b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b672def05cb0d96f4e35d916c13e4bc55676d21e94120d4e27e10e1c9aa9e0fae59434ea8856817f": "0x00000000000000000000000000000000000847696c73616d610101010100000e406b736d767374686577726c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b67386b3a2bca62fa6805c6dc7757cea227e11839257d4e24ad39520621e99e6016ee0e1907c3315": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000034d430c4d61726b204372696e63650000156d61726b6372696e636540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b67f107771c3b26f78daf5556df89f21e14e2e07a132f523aba6a03c21792d14f7d41a5192c53453": "0x000000000000000000000000000000000019437265657079467269656e646c79436f6c6c656374697665001c68747470733a2f2f637265657079667269656e646c792e636f6d2f001f637265657079667269656e646c79636f6c6c65637469766540676d61696c000010404372656570794f726967696e616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b69333f8c0d86b1248c2f61e58783887d3652c07bc6bcddffa6373246c2f2b5270e7d5d3b57af315": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000105a6569746765697374204d696e65720d5a65697467656973742e706d1668747470733a2f2f7a65697467656973742e706d2f00106869407a65697467656973742e706d00000d405a6569746765697374504d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b69339fdfcab0d9f1cbf2d072567bdfeb00359e9d318e7b425a65449eb94b1a8f5ca0c28a9513878": "0x00000000000000000000000000000000000659616d6e650000000000000c406572615f6974616c6961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b69e21ddf4af61a05a89c086659b0ae940285ac34a75b3d1e846350f647cd7ac1236377fcd9d4405": "0x00000000000000000000000000000000000c496f616e5f54656d6e7565054976616e00001875736d766964656f363432324069636c6f75642e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b69ffb015d88545c0470d52d80c8f777e2a326e028444cedc0f910af3db5e49ca84751736d086f4a": "0x0000000000000000000000000000000000094c656e6f63686b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6a30b89e64a46012419b405a61cdeb929bcc1883a7368b2fba867bd78ff4886800ab56b273ccb3f": "0x00000000000000000000000000000000000452757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6c8b7052e61ea994437c8a23f1c5d221ddaaee441be0a9f38c638300e2805018abb4e72f7de753e": "0x00000000000000000000000000000000000b5073796368697465637401186c696e6b74722e65652f50737963686974656374417274010100000d40707379636869746563745f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6cfd687de7a23b4d60cf655685824e9966b0a10c01dc8b17b37e24944fdd760e4dd73ff1dd4ac14": "0x040000000002000000000000000000000000000000000e416c74204f72646572204361700000001d616c742e6f726465722e6361704070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6d97ff4578c0fe536fdcc8b78421a34a864a6a100bd9426c9f154381739a74f617b7f5988dced32": "0x0000000000000000000000000000000000114b6f6461446f745f7374657761726473001468747470733a2f2f6b6f6461646f742e78797a0000000009404b6f6461446f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6ecd013f449a75f58f2f7dd26682082ccd78611deeeffb89b38bfe97fe95be7e2047cd8e346ad1d": "0x0401000000020000000000000000000000000000000005474465650c47656f726765732044696200174067656f726765736469623a6d61747269782e6f72671667656f726765732e64696240676d61696c2e636f6d00000d4067656f726765735f646962000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b6f81cd81eee83ee72559667d3ccc1f96dded8d17e6299c5ff111ae37d9aba73bc7e6cbb53e6dc0d": "0x0000000000000000000000000000000000105468652048756d616e2042697264730000000000000f4054686548756d616e4269726473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b70e7e870eb10773f4e890b0badca21d04941659525012545053c6fda2c75381553fb91394b8d92a": "0x000000000000000000000000000000000013466169746820416e6420496e647573747279011d68747470733a2f2f6661697468616e64696e6475737472792e636f6d01206661697468616e64696e6475737472794070726f746f6e6d61696c2e636f6d0000104066616974685f696e647573747279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b718fb63dc5e0eca26b4ebe12602aeb02aa9d74a361a687fda2155814b680edeeb26f5159cdce741": "0x00000000000000000000000000000000000d4a415649544f4152524f42410000000000000e406a617669746f6172726f6261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b71a89138784643960235425858d04422d3183b91e97c522d39b532a547065d395532b60542b752f": "0x04000000000200000000000000000000000000000000096b6f6b6f72696e390000001b6e696b6974612e642e736f626f6c657640676d61696c2e636f6d00000a404c61676172743073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b727995258469c869c9db3e7b4aa077d5df26c65a2f98f8fedc50f8cc445cd7cfc26a96ce57b9654": "0x0000000000000000000000000000000000047373730473737300000c737373407373732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7461dfb8eafd0dfeafe7afd0a43dbdf3ed4d2691aa15907978fe457ad52bc326be51cfa098dd865": "0x040100000002000000000000000000000000000000000e6d617274696e2e6a656e73656e164d617274696e204cc3b873657468204a656e73656e0020406d617274696e6c6f65736574686a656e73656e3a6d61747269782e6f72671e6d617274696e6c6f65736574686a656e73656e40676d61696c2e636f6d000010406d617274696e5f5f6a656e73656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7636fb25a038da49c78b621dbae80aa6797a28f752059eef1abd763dabda3595560a0348ff82e39": "0x080000000002020000000100000000000000000000000000000000000000000000000000000000000000000b5354414b452e5a4f4e4500000010696e666f407374616b652e7a6f6e65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b76acca59a92ef07ce072084c159fb3547381b718ac1660d14030e7bcbe9db68eef0f7c0e340f33b": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7792dfd8eea068b88b9e241d5bc525d51b2784a4545429311f373202a8fca5706ed6c49141b350a": "0x0000000000000000000000000000000000067265616c4d0000001369636f646f6a616b40676d61696c2e636f6d00000a404b614a6f446f4369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b787cc241627881d7edf6c4de505630a4dc222c9de78e78becb4bc08a72277ee786da979ed4d8075": "0x000000000000000000000000000000000006746569646500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b789289293d8c850dcf93493400b853ddb07cd0ddf190ac86817206c9ad23dfcd64a480384c8bc0d": "0x0000000000000000000000000000000000074d61726c657900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b78cbac72154fae87aa524afbdeb18aa240f0b09780fd634f24ef48d87e5f328cd7471766bfd4c7a": "0x00000000000000000000000000000000000979657668656e69790959657668656e697900001879657668656e6979333939393340676d61696c2e636f6d00000b406672756b7474616a6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b797ee954f7fdc00a0aa404a3a1178f1337564cf2a5a70db2819f832ba23c92346d6b74271928126": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000e5068616c61204e6574776f726b0e5068616c61204e6574776f726b1668747470733a2f2f7068616c612e6e6574776f726b0014776f726c64407068616c612e6e6574776f726b00000e405068616c614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7ad4b1d953b9c6d84fc160fbb01b3a8dfee1ec843cf2e3c60cf7062de3c0a7614eb8d79c58dc46b": "0x0000000000000000000000000000000000056d696e6800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7b8b1b5a75ce20d524cf67b5db0c0e6a04d9509f1e6c980623094ad9e870adbd0a7a1b85a11e345": "0x00000000000000000000000000000000000c546f7276616c6420536f6e08546f7276616c6401010100000d40546f7276616c645f536f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7bec5191a59492f82230d13be153b9db2876a9b26c9e35486c41aa8c987eb16bcc8909a481b4257": "0x0000000000000000000000000000000000057534696101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7e08c50407adb61c00f8f18bd12975ae69a9b145cde3835109e4dfe2a18d7da51e98e54b62d703b": "0x0000000000000000000000000000000000084372696d58656e000000136372696d78656e3240676d61696c2e636f6d00000d404372696d58656e5a65726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7e95879065eb42bfcef3034912f1b6b1bbff67d362083286698d80defff9ab1ea0279da0fd2d83d": "0x00000000000000000000000000000000000b5468652043697263757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7f3be7246e94277d6ff0e9daf6baadc9aedaafad3db973385df8124cb0e35cf2d183c1539ed4109": "0x0000000000000000000000000000000000114d6175726963696f5f446f7453616d6100000000000011404d6175726963696f446f7453616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b7ffd9218f5ca5750e0797db0e2ae604c97ba48e3f3490ed781718d28e6c6162fcef61dca4d51404": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b80c4ca47b74cc28b425b49b63e7422dc709b51218af8f981f7d4dbc7745fb2e3b91a64ff3d80570": "0x000000000000000000000000000000000009466f73666f726f73001b696e7374616772616d2e636f6d2f666f73666f726f732e6e6674001e616e647279757368612e66726f6c6f762e393340676d61696c2e636f6d00000d40466f73666f726f734e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8114461fdcaf8d8046b4467eec7e673d63c621a3e9cac72b515014c74f9046de1caf79ff798f23b": "0x00000000000000000000000000000000000c496e64696365735f4e465400000016696e64696365735f6e66744070726f746f6e2e6d6500000d40496e64696365735f4e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8131ca67ebf42dda6addc873dab36ed63418ecfcaf4e40f6ab30badeae2cae08c5b307d3527eb4d": "0x0000000000000000000000000000000000134b7573616d61204672616e2079204661637500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b81a60ef7174fcff4adaa68a6139ecce46e6f5fa0608f3c60d34787bd25d7a57f1a49e42c935c315": "0x080000000002040000000100902f50090000000000000000000000000000000000000000000000000000000c416c65785f4d6178616f6e000016407361736861313938333a6d61747269782e6f72671f616c6578616e6465722e61726b6869706f76383340676d61696c2e636f6d00000d405361736861313830383833000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b81b10d0eaa7b26976729e17ad31469debcb60f3ce3622f79143e442e77b58d6e2195d9ea998680d": "0x040200000002000000000000000000000000000000000b4d61746857616c6c65740b4d61746857616c6c65741b68747470733a2f2f7777772e6d61746877616c6c65742e6f7267001568656c6c6f406d61746877616c6c65742e6f726700000c404d61746857616c6c6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b825d933ae3512dfb6dd45ba18e564b4aa812a9974ce45e71d51355d2d93335d22f6804d782cf43b": "0x00000000000000000000000000000000001d597572694e6f6e6475616c207c20524d524b20636f6c6c6563746f720009726d726b2e61707000167975726970657475736b6f40676d61696c2e636f6d00000d405975726970657475736b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b82ca38b993a4d8b5a7aaed28c23b0b10d2fc6a0a914c93ce965749d67d7f657facb010255e4852e": "0x040000000002000000000000000000000000000000000a5374617475746f7279000000196d697368616b656c6d616e37373740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8a088107fc00e82440ca03d91b4a7a9ac7f74d416e1ed29899ae32c2ac81fd5380f8a07e3713812": "0x0000000000000000000000000000000000084e6168204e6168000000116e61686e616840676d61696c2e636f6d000008404e61684e6168000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8a497e0503c1d16bc063e9ffcd1f15193240f7ce33e9ae2faf17345ea06cc4781208e4a4585cd46": "0x00000000000000000000000000000000000e756e636c6520676f72696c6c6105616c657800000000000a4070616f6b34616c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8b5006d5797640e6e753aa0bf6a3699bf1820cd8cb87cd1fd7c88d0c3e9c194a5055bbf6d338047": "0x00000000000000000000000000000000000d53656372657420416c69656e0000001473637274616c69656e40676d61696c2e636f6d00000b4073637274616c69656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8dd952c3de3ccebca83919d5d59734897305b32ff1eeb190fa168b7a8f10d613a5fa9067c708f7f": "0x00000000000000000000000000000000000744616d69656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8dec3cd52567f7d50deac6bb330e0370fb0f6e25693717ed7c05ae1d43c22b93e9ec5814e318d25": "0x00000000000000000000000000000000000564616e6b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8e12a80176f0c830aff6865635ae11013a83835c019d44ec3f865145943f487ae82a8e7bed3a66b": "0x04020000000200000000000000000000000000000000114272756e6f207c20524d524b2e6170700e4272756e6f20c5a06b766f72631d6170702e737562736f6369616c2e6e6574776f726b2f406272756e6f154062697466616c6c733a6d61747269782e6f7267136272756e6f4062697466616c6c732e636f6d00000a4062697466616c6c73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b8ed6b693822d4a77825b33ec8baf2d437c19856a6ce74f09bbf49c284602a18ecc0683874dd596e": "0x0400000000020000000000000000000000000000000012736e66206b736d2076616c696461746f7210496e666f73656320436f6e73756c741c68747470733a2f2f696e666f7365632d636f6e73756c742e636f6d001d69687562616e6f7640696e666f7365632d636f6e73756c742e636f6d00000a40736e696666736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b902e56a5ec842fbc8018be75da4c5757d622874c1dd478950b27baff9b50ca4c0e7670c237f626d": "0x040500000002000000000000000000000000000000000a77336e3a657269636b0c457269636b2052616d6f7300001577336e657269636b40686f746d61696c2e636f6d00000a4077336e657269636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9206afde78e38223a154cb2e55ed80b9b671b240ccf20a8e2a47a7097a61f156eaebdc98fe4780a": "0x040000000002000000000000000000000000000000000a4d616964616e5f5541000016406d616964616e2e65763a6d61747269782e6f7267176d616964616e2e657668656e40676d61696c2e636f6d00000c4059657668656e69694d31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9467b909c56e93efc49c631023463a74ee7b3a3294cfc62479ed9879d7b96cbac4b31cc480bfd68": "0x0400000000020000000000000000000000000000000008494e5349474854000016407368696e79666f696c3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9541ad999d600439c2010321b6f64024b485ffcb9c2c6218bc6baae3b30ee2edce121033c4e443a": "0x0000000000000000000000000000000000074a617a7a75730d416e6472c3a920446962c3a9127777772e6b616d65616c6162732e636f6d0014616e647265406b616d65616c6162732e636f6d00000c40616e6472655f64696265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b96d7c19d50508c4cea875e1a4dc1d17e8f7a389467ce388a27f4e6bf47d48bee57490922ea64764": "0x00000000000000000000000000000000000e5361736169204b756461736169000000000000114053617361695f5f5f4b756461736169000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b96fec1148c50fd53277094fa10fb120ac35dc09a0b57ad3509699366dd95c36c79390832dd1d978": "0x0000000000000000000000000000000000094e61726973657469000000196368616e752e6e6172697365746940676d61696c2e636f6d00000f404368616e753436313836313331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9792ddb83a0fbf980a42994e6266629750cb091d1cd6abd99b9f8371d7ac1c9572fbff31a9fd108": "0x00000000000000000000000000000000000866756e6779737300167777772e6c696e6b74722e65652f66756e6779737300000000094066756e67797373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b982d49de1e3d631c6423f3a139fc55c4cea94f27c7472a1ff86c9d7a160b750425d1182bfd83858": "0x00000000000000000000000000000000000c546f6e694d6f6e74616e6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b982dbb2e3c6ee865ac0bc1423595a61eac2804e8007dd17c6106c9f3153210ea9a7646d486da513": "0x00000000000000000000000000000000000b43727970746f476f6c6600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9840b5e244be97a3c2ebd0507647e389d89069d87d98594c0390f15b774ad70d69a506cc0721262": "0x00000000000000000000000000000000000b43727970746f2e4c69750ae58898e4b89ce6988a1a68747470733a2f2f7777772e696d616e676f646f632e636f6d011364686c69752e616940676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b989abb8037b868632cd5ca83f4f70c0570b608c91253f4ec8bb7aef34d6ea23813268a08be1f50b": "0x00000000000000000000000000000000000544415a5a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9ba5adedd76a0a63443089409ef5b3fe6fe1e79bca1ed3f035b35af2353cf6f9036b598c852cd74": "0x00000000000000000000000000000000000f706f6c6b61206d6574616d61736b0000001161656b6d656e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9be7b84d6056f5f427dbf56380f49793c83aa5a8e7a4f577be76293593a99b3b3c21e47d3821e36": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9d502fce7c93459067e77e8ffec0eb4beddd71651aae4ca9f05dfe519e5a83745103c15abe7556c": "0x0000000000000000000000000000000000076b656e6c73740000001531336b656e7473756e6740676d61696c2e636f6d00000b4030785f6b656e6c7374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9ef95a6cf7ae500d20b07471e8891d2417c00839dab57c278bd59e855b8c0ce5e7d75bd48dcb303": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000006786e30306200001a40683474743072692d68347878303a6d61747269782e6f72670d6b7535346d3440706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9f6138c9463794508379206f81bebd18953ff826599e0b8c0bceedfc72a996c52e343647f0d625a": "0x040200000002000000000000000000000000000000000d47656e657369732d4e6f64650000134076306964756d3a6d61747269782e6f72671e6b7573616d612e67656e657369732e6e6f646540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9f65131235fe195ce5c65fecd7bb733ee636a381fa9dd916f8cca91e2e403c8aea2f7ed32b31d68": "0x00000000000000000000000000000000000c424c41434b4d4952524f5200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714b9fa90bddc30fe5cbe29ae471fd4b81a6efb3dc6bc7fe4b65b52d646e24373b4237613322099e63e": "0x0000000000000000000000000000000000065374616e6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba17b7a7c96751bad490a44a398ef9ddb3d9fc9159ee9211cad8b42ed24378fc8ec6a2051559ba4d": "0x0000000000000000000000000000000000096e616d656c65737300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba2e001c3fdf3cc590980036ef824bdf5e58efd3a0bcfd3b9ce9a6d08584a5aa4631f0fecdec287e": "0x00000000000000000000000000000000000c466f726573742047756d7000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba3272263a601b26705bed5a79303588fb60600fff425e0d0c1129332c341a9f28af16f70a0d0072": "0x00000000000000000000000000000000000c43657361722059616775650c43657361722059616775651668747470733a2f2f636573617279616775652e65730016656c667265736f6e65726f40676d61696c2e636f6d00000f4063657361727961677565617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba34277ae1163be29c81bfa3aff6c4db81aa876fd24384ff7147fe58fdecae448ac4c2591235042c": "0x00000000000000000000000000000000000c494e54454752414c5f31380f494c5941204b555a4e4554534f561e7777772e696e7374616772616d2e636f6d2f696e74656772616c5f31380012646a6e6176767940676d61696c2e636f6d00001040496e74656772616c50737963686f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba39954813b8c8e0c835ecd271a6b07d93931cdc3ed8f1501cb15130db011c1e1e19bd229bd0827d": "0x04000000000200000000000000000000000000000000136c616e6465726f73207c205374616b655570001668747470733a2f2f7374616b6575702e746563682f15406c616e6465726f733a6d61747269782e6f7267156c616e6465726f73756140676d61696c2e636f6d00000d406c616e6465726f7375615f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba4212be20da972e4601d5e1601ee14b4ab46a8db6841f6165e7af0a05f91dcf5625c56b88294e51": "0x00000000000000000000000000000000000753617676615412536176766174697920496c79756b68696e0000187a656c6761646973657865313340676d61696c2e636f6d00000a40695f536176766154000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba4a9572710e11eae4b3182c87d1d282b76398757c96af32377066b3941fa21a038885dbffeb027e": "0x000000000000000000000000000000000013524d524b2050756e6b732053657276696365001768747470733a2f2f63616e6172796e6573742e696f2f001652656d61726b50756e6b7340676d61696c2e636f6d00000d4052656d61726b50756e6b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba57612f37ff87d8c0f6272125c7aa7259ab82cafc9e7f170102cc50818299a90a5807debfdb0957": "0x0400000000020000000000000000000000000000000009676c6562616e797900001840676c6562616e79797979793a6d61747269782e6f726716676c656270656e6b696e3840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba594f7276ff200c4e531ab22f712634089201978511b49aa987322314dcd8f16fa241f0055e3737": "0x04000000000200000000000000000000000000000000094172696e676f74790000001674307468656d6f306f6e6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba5e9cf778fa9a309ee26710c447115a1467aa6cddcb5b11a450522fe50f8c328ad7018ca3ca5109": "0x040000000002000000000000000000000000000000000a57494e2d5354414b450000001677696e3737377374616b6540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba67fb7fc8a0aa49a6915d6fb30cd30367f23194c68842a6018f565c773ea0c544eb2a62597b1b34": "0x040300000002000000000000000000000000000000000b4c696562692054656368184c6965626920546563686e6f6c6f67696573204c74642e1268747470733a2f2f6c696562692e636f6d001068656c6c6f406c696562692e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba6839973e6e9ad1e2a0a933d2b1e2dfd0c06baf42557bf4aa2ad84866859e6c869733d6baadf152": "0x040400000002000000000000000000000000000000000c637279707445676f642d31000000147761796e6f3733333740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba91bba06b9f9bc520214ae0372ce9446bff0c4b6c1d56b8d5f8bedd43e563d12dd888e910a67069": "0x000000000000000000000000000000000011f09d9488f09d94a9f09d94a6f09d94a405456c696110656c69612d6f7273696e692e636f6d0018656c69612e6f7273696e6940686f746d61696c2e636f6d00000a40656c69675f5f5f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ba9c47cbe1e3127fc6f159cc01916d03e79dd23ddb4f32bc3505f47f99548b36c8dd85cb3d703f17": "0x00000000000000000000000000000000000773686f6e79611253686f687261742042616773686979657600001673686f6e79616d63636f7940676d61696c2e636f6d0000104073686f6e79613036343734373836000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714baa78287fb8b42a5f89cdade39dc2b7f42cd668be4a3aabfa432524f9732ec2b38362ad8b6b6d17e": "0x00000000000000000000000000000000000f5468655265616c4973696c64757200000000000010405468655265616c4973696c647572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bacc123aba961dfdac7c228c0c2f9f8bd69a79694a21c0aaa11fa0bdffb8a24f8a2b2c7c71dd4464": "0x000000000000000000000000000000000008616c657867676800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bad35515a8d5aa0ce26cc8ecc7230bf0579be3d530cfcd6cfe8e18f560a20bb651dcd4bc5877c442": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f353100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bad85d54508d6840b433c85404bf9625fccfe9f33ea14dc941c5f2d33a2ee131b462526ed834365a": "0x00000000000000000000000000000000000c546174617461205465616d0c546174617461205465616d000013736179656e34696b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714badc22310930427ba763de880dfe6c4bbdad18fab60e27002f648c221df5248b7d44a575b4bc7342": "0x04000000000200000000000000000000000000000000054d6f626200001240316d6f62623a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714badd0717f1d37bea9a351f499b0c0ad66910f50ad9b28097a671da936b170ac23440194c803b8c2f": "0x0000000000000000000000000000000000000000000000000d40766974796163727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714baf2344ffd48e8ba62b57bdeb1e972c6f82ddeac93c75c9068b57649792c34110443f6a5cab2757b": "0x000000000000000000000000000000000006646c73393306446f742d58000016646c7340646973706f7274656c65636f6d2e6e657400000840646c736d7173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714baf41e8958962423603c30a2fec5564ad9ab97b2545ea990e3c1e6ad80537b9f49ee5ea077c37a29": "0x00000000000000000000000000000000000f63616c69636f666c616d696e676f00000000000011406d65746170686f7269636472796674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb0178d1513af2c9c8aa860ecfe404cee1ae6ae1e175966ffc5d0ed9518febe66c949472d9ccea52": "0x00000000000000000000000000000000000954616c69736d616e0954616c69736d616e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb146d7c8d93ce7a7874637d61f8a35d5cc1f042c93a1eac375025b66d469df55822b40d374a146e": "0x00000000000000000000000000000000000f4c697a692050616c6b696e697a6900000000000010406c697a695f70616c6b696e697a69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb1a60ea00d6b485d26dde9e6d3cce0d69ae970d6d9ea7c3a5e39c197fc4360a063f68da22df3c30": "0x000000000000000000000000000000000008566f6c6174696c054e69636f000015766f6c6174696c64756240676d61696c2e636f6d00000d40766f6c6174696c64756273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb23b116b16ec5027ef5168fd3e20f6dd7063f3d7654fa986e326da23f6132acadddcd47c2fb7634": "0x00000000000000000000000000000000000b617065586368696d707a001c68747470733a2f2f7777772e617065786368696d707a2e636f6d2f0015746f75636840617065786368696d707a2e636f6d00000c40617065586368696d707a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb316e0c469f968b5064b971aae8c27d90e75935176851e03c3b30d7737a81b4ebaafae61e86e008": "0x0000000000000000000000000000000000064a756c69650d4a756c6965616e6e65204e672168747470733a2f2f696e73746167722e616d2f6a756c6965616e6e653139393400186a756c6965616e6e653032323040676d61696c2e636f6d00000d404e674a756c6965616e6e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb3c046d0a6fb474e0084f5bd539e9f109706deacc25d346a52b1c61870f5f47d80b65defb7c9174": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f33370f62696e616e63655f6b736d5f3337000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb439f2ecc149015560189524f9e8a5a319945ba02d9696b8e17068709af4f3a3b37961b21b73a25": "0x00000000000000000000000000000000000f4c7575752040204576726c6f6f74064c75636173107777772e6576726c6f6f742e636f6d00116c757575406576726c6f6f742e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb5235e6238a13f3f496e79339df9183c3498406c6a885d6b381e33eeca4fb217751cf02fcfe1d72": "0x00000000000000000000000000000000000f4a5755204368616f7320323032310a4a757374696e20577513687474703a2f2f4368616f73436f6e2e696f00166a757374696e406465666973756d6d69742e636f6d00000b406368616f735f636f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb5ac47891b1706c02182bd1df5c617cd764a92111372e138c8f2de893e2870e1ba6798b69629e65": "0x00000000000000000000000000000000000654616e6b610f54657469616e61204b6c796d616e00001874657469616e616b6c796d616e40676d61696c2e636f6d00000b407468655f74616e6b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb6fb2c1a1cf337b7ed3dd1132e1f216cb30c2440b46423faf32c6effd0a2d9a9f24e52f57af6677": "0x040000000002000000000000000000000000000000000b4c415552454e5454524b000000186c617572656e742e747572656b40676d61696c2e636f6d00000c406c617572656e7474726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb90b6ee5cde60ba10a769ca3066979c556735c449cffae412f7ba4bb7f8eb1377e0b3f11a8f144b": "0x000000000000000000000000000000000004416c7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bb98a2562e4cc62d54c768b91070d322e396886d9ba5fbb6d75ba6d04b244ba8efc1c318b3591b52": "0x00000000000000000000000000000000000e62616e6461692d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbb543598a54ca6b9c974e668dd5d28bd12df4e36aabde599fa1623ee8b97811dbfde761fe762857": "0x0000000000000000000000000000000000085361757261626800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbc7bd73b2748c6f96672955216c27e79001bf18f21b977f2765ef1d0f2aa2f037725ba051311537": "0x00000000000000000000000000000000000d535550455220504958454c530000000000000e405355504552504958454c5378000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbcb83d90d25faefbadef2fe7ed3061a98b743c923501b7e196735e1a8bd1f066b1c3c960511445a": "0x000000000000000000000000000000000016f09fa4b5f09f8fbbe2808de29982efb88ff09f90900000000000000d406d725f5f77686f676f6174000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbd9f3a4a489a29e46b99e4f0ae2bfa4a719980c7833c4fc1a6f78fd8b4ea4aef68a036e6ba4b845": "0x000000000000000000000000000000000007656d65656e610000000000000940656d65656e6134000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbdd44aa00ffeb9790174218ad9d5531fc97c3b347e073d347d157cc40a470ad89b75604b0d9dc33": "0x0401000000020000000000000000000000000000000012546f6d61737a2050616e7461205268656910546f6d61737a205761737a637a796b1568747470733a2f2f7761737a637a796b2e636f6d1b40746f6d61737a7761737a637a796b3a6d61747269782e6f726714746f6d61737a407761737a637a796b2e636f6d00001040746f6d61737a7761737a637a796b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbe6cdadc6b5f81166abfdc8c3f01b4913bb09c1690b3ad15179ad20fb3e1f46d90e0104ea90951b": "0x040100000002000000000000000000000000000000000b4e69636b20536d6974680f4e6963686f6c617320536d6974681768747470733a2f2f6e69636b736d6974682e78797a2f00196e69636b2e63616d2e736d69746840676d61696c2e636f6d00000e406e69636b63616d736d697468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbf2c08ccad2373618270c23416bc290f3e029234130076858ec2b13753249521efc90f74ae62656": "0x040100000002000000000000000000000000000000000a53696c7665726561751053796c7661696e20436f726d69657200164073696c7665726561753a6d61747269782e6f72671c73796c7661696e636f726d6965724063726970746578742e636f6d00000b4073696c766572656175000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bbfce08e9e5bda94e2cd3cc85125534b5ea71b50545fea6da949704fc53b8ad0fa6a6e53c1e8b60d": "0x000000000000000000000000000000000007544f544f544f000000107a6a6b32343030403136332e636f6d00000c407a686f756a69616b7569000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc013d27fd77c44a621062161709870a2adfa220222901a2eacfeecc3a4d57ec0ceb0892770f4d31": "0x040000000002000000000000000000000000000000000a4d6568616e696b6f7200000016706f6d69646f6572696b7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc11b42293c053bb8aaaccc15d1e83263b6f51805be7a175838e9039d93a4c510954d03b8928fc51": "0x000000000000000000000000000000000004616e740847756f204b616900000e6875616e666f4071712e636f6d000008406875616e666f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc2d8754336d8fa7da2b89ee8960496527b6374ec753a1f5fda3e39e9e9b03d9badfb4bccf6e8f56": "0x00000000000000000000000000000000000742696f4172740101011362696f617274383940676d61696c2e636f6d00000e4042696f4172744c6561677565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc39f04eeba5e074def7e734f3e6f486dab2052f0ec6f574424cfbabc1d9f8c707c831398bad520a": "0x000000000000000000000000000000000008416e74616c657300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc547c1424fb130ccc26f3f343300ea20b4ce386372382e3d33e9ece9a27e0a01fa995338c0f651d": "0x0000000000000000000000000000000000055155455300000000000011406369676172696c6c6f6f7074696d6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc668f7dfbaa59cb02d7a8a8876312537dcdef0ccc8d7aa11011b1e95d82e0d4be84f40b5e97537b": "0x00000000000000000000000000000000000864796e616d694b0101010100000c4064796e616d696b756e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc6b5bdca0cef0328e80f01c037bbec2db122fbd54406add4e7876dad507df9686a4602bf41cf664": "0x040000000002000000000000000000000000000000000c59657668656e5f56616c3200001a4079657668656e626173617261623a6d61747269782e6f72671a657667656e69792e6261736172616240676d61696c2e636f6d000011406768366d786a78384f437754776373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc737a0b2b1b692a444c69e29645f58dc986ea6c666c7d6fa7183d0e517d9bf72bdc4f642d38c163": "0x00000000000000000000000000000000000d426561726f667468656e657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc7dd41f6fa996306a36dac17180d46bcf920c75b4e77f8000639ff41f6e55f2232a7650002c2934": "0x00000000000000000000000000000000000d576f6e6465722057696c647300187777772e6a6572656d7962616b6572617274732e636f6d0020776f6e64657277696c6473406a6572656d7962616b6572617274732e636f6d00000a404a6572627a576565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc95df3416acfce29ec982d60f3779d8f0043933ee6d1b2a4346df17d07e44a22a2cd91a31076352": "0x04000000000200000000000000000000000000000000076f726469616e001a68747470733a2f2f6769746875622e636f6d2f6f726469616e0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc9c5c7658dc2a36b45071647184e1df1afe1d9165a5762fb9b986c4041f744c95c15fbd55359951": "0x0000000000000000000000000000000000104d72204b7573616d612f5041424c4f0e537562737472616e617574732011737562737472616e617574732e636f6d00146a756e65736e74776b40676d61696c2e636f6d00000a406d726b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bc9fa9104384658136e4b176f4f8c8e93d1f038c4ad53d6ce6308764888af81d0b2acc9903f59a3d": "0x000000000000000000000000000000000010756e6a6f626265645f63616e61727901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bca25b49658f3abbc422e2ea493a1dcbb08fe47a38b7a06ff11372588ff78f041e2dec92932a274e": "0x00000000000000000000000000000000000a4a6f73616e6b4e4654001e68747470733a2f2f747769747465722e636f6d2f5468654a6f73616e6b00196a6f73616e6b4e46544070726f746f6e6d61696c2e636f6d00000b405468654a6f73616e6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bca4e93e46a1ee7a83c75b56557a84fe8261cadc0c308577b0709cdc54311afc5ec8d348b939f589": "0x000000000000000000000000000000000010416c69616e7a612048697370616e6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bcc32e782ecc9fabd8cd80b17fc41772945cde33054bcf50ba34a036208b9799414c92a187742226": "0x00000000000000000000000000000000000e436f736d6963204a65737465720e54696d20566572686f6576656e177777772e636f736d69636a657374657233332e636f6d0016696e666f4074696d2d766572686f6576656e2e626500001040636f736d69636a65737465723333000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bcd1f1445ae81362c8dee77020353131d4765e808b2c6cc7b6210eb6fcd3124ae83425c4fc054b69": "0x0000000000000000000000000000000000074d696368616c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bcde3d13baf8df94629a1162629bfa1c1b9291bdb4cd489a90b996ae15af912e8eaa384967b23668": "0x00000000000000000000000000000000000b446f75626c652044656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bce3132e4ef55facd425daddf60b2545e07c695d32d6bea2b9343f1528052b4edd1a777e93058565": "0x040000000002000000000000000000000000000000000b416c7363616c61626c6500000017616c6973616261626c6572744070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bceadde40165af33fe5a9cca6c5a8bd14c35c961d2a673268d204c2c36d15ab86335ea7954a8e963": "0x00000000000000000000000000000000000e50756e6b205661756c7420233600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bcf5cae0679b87b9aa192026f9edadc2b37b96a189bb52a799bc6b81c38af03294269f4f1f40371a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bcfdd67ea673f1f2641768da63aab1ad01b2ffed1a44b41c4475f3efdcb74d1e45cf3c490db0c11b": "0x040500000002000000000000000000000000000000000b7863526f6d312e646f74077863526f6d310000167863526f6d314070726f746f6e6d61696c2e636f6d00000a40726f6d315f646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd003bec2e6f36549a303844f021a011c22d653fb6259b4b8fab1d68b0c0874b185583da201bdf28": "0x000000000000000000000000000000000008507368656b656b08507368656b656b00000000000940507368656b656b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd07137d6081d8b92430a1698a57e4e339ecb9de55ad5673044714661b246edb2c1ea5a2646d9c73": "0x00000000000000000000000000000000000a4d61696b306c5f303000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd136d88ba01ae124af9159027de5ea1662da355ea7cbe3fe413d6531e07aa239d1ba6d9a1c09b12": "0x000000000000000000000000000000000008526f62737465720000000000000a403030375f526f626a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd1575bcc84ab1311010f8f677bbac23220af0b0ac65736ebc00b02e974963a5d006d266bdaf955e": "0x0000000000000000000000000000000000074e756e7a696f00000017616e6e756e7a6961746f636f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd17f907497d7c56a0cb11fa6afcf3be8012015df4a96a7b2020cd7271718a05f8a51027af726971": "0x000000000000000000000000000000000009427275736f66657209427275736f6665721d68747470733a2f2f747769747465722e636f6d2f627275736f66657200216272756e6f736f61726573666572726569726139323940676d61696c2e636f6d00000a40627275736f666572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd2ecf6ad5d9dd9aee019d37459e8eed15e0f5009e508c41af67a4e7be45b790cd9e62d9033dfd5c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd3136476e89f2d1688a4b3d49b7fa3e1587f8a8e3b445c7c3e830d524a6dc0bfd89a0f8627a6f08": "0x00000000000000000000000000000000000b616e746f6e6169796c790101010100000c40616e746f6e6961796c79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd39bcb26e4bbeaf9e5d65b57e68b695519207678cf4e14f3311e3b37918551b2859fa20acf5d538": "0x00000000000000000000000000000000000f4a6173654d61746963546f73686900000000000010406175737369657061727479626f79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd3a85fb653543aea882853228a1b570c5461bca6cd0457e2c8fa58c6aa52aa78f29bd5ecaf3513c": "0x000000000000000000000000000000000004544a420654796c65720101166a62743432324070726f746f6e6d61696c2e636f6d00000b40746a616d6573313435000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd3e1f96cf2e126e7054e5eabbdb6217217110e775a6f6f0b90c7ae2ca9effeaa9364eebd4eb206e": "0x040000000002000000000000000000000000000000000b48657865722d6e6f6465000018407370656c6c6361737465723a6d61747269782e6f72671f7370656c6c6361737465722e6e6f64654070726f746f6e6d61696c2e6368000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd728b26f60d3178f0fe1b04915cf406ce80faca3c18fda01d62d2ce52181870c984fb91c3a7df17": "0x040000000002000000000000000000000000000000000b5361746f79616d612031001b68747470733a2f2f7777772e7361746f79616d612e746563682f00197361746f79616d612e7374616b6540676d61696c2e636f6d000010407361746f79616d615f7374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd73eac9321df2b4bcb330a49b5766dcd63fff92cf95243ec2a29c4131f19155724095e5cfd5197a": "0x08000000000100902f50090000000000000000000000040000000100902f50090000000000000000000000000000000000000000000000000000000d47726567207c2041737461720f477265676f7279204c756e6561752068747470733a2f2f706f6c6b6176657273652e636f6d2f40677265676f72790013677265674061737461722e6e6574776f726b00000f404c756e656175477265676f7279000a68656c6f233331393400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd7cb7fed15797d09eaf21efa0b5543ff7a8f857e47440732a45b5e8a5089741c02b56df13410944": "0x000000000000000000000000000000000018524d524b20537570706f7274207c2056656c696e6f766101010113636872697374696e6140726d726b2e617070000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bd922ee4590a662b5220aaa3db247e52267f6c127eb427c31e5a6a73cdcfda6b2c716f945527780b": "0x00000000000000000000000000000000002150656e64756c756d204b7573616d6120436f72706f726174652057616c6c65741950656e64756c756d20446576656c6f706d656e74204c74641b68747470733a2f2f70656e64756c756d636861696e2e6f72672f001c636f6d6d756e6974794070656e64756c756d636861696e2e6f72670000104070656e64756c756d5f636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdaa6fd826d3e849dac5c7f54060315d58706b0956b5ba06ee5418f9c6ef558a7d95446c29d0e73c": "0x00000000000000000000000000000000000b617065586368696d707a001d68747470733a2f2f6c696e6b74722e65652f617065586368696d707a0015746f75636840617065786368696d707a2e636f6d00000c40617065586368696d707a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdb707c454d386493ed4491f24c65d4af76d353ac2932457ddaf3d27df87ffa4445ea40f979b9c60": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdb8c60de2e112d532d982ef0b332719d3a292188fef7138daa785a5c1a3d3d55eff4cdc71eb5069": "0x04000000000200000000000000000000000000000000094c6f6e674e6f64650000001c6c6f6e676e6f646576616c696461746f7240676d61696c2e636f6d00000b406c6f6e675f6e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdd0aa5b808b0d34b437f703710d52aed228ae7f941f8e08b32edde56e683dcc94664c3dc8622e02": "0x0000000000000000000000000000000000114d65726b6c65426f74204d696e746572124d324d2045636f6e6f6d792c20496e632e1768747470733a2f2f6d65726b6c65626f742e636f6d2f000000000b404d65726b6c65423074000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdd53ac7ebda26846230b351838edf68965d65538b501241b45871b5e0c20414e8fbae73dfda2a34": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000009436f696e57696b690000154077696c6c6e6176693a6d61747269782e6f7267113139393230343639324071712e636f6d00000f40636f696e77696b697065646961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bded1c61bcf50ff15615825944703a7f9494aa2901e4bad051e2f06763f755a3b010c887be77fd73": "0x00000000000000000000000000000000000b4178616e746173616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bdff2bb6b49fe71dc0125eaddaf1645d52cad388414ee3d814aab298a97d670d1d5172d4f5b8db0c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be092d7e5aeb9a7802948b18cd5001e68a33499343bd8ed974fc8398bbfdc3dfafbc7c478544f67d": "0x0401000000020000000000000000000000000000000006696c67696f001468747470733a2f2f706f6f6c67696f2e636f6d1240696c67696f3a6d61747269782e6f726712696c67696f40706f6f6c67696f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be3183951dd1f1d5e626934768e68509f3b657372165e6f98fdefe615cc8e669d5bbe033a6478556": "0x040000000002000000000000000000000000000000000bf09f9491204b65697468000018406b656974683a6d61747269782e7061726974792e696f106b65697468407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be3990dcba28e51a80dea82a6a4704d208bd43d1ea1d5a0bd97a9d20c5237beb348be8c82f37d93c": "0x0000000000000000000000000000000000104d617274696e20f09f8cbbf09f8c9e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be3a70de3dc8981a02098b5f718885f0d6f0f18359a7d16b44c9229857934efe66daf4d9f0eb7a43": "0x04000000000200000000000000000000000000000000084e6f646561737900001540637261626265616e3a6d61747269782e6f72671577656e7a686968616f406269746f7069612e636e000009404e6f6465617379000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be41c254bc739ae910473e87fb3a40efd144767bd4a2b66c551947290d28eb81798dfcaa2981c134": "0x00000000000000000000000000000000000d4d657461204c696d697465640c4375616e205361757465720000156375616e73617574657240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be67a4a924a2f024ae7c2e1a07ea367f42d8a50cc1b05e67313b2d0961a176bc914ce5418093a816": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be6eb4fcd98b5e48225f2459239641fc50300041f8980fa044cb07705db61fefb340804172b1c25d": "0x040000000002000000000000000000000000000000000f43726f75746f6e4469676974616c00001540746f7861333333333a6d61747269782e6f72671763726f75746f6e6469676974616c40616f6c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be87f9c4b210b250122ff96f07bd9c9b3961c4387d71362315d05addda58f1dcce642888a643f930": "0x00000000000000000000000000000000000853435954414c4500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714be986efd0a14e39c8ecdc51d7c98b64a51f2c4c19e2be313af46a41bbb620432be7f2f78a27f7c1a": "0x00000000000000000000000000000000000a4f6d6567614d696b650a4d69636861656c20420000196f6d6567616d696b6540747269736b656c696f6e2e6f6e6500000d406f6d6567616d696b653834000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bea99ac32a4539bc724d262fd25c8cc975189c3ae4f0dee1ba2e17080cda69183412d0928b49db0f": "0x040100000002000000000000000000000000000000000b7375626c61622e6465760b7375626c61622e6465761368747470733a2f2f7375626c61622e64657600126f616b6c6579407375626c61622e64657600000b407375626c6162646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714beb64061aa9b85f752cf40bb293c3639c52e8d1102816a0eeb15adbdcb34985f4f555d83d6fd9f35": "0x00000000000000000000000000000000001f53414d4241207c20526f79616c20536f6369657479206f66204368616f730d576f6c6667616e672053616d147777772e776f6c6667616e6773616d2e636f6d00146e667440776f6c6667616e6773616d2e636f6d00000f40776f6c6667616e675f5f73616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bee578c453b0ec8a10dcba5c743f0ac5f458c84cae222de427205dbdb1ea5c38070be7a728d44109": "0x00000000000000000000000000000000000c5468652043757261746f7201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bef054a6e8d99eba983c5a0d1f1e697c1a0f9798bc25543603751b41102d41c3b0e23cbc6e3fdc0b": "0x0401000000020000000000000000000000000000000008566978656c6c6f0c566978656c6c6f204c4c431468747470733a2f2f766978656c6c6f2e636f6d1440766978656c6c6f3a6d61747269782e6f72671268656c6c6f40766978656c6c6f2e636f6d00000b403078566978656c6c6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bef3200eba174d218000262b138778788d2c01044e23dbb7b4159a60cc72b36455320866545ea72d": "0x00000000000000000000000000000000000d44616e656c694172746973741044616e616520476f6e7ac3a16c657a00001664616e65676f6e7a612e6340676d61696c2e636f6d00000e4044616e656c69417274697374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714befec0bbe28bc4156cf103d56cc23ec72abe93fa1bb8b2ce999da4c64cf87a6382fc6f743a176d71": "0x04000000000200000000000000000000000000000000055a756b61000015407a756b615f3131363a6d61747269782e6f7267127377343832363440676d61696c2e636f6d000007406f6b37693300097a756b615f31313600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf0b85bf56b1122f2644199cf370ae595ee0fcfe125cf1f57ccad32c435b62ba43ea09b7652aaa78": "0x00000000000000000000000000000000000f4b7573616d61204b696e67646f6d001f68747470733a2f2f7777772e6b7573616d616b696e67646f6d2e636f6d2f000000000d404b7573616d616b696e6773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf13eac6858519dcdccfd108cf2a01b8e6cf878849eabe75728f267ea10fd8f18b6fe92220c8991d": "0x00000000000000000000000000000000000e4c696c6c7920506f727363686500000000000011404c696c6c79506f7273636865417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf17a0437a59fce41c45953edf44501060286e3eb61e389d86d13e7c2a6e4acd6bd1df389d34f358": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf2341873b4d4cf676587217399584996f3d1f2135f8c76cd128e795fc5e04018e3f15be7aded120": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf284bae8cc1a1845687439c0a1ffe34131bc8f47408fd64663de30e4eb54aa128e578db2745c749": "0x00000000000000000000000000000000000962656e6c75656c6f0a42656e204c75656c6f000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf4f9995d06677041cf0dca0b7aa11a240e5706fcb3475f60a375814d69755c9362f65caeb55a867": "0x00000000000000000000000000000000000277000000000000034077000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf5e40a7dfc4431c8a99501bbf355e2b2f19a22c79915c2deefe1a3e19c957a9db910b7d3f6ff24e": "0x000000000000000000000000000000000008456c65786965720000000000000940656c6578696572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf6bd75b748928f06effd095a398639dc8af6f449a6362b40ee962e69700369eb9e530629bfa386a": "0x00000000000000000000000000000000000f4b7573616d61205a6f6d62696573000000186b7573616d617a6f6d6269657340676d61696c2e636f6d00000f404b7573616d615a6f6d62696573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf74188b125a3306308b59a947eeb792acf6de27fa47a92ad37d53a15a7b97cd25f11c25455ba253": "0x00000000000000000000000000000000000e4c6f63616c436f696e53776170001a68747470733a2f2f6c6f63616c636f696e737761702e636f6d00177465616d406c6f63616c636f696e737761702e636f6d000010404c6f63616c436f696e537761705f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf85c9682d95267f0459226895922ebcf36a4fd2441690ddeca7404cd4ee5403ebea4c9ef367fe4b": "0x0400000000020000000000000000000000000000000008437269735061700000000000000b40437269735f50617038000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf8e0379b44b6804dcf2917d37c64e3d60416e47b5185b4d6c3965ca531ecbe29e1d2cf759f5f871": "0x040000000002000000000000000000000000000000000f554e4956455253414c444f5430300000001d696e666f40756e6976657273616c646f742e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bf9ec12dc8498206bc43e27bc2e8f85dd0bd886f3512866f82132844654c78465fd3b23dc7988e0d": "0x04000000000200000000000000000000000000000000074b7269737479000000156d6172786f786f6c327540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfa9ffb31899babc08fabdcfdd509f6f46ae0d3d94774a5555f448378075d9d6e2818dabcfcfce4a": "0x00000000000000000000000000000000000744726f6f736b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfaa3c41adc4090b76b408e1da2f3e3aa9933dfc856970e1910172ca002f7c692aef2cd814a4d16b": "0x00000000000000000000000000000000000e49736874617220537072696e670000000000000e40497368746172537072696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfae967d3e6d06430263fbfa5728d893da31a94b7b23aea0fc23e87b2e24e12e08e372bfde42fb2a": "0x000000000000000000000000000000000007426c61696e6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfb6186ececfda792ef97696585f2074e73c1a7e50fd86be024eba3cf4472ab02e9e5e60658a9f0f": "0x0000000000000000000000000000000000096c6d61747a38323300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfd1adb8160d3d9cec8c97edfab0a07c37625d53be2075b8ea64a00ca71d80cffe94edb44d215e00": "0x040000000002000000000000000000000000000000000c6e6f6b6f67697269737276000018406e6f6b6f676972697372763a6d61747269782e6f7267176e6f6b6f676972692e73727640676d61696c2e636f6d00000d406e6f6b6f67697269737276000c6e6f6b6f6769726973727600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfd37fecc62ed30d50d3a21916778f488ad7fc8be11e29ced183651fa35e9a5a4148077e3dffb146": "0x0401000000020000000000000000000000000000000004535044001b68747470733a2f2f726f626f6e6f6d6963732e6e6574776f726b15407370645f616972613a6d61747269782e6f72671773706440726f626f6e6f6d6963732e6e6574776f726b00000d407370643537303638333935000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfd63dc631849c7f40a40af94843458d2a32dffda8c113143c4c263b689fb22feb2817d44b557447": "0x00000000000000000000000000000000000c476176696e20426972636800001340676176696e6e3a6d61747269782e6f72670000000d4045746865725f476176696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bfe419a5c9e5d3ad6c4e8b48b79ec203ce159cd966e441d6e96f1250639d1ce8e2cca50574a1cf20": "0x040000000002000000000000000000000000000000000b4a756d696e73746f636b000000156a756d696e73746f636b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bff2bb4618f007527cee2043a1c5ab3ca7b376a1038e0200b82436d83c6f12cee8a2838f3374511a": "0x00000000000000000000000000000000000d616e64726573616e656d69630e416e6472c3a973205065c3b161117777772e32316d62756c6c732e636f6d0017612e6c656f6e6172646f706d40676d61696c2e636f6d00000e40616e64726573616e656d6963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714bffb48c65264e596623a83df18a4035e3f753cf28bd99cfee9d86937a0249e64c0edfaaf774aad70": "0x00000000000000000000000000000000000a30784b727970746f6f00000000000011404b727970746f4d616e69614b343030000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0076111676aa5c932585bcfe3a06cc536501471159584b934d07923e03f69ec4e7101f6d21b9a42": "0x0000000000000000000000000000000000084b7573616d626100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c017c9db88e20ba7d6ea290b1d0c9db6b60e1ccf45cd46ccdfca05d0eefb211f8737138d5f23e81a": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c01ea55f307c73957ef55983821ee123bb7141da96e85024e537b7c3d4dabee51f6bcc458f2ce77f": "0x000000000000000000000000000000000003474d06502e204d2e000018616d706d5f43727970746f734069636c6f75642e636f6d00000e40616d706d5f43727970746f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c04a9c7d0caebe131693a51ef6a5e8d8d7f8254be6e1da86af31c6fadc8cb63c489d3676012a6d46": "0x000000000000000000000000000000000006445245414d0e447261676f6e20456d7069726500000000001040447265616d447261676f6e456d70000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c04ca87c3c9a9c0e54f7907932d3b6acc91644057bf2732683d772a7b69f8df49f91cadf50e0ca41": "0x00000000000000000000000000000000000e506f6c6b61646f7420426f73730000000000000e40506f6c6b61646f74426f7373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c07690bc374b92f796acfe70c04eae75f56d603fa55ea58adc1a5be6f7780f6bb8b55ca788ad670f": "0x00000000000000000000000000000000000c5375706572636f6c6f6e790c5375706572636f6c6f6e791868747470733a2f2f7375706572636f6c6f6e792e6e65740000000011407375706572636f6c6f6e795f6e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c07b13ed9c7bd5784a9bcc5ed3d67b713c73686690eeaa8d56d0e933b1767d04e6a78c5bcfb0b953": "0x00000000000000000000000000000000000656616c6c791256616c7961204e617274736973736f76611d68747470733a2f2f6c696e6b74722e65652f56616c79614e61727473001556616c796131353331324079616e6465782e727500000c4056616c79614e61727473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0a3a98b551ee046f623943323c10fca98730a4dcae0b6f710f51a9b574a415f4c84617389345024": "0x00000000000000000000000000000000000a5768697465776f6c660e4a6f686e2042616c6c6d656e7400001b7768697465776f6c6637354070726f746f6e6d61696c2e636f6d00000d407768697465776f6c663735000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0b698fe85dc7f07f46a2cda2040566d6299f92cdb1132a231dc2632ff84b711e3db8634c344f93e": "0x040000000002000000000000000000000000000000000d47696f726765416264616c610000001767696f726765616264616c6140676d61696c2e636f6d00000e40416264616c6147696f726765000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0c86ee622ccbd7b50cf2ac5c2184c5b56bcc4020ff5858a46411c63eafde5c0073033aa9183b008": "0x0000000000000000000000000000000000094d6172666f72696f000000136d6172666f72696f4070726f746f6e2e6d6500000c4030784d6172666f72696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0c97d65a24f61b1143b4dafb938b67c2305804cedd61580d28079cc89366c4d02754275188e8207": "0x000000000000000000000000000000000013506f6c6b61646f7420636f6d6d756e74697901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0dd630e2b48c6f1883235753d2d2fbdcde84d5bedf9d4e3049d3aa38eae44b6baf7f90dfbc27c77": "0x00000000000000000000000000000000000d616c656b736969627261766f001d7777772e696e7374616772616d2e636f6d2f627261766f2e70786c730014627261766f70786c7340676d61696c2e636f6d00000e40616c656b736969627261766f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0e60e80c24de0077c140ace22ed9c9542e5bb2a752621225ce07325c26d02a494883e860329921f": "0x000000000000000000000000000000000008446f7473616d610f5269636172646f2043616d706f7300001b3137446f7473616d6137314070726f746f6e6d61696c2e636f6d000011405269636172646f3138393538393533000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0e968a177335220aa220871834d1f214169691dfd97c70823d90d192b246378dc01a59daafffe0d": "0x00000000000000000000000000000000000c487970657273706865726500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0f5d760b3d480556c406cd98bab3d290bba03d428b468a9b6b5a4a53101cd11594fad41a27b2754": "0x00000000000000000000000000000000000e69636c6f6e794163636f756e7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0f7c7b14b34538fba5cba767a8f31682b274dbb330de35c26ad281d7ceab309649a99d7ea0f8b05": "0x000000000000000000000000000000000005416c616e05416c616e000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c0f837b7cd7e3836b02b8226fe805f72e05b5c6b634b076a01c30d1cce7f1ab7127e63d6e3eaa06d": "0x0000000000000000000000000000000000054c757575054c7575751d68747470733a2f2f6c696e6b74722e65652f6a7573745f6c75757575001a4a7573745f4c757575754070726f746f6e6d61696c2e636f6d00000c404a7573745f4c75757575000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c103bcc5de571eaad01b3c1368fe9f57cf7dcd732ce35249557f2ce8876a9d083f0921529afbe52b": "0x00000000000000000000000000000000000844696d6172696b01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1177e10764520f0286ed5b9c507942cbe163cd75a2cd6de711b44216438b6618c2b1a5af864a31e": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f360e62696e616e63655f6b736d5f36000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1182c59277d714b4697f390f0f6624792b81cc517134435760de5303fed079a7f3ada19c3622900": "0x0000000000000000000000000000000000084a6167754e465400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c11b1c3f82b75014e4d733aa6e16d24e220efa69687f6ff198317062ab5ee12a059d47b732c27624": "0x040100000002000000000000000000000000000000000a507572655374616b650e507572655374616b65204c74641b68747470733a2f2f7777772e707572657374616b652e636f6d2f0013696e666f40707572657374616b652e636f6d00000d40707572657374616b65636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c153bf084b7770907a60b5bda7a39f689d7e836cd6496066d3959e65ac56da32ced67bab4454d678": "0x0000000000000000000000000000000000044c656f114c656f6e6172646f2052617a6f7669630000156c656f6e6172646f40706f6c696d65632e6f726700000a406c72617a6f766963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1766eb50d30248b986cd47abb7ad417f9b127dc8c38b34fba72a604cd2643f74b0ecead90af9a57": "0x00000000000000000000000000000000001357696c6c69616d204c696d204b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c18ee488c392d992f888820459c387645732dc07dce5bb6884a13caf0c41dc1ee81734a74f19e07f": "0x040400000002000000000000000000000000000000000850415452414354001368747470733a2f2f706174726163742e696f16407975656c6970656e673a6d61747269782e6f72670e686940706174726163742e696f00000d40506174726163744c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1a57f5abdde93362461cf63ec5df1c71102f6122af9fca5fab21a9c7bedb84f21f2a07504d98213": "0x040000000002000000000000000000000000000000001e48756220556b7261696e6520506f6c6b61646f7420f09f9299f09f929b00002140706f6c6b61646f745f6875625f756b7261696e653a6d61747269782e6f72671d706f6c6b61646f74687562756b7261696e6540676d61696c2e636f6d00001140444f545f4875625f556b7261696e65001c68747470733a2f2f646973636f72642e67672f353743444568363600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1ce12824a5cf3c7b2bbd89d32024cfa3f782fd05b0e325cb9d364d419d85768bbce95395f124e18": "0x000000000000000000000000000000000006432d31303014436974697a656e204f6e652048756e6472656400001e636974697a656e2e6f6e652e68756e6472656440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1d7648a3e3194dab2bdb0d774986625498e0b5fce860c7d58103bdb6b7b348054d525fddc3f3e7f": "0x00000000000000000000000000000000000a506f6c6b61506f6f6c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1d9151efd144bc7c6e2ca836b28b68978aa39dc41d5b7ef3a7b8630a3e432d8ca99f24fd86cbd05": "0x040100000002000000000000000000000000000000000a64616d736b796674770000001c63727970746f64616d736b794070726f746f6e6d61696c2e636f6d00000b4064616d736b79303031000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1e288e289580287886286c58d67217bdd854832d5e9f1b218dec6a0ff7e0b7573147ca94a233a0a": "0x040100000002000000000000000000000000000000000c4269742e436f756e747279001468747470733a2f2f6269742e636f756e747279000f6869406269742e636f756e74727900000f40426974446f74436f756e747279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c1fb74b2482e1fa3be485a0806e6773e0f8df67b7a7849f2171fd0e42db790dfd9d9e923e79e6d30": "0x000000000000000000000000000000000015747269636b79206e6674206172742074657374730000000000000d40547269636b795f4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c240fbc12423680f764c70f6ae87fd18e901fbe3da02098ba42459d29bf26602ec68c229292f301f": "0x040100000002000000000000000000000000000000000b5374616b656454656368001968747470733a2f2f7777772e7374616b65642e746563682f001b7374616b65642e746563684070726f746f6e6d61696c2e636f6d00000c405374616b656454656368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c247e5052d61631f088a514be77fc6e8c07ca16c66eff21fabda2362183d9342b017b7f4e3abfa1b": "0x0400000000020000000000000000000000000000000008696c347231343100001440696c34723134313a6d61747269782e6f726712696c347231343140676d61696c2e636f6d00000940696c3472313431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c24a329489b706b1e402e6024bfb3168e669c83931a367668e2cb6721ae85d549caeefd9cc74523d": "0x0000000000000000000000000000000000084769674d696e64001468747470733a2f2f6769676d696e642e61707014406d6d61686572653a6d61747269782e6f72670000000a406769675f6d696e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c24ad04d4c11675896324cde80264d4b481bbfff59c179288380084d346630e3d69ae79a584ba27a": "0x0000000000000000000000000000000000067375736c6f000000195365726869792e7375736c6f40686f746d61696c2e636f6d00000d4053657267696a5375736c6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c24ccc1f4f0c01535860ef101dbbcbd69d9c3c0d43cdd6ac285ea2d81e5de77ea31c9b5f46345507": "0x00000000000000000000000000000000000d5468652053756220436c75620d5468652053756220436c756200001967616261676f6f6c676c6f62616c40676d61696c2e636f6d00000f40546865537562436c75624e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c2531fceab22368da26c51051a9031ebcc5ae2a4eb9a72e444a5bff59b995ce4612ed8cabe8a2a70": "0x0000000000000000000000000000000000144272616c65204b7573616d612057616c6c6574064272616c651368747470733a2f2f6272616c652e78797a2f0012737570706f7274406272616c652e78797a00000b406272616c655f78797a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c26b60c340f2850fe003e4deb7ba19046cc38a5b19fce737a9b85dbcffd02c7a9b5ac939c649bc3c": "0x040400000002000000000000000000000000000000000e4368656e5a6f6e6778696f6e67000013407a786368656e3a6d61747269782e6f726711637a78637a6640676d61696c2e636f6d00000f404368656e5a6f6e6778696f6e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c2d515788ab8e1a0e27efcd0fd4d153900de5a5eef0ff376e377856eda61b99e351d8b0feab02271": "0x00000000000000000000000000000000000850617a204c61620101011474686570617a6c616240676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c2d9f475a129afb3de35d75951081e7ba5a6bd03a14547079abd9ba3e02b86be08857cb2300fe370": "0x000000000000000000000000000000000008526f6d312e696f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c2fca83922e702d9fad031becd3e949c4168031dbf67cfd0425c23cc9e97602945557cfe94f9686c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c30921ca6904d9b0481d2289e340dbe924b2d24032e0382fa4385ee579617d900962044ef8f76d78": "0x000000000000000000000000000000000005574f4e4700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3125cbfe931ee052c08cfa5b2dbfcf6850a3b836596d82a9ed7d2d743b42aa5c69798b502b29b57": "0x04000000000200000000000000000000000000000000104e6175676874794e6f6465732e696f000016407472697072616d626f3a6d61747269782e6f726718737570706f7274406e6175676874796e6f6465732e696f00000e404e6175676874794e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3177ffd686ff73b887aa7b29cd25037b5adbc515ffe27ac96d457cd8af6bb2dcd486fd29e89c955": "0x00000000000000000000000000000000001454686520476f647a696c6c61204c656164657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3187f2193d5784124833c81b9862a86b8f6d9b7099661ec45acf14f1831acf5184dc477d5f1445b": "0x000000000000000000000000000000000007707369633474000012407073696334743a646174612e6861757300000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3288af44cc8896786018db371564be5c7f5c49e28d43d00c70d34cbf53f71705f1f670a3dedac5e": "0x0000000000000000000000000000000000184f6e2d72616d7020426f756e74792043757261746f727300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c32db95f6c40dffcec4b556151cf2da16df2febda18f31e50231881bc5d55a845958bfe87c59e12e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3307fa4d9163f3c203066b0a657bdbdbe9974c20a2644881f384f9b206c7c394054c0d411d7bc6e": "0x00000000000000000000000000000000001c526f746b69204b7573616d6120626f756e7479206163636f756e7415526f746b6920536f6c7574696f6e7320476d62481268747470733a2f2f726f746b692e636f6d000f696e666f40726f746b692e636f6d00000a40726f746b69617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c33e475fb0c3b46a9af751af01e61162cc3339e23de3d5387e209eb8ceddc992e4ceff620ccb837c": "0x0000000000000000000000000000000000064261726f6e0000000000000c4047656f7267334c6f7964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3427b260581a0d4dcd6bde04b554d3bc0cd72a5cf503ec854b4a44a4e5a9f8057dc2d0cbcaf5b41": "0x040000000002000000000000000000000000000000000977646d61737465720000154077646d61737465723a6d61747269782e6f7267136d6f6c7465732e6740676d61696c2e636f6d00000d404d414b53494d3738383736000b6d616b73696d3133343900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c347cff095b54034e6261adac5418d9d46cb1d02d640d2afb74d5d27945a2c28e176049a6d757d5b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c353eaa2aa4b36d7c48799cc5e6109c73e8502411177081cd1c77881a6ec2f61bd0d11df09c40804": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f330e62696e616e63655f6b736d5f33000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c35fa9be4d106de5521cb7c68dd8c9563fa2cdb0311f820f8aafae31da6007aa89730cde9f46db3a": "0x00000000000000000000000000000000000773746572796f0012687474703a2f2f73746572796f2e78797a000000000a4073746572796f3335000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3724f9765a6e28605dec8ffa7205cedfddf7d4a5d76b469d764a9833a3929b33c39a8479c3762ef": "0x080000000002050000000100000000000000000000000000000000000000000000000000000000000000000d44494e4f56414c20f09fa6960000144064696e6f76616c3a6d61747269782e6f72671261646d696e4064696e6f76616c2e746f70000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c38be37ff19e3a8a7617b9c6475f887ba801cee49b322a4d888224c8d0791bb0d5c999b6605e251a": "0x00000000000000000000000000000000000a73796e636c75622d310a53796e636c75622d31000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3903a41eb7b0ea04a1e5db2241a15c418162119c39fe2e9570abaa5b36c7225e4a5b306cc39c047": "0x000000000000000000000000000000000006576f6c664b000000000000114063727970746f6d796c6f75776f6c66000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3946172675052829aaca335cc3dce64d9ed58100cafbefb2bb2973985671676c7d645936a5d172b": "0x00000000000000000000000000000000000e54484520434f4c4c4543544f5201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c39daa94631294ae14ce4e09b999c54351c75b74d0bafdd17d86d98b6aab5176b9068e1be13e096f": "0x0401000000020000000000000000000000000000000014f09f909120686f646c2e6661726d20f09f9091001268747470733a2f2f686f646c2e6661726d1640686f646c5f6661726d3a6d61747269782e6f72671068656c6c6f40686f646c2e6661726d00000b40686f646c5f6661726d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3a4d5d0c403e3b4387cbbabecc63d610ae7d4e8089aa6b341a52764f822342e887ba35160a26a61": "0x0000000000000000000000000000000000074b68656f70730000000000000e404b68656f707343727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3a7aee697f8537eced0a17e590489a73c7187393c0004adf62f7bb12bc01c2eab624a81f7b11225": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3aa48e3a86671870cd7f4ead4230679019f6a6728e1b01daa539969c1ff6e5d7659ee88e6e7792e": "0x00000000000000000000000000000000000c44696e6f20582044696e6f0b506c616e6574204e656f1768747470733a2f2f706c616e65746e656f2e636f6d2f001b6361707461696e2e6e656f6e40706c616e65746e656f2e636f6d00000f40706c616e65746e656f5f636f6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3b1ad8cdba491b4b2379dab464407695ce9efad8a5b30814255ec0a7b680ed5e90b008d5991a730": "0x000000000000000000000000000000000007566963746f720a566963746f727272520000000000094056696352646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3dee0cf198fa26528148ad524276363bd3c138bcbf71d62971c8e7a4e67e4833dad82d554d1372a": "0x00000000000000000000000000000000000a446176652053616d6115536c6565704c65737320436f6c6c65637469766500000000000d4064617665646f7473616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3f203317925ee60342908079a81bffbcebf5120459750595a066d3d1a00547f26a5b8602ae1ec51": "0x00000000000000000000000000000000000c686172756e6f686561727400000016797575626172696465737540676d61696c2e636f6d00000d40686172756e6f6865617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3f2c1579fa4e27478baec43fd49badfce811cbba08b3f0ccf758b5e22f0c4d745452f5dad6eee07": "0x04000000000200000000000000000000000000000000154150455254555245204d494e494e4720f09f8e82001b68747470733a2f2f61706572747572656d696e696e672e636f6d194061706572747572652d6578653a6d61747269782e6f72671d76616c696461746f724061706572747572656d696e696e672e636f6d0000104041706572747572654d696e696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c3fdb0ea29d362e6b83d19e4a3ad242102f94a4452381300ace74c5d50fbdd9675a869401d3bff64": "0x040000000002000000000000000000000000000000000645726e69680000001a65726e6968656e656c626f7371756540676d61696c2e636f6d0000094045726e6968626f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c418004698b256eae08a0336e48b06e7993c654fe5a4eb0926b945368ab819ca106038ff7d951601": "0x0000000000000000000000000000000000064b656e6a69001768747470733a2f2f6e656f6e6372697369732e696f2f000000000d404372697369734b656e6a69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c41c1de12f5ccec960c320ebf47a6248effe7b1e0d9fa1a05472d9c9face28267a2d6f3897d8460c": "0x00000000000000000000000000000000000a4a6572656d313933310000000000000f406a6572656d7931397061726973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4203048b255be4d94d18f58da33ad88b8f369b0550f4f119c29487db123a8fd7808192c7515d51d": "0x0000000000000000000000000000000000054d696b65010101136d657461646f6f7240676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c43479830549f3b92b1898eea254aee5a9b583a87935d2fdc343cf246324922e7c843d13d4858f02": "0x040100000002000000000000000000000000000000001443727970746f50726f63657373696e672e696f001c68747470733a2f2f63727970746f70726f63657373696e672e696f0019696e666f4063727970746f70726f63657373696e672e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4352fa303548bd816e0943d412bdac132040c9c6c72b1e67f2669b9b9ed534c919ad61536fd6631": "0x000000000000000000000000000000000009456c6f6e4d75736b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4369a5a713b27e3fc7fa982540bee375242fda3776a68bc6b8f1a017d10060303b2a1492d508d04": "0x00000000000000000000000000000000000f656e436f72652e655865f09f91be00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c437a1a197732969421c28afeed76e4961a3def6e7a9df8c5bdbd2917e7dc07e16df23f858f06f63": "0x00000000000000000000000000000000000c4379636c6f686578616e6501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c43ae492abb7aee99234e13aa20406b05abfa896fd51dedf36648b5a73a45bb0518593a779c0503d": "0x00000000000000000000000000000000000941627320417274730000000000000c40416273417274734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c440bd35b1a2b564545efafec313a5bbbcbf30f172e615132bae08debd8141b0255523338127f52a": "0x00000000000000000000000000000000000d756e7a656e2d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c460ca530497a319165990d6152cdfdcb7ec7b5c44e5651d5061f0cc95cb30da6d5537cd8aa06321": "0x00000000000000000000000000000000000e43727970746f4c6f63616c6c790e43727970746f4c6f63616c6c791a68747470733a2f2f63727970746f6c6f63616c6c792e636f6d001861646d696e4063727970746f6c6f63616c6c792e636f6d00000f4063727970746f6c6f63616c6c79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c46ba4a0042e414d9ee1fa0d8d4e022ed5680b5925d19718a7ecc9f8f2ff77de54f0822978d27755": "0x040000000002000000000000000000000000000000000c476f6c64656e2047617465000016407365726269616e37343a6d61747269782e6f72671662637374616b696e67406f75746c6f6f6b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4706b7c96f81ec6cc89eac7f80e6c83bf44918ca04feb8a8a2583b4cba629d7388fd98f2ae14164": "0x00000000000000000000000000000000000b426972622054617065730000001442697262546170657340676d61696c2e636f6d00000b40426972625461706573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c48230cebc1a6bcabcd06bcfa928213a6402fca4096b81a51bbfce4105322ab80881148437d6e44c": "0x04010000000600000000000000000000000000000000084b6c69646f7a6f136a6f686e6e6174616e2067726973616c65730000116a67726973616c6573406d652e636f6d00000e406b6c69646f7a6f5f6e667473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4b6532d1c37b711aa18b3cf52cb27fd19d5b80fe7982ff955e0d5124dae26ac360056f401dad846": "0x0400000000020000000000000000000000000000000005454e4259001d68747470733a2f2f656e62792d636f6c6c6563746976652e6f72672f1140656e62793a6d61747269782e6f7267196d61696c40656e62792d636f6c6c6563746976652e6f7267000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4c023a99cd1728bba1b4c6166343cc8598bdebc0ed4baabf5aa3e212e19fbe876e9b2bf8ea8015b": "0x0000000000000000000000000000000000074754524d524b000000000000094047545f524d524b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4c10952fe64fecb528169b51314b1ec0f014bcd4453d83fa21320e5b19a3b2e02657d0c21f8882a": "0x00000000000000000000000000000000000e50756e6b205661756c7420233200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4cc158572b1a1217c49d0e3c5129947f9a8ff4e10fad98714c31499918013e8594bf3928fc5da3d": "0x00000000000000000000000000000000000c4b6c6175735765696e363901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4deb83fd3636acd789a634476bba8c44dda974b349800e3618b64732c488f98e75cd6941605ae1f": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c4f3bb9a6a26a4b7249aca910e224a87c14afb90980ef0db0a6b12c9d6b48c1acae111a1dda36617": "0x040000000002000000000000000000000000000000001050617261636861696e732e696e666f0000000000000c4070617261636861696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c516a00589c5f1062af1849b7c7bedbe910d02ee342f6318414d33f17a50f00c029ec0eb359c6174": "0x040000000002000000000000000000000000000000000744616d696d690000134064616d696d693a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c51a01ea9809075a3a42cbc61ac54236d45147631d7fb2b7b32003bc2d53e6e9534ca518084fd814": "0x0000000000000000000000000000000000114b6f7374796120436f6d7a756d6f6e6500000000000008406b6f6261346b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c531d8ad189c5d4d660e9b4063cfa8684f52190e679f8cbdcbeea8886bdca31d38c6da70c07bdf4a": "0x04000000000200000000000000000000000000000000096c61676172746f73000000176c61676172746f73313938374079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c544e460580be7c67c05666c7b84f6e937f6972ec3117110bb0750d2994bf1f680b133d990b98e1b": "0x000000000000000000000000000000000007796f7534323507796f753432351868747470733a2f2f6e6f74652e636f6d2f796f75343235000000000b40796f75343235796f75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c54cd15798f98d6ffa84a4002c8ade8078eeb6ee7d4516e548c6eefbbed2d87acaf329d77f29a378": "0x0401000000020000000000000000000000000000000009576f77204c61627a1c576f7720496e7465726e6574204c61627a205076742e204c74642e1968747470733a2f2f7777772e776f776c61627a2e636f6d2f1540616d69742e776f773a6d61747269782e6f726717616d69742e73696e676840776f776c61627a2e636f6d00000940576f774c61627a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c55831fe1424bc8f4a2a8a33eb13857917959b364672391a64e41f03129c74dc5bd7856fc0fcf964": "0x00000000000000000000000000000000000a416c706861204775790101010100001140616c7068616775795f63727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c560adb2f53e7fdbba0518b2408a0883ce26ff4ea90f8639ac05332bf82260fc45033d7b5baa0a20": "0x04000000000200000000000000000000000000000000097279616e686967730000000000000a407279616e68696773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c56c778db308e44b8e32641448f9a5ec78ad04a33b7874a2942ca7ad4c7e8ee2e45409cee1883e06": "0x0400000000020000000000000000000000000000000009436f6465676c6f770000001f74727564696562616b616e6175736b617332313040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c574259a47c36e9cc6730bbb5f77a45b3095c85b50d6d536d358147478f05ed0337d07f43a4de17a": "0x0000000000000000000000000000000000065369676d610000000000000f4043727970746f5369676d417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c5873c02a0650aff3cd8c53d034ca3f0878d3b02c6d2f42084d49c024f08ac1637b7446c6d48b952": "0x0000000000000000000000000000000000134c756e6f20616b612074776f636c69636b730000000000000f40706c68615f73655f686c617369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c59c65c996cb7128c8d887817cd801c256ae0adad712737a18a89e23eb061b7002839d16530fa0d8": "0x000000000000000000000000000000000009696e66726164616f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c59e3ec2cf0fb44e4e0bc107a3826d65cc8a42f501c9b0bfa88ccaf00041fd568566b99adeb3c154": "0x00000000000000000000000000000000000b4f484c414c412d4e5943104f6d6172204865726ec3a16e64657a1668747470733a2f2f6f686c616c616e79632e636f6d0101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c5a064463897ec28ba98d1704adcb69b1d50aebfab39709c03713555e3d49e75690492b0a02f547c": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c5b4b74e80892500b46d25d53359fe3d532417e8eae2cba1ed38c7c3fc775a4bd30df90f820d900f": "0x040100000002000000000000000000000000000000000b5354414b45204c494e4b0b5354414b45204c494e4b1968747470733a2f2f7777772e7374616b656c696e6b2e696f00116f7073407374616b656c696e6b2e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c5dad8e8b3b4327c8cc1b91e8946862c2c79915a4bc004926510fcf71c422fde977c0b0e9d9be40e": "0x040000000002000000000000000000000000000000000976696b696976616c0000144076696b6976616c3a6d61747269782e6f72671576696b696976616c406b6f6461646f742e78797a00000a4076696b696976616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c5fdab086521b971d0e861d8e4257e09a778688629f5283e51f9875a3def184722a0112005cc931e": "0x00000000000000000000000000000000000a53616c73616f7368690000001473616c73616f73686940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c605f4a4cc9de0cf60e353afd3230a13cbb023c276697f7c42071973b470b9b1e79a4c1d99f27857": "0x00000000000000000000000000000000002131334333384e657a734a4d6e434c7a56574d5070546b64504779696d6e71773600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c62159eb22aa2f9ee882cec1afe19967602ee2cb6ec847b913115fc2d2d1293b467f41f2a817f80c": "0x0000000000000000000000000000000000094d722e4368616f73094d722e4368616f7300001b746865627572726f776f666368616f7340676d61696c2e636f6d00000e404348414f535241424249545f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c62d71f1d9e80b5e284eb76f4116f4b75a718fd1a374cc5b6e02fc18f37e02deb3054e57539c5328": "0x00000000000000000000000000000000001ee29b93efb88f20444f542056616c696461746f7220416c6c69616e6365002168747470733a2f2f7777772e646f7476616c696461746f72732e6f72672f636f001b646f74616c6c69616e63654070726f746f6e6d61696c2e636f6d00001040444f5456616c416c6c69616e6365000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c637b13dd6b9ed4474c76b2bb6e2e4b16fec1849aefadeae913aed26e72e2101a4dc34abb3e40776": "0x040000000002000000000000000000000000000000000e43687269732d5374616b696e67001b68747470733a2f2f63687269732d7374616b696e672e636f6d2f1240636c616e673a6d61747269782e6f72671863687269734063687269732d7374616b696e672e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c654d73fa3ebaa0b52de56cc1be8f484e681df0b45bea0eed7149eb4b83af80723b44eba4d04db1b": "0x04000000000200000000000000000000000000000000084c4f4e524f5448000014406c6f6e726f74683a6d61747269782e6f7267176572696b2e6c6f6e726f746840676d61696c2e636f6d00000e406572696b5f6c6f6e726f7468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c65c9dea76fe6a4a04c560690aaf6359dc5dd27d7ad3424eb447f4460f1dff44949de5dadb457545": "0x0000000000000000000000000000000000064b657474790d4b6f746b6f7661204f6c67610c6b6f746b6f76612e6172740013616e747a616b617a40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c662ab00c0706d5924c127f0b5492bc5439fb0dc1acfed7132bc27b761eb5ac5904670091251d12f": "0x00000000000000000000000000000000000a5468654d61737465720000000000000940636f6e78657074000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c67401b1f25d1590b45b073f1e692d18c2dcebae861b2f166a4dbfd95d9780ffef603c9e61d00935": "0x0400000000020000000000000000000000000000000004536f6c00001a40736f6c76616c696461746f72733a6d61747269782e6f726718736f6c76616c696461746f727340676d61696c2e636f6d00000f40536f6c56616c696461746f7273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c68cd80f169ec5de3040ea71921e73b1d72152deb0d9076de5b09d810cc575fb6d11b14820fbbb04": "0x00000000000000000000000000000000000974307a656d30306e0974307a656d30306e00001374307a656d30306e407961686f6f2e636f6d00000e40416e64726577346973686572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c693160e6ea97aa8369478717731349632db8341d2a8502aab460f8109dfd249957aeb9b77c3b546": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c69417cb51b0b3c2440d92a969cae5defa9cce85c117ff51435b149ce2a58c38052b195a64f8d050": "0x000000000000000000000000000000000017526f79616c20536f6369657479206f66204368616f7317526f79616c20536f6369657479206f66204368616f732068747470733a2f2f726f79616c736f63696574796f666368616f732e636f6d001e6368616f7340726f79616c736f63696574796f666368616f732e636f6d00000f40726f79616c736f666368616f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c69593e93494eefa1a2b74aeaa4f3d498de298ffb9775c2918de5e045085edb29dc9f3e339045929": "0x00000000000000000000000000000000000b4a6f652041646f6e69730000001363686566796f6d7a40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6ad09b66af3693b2e9169837f2af124b7e7fbbed4f8b50f26e37f8cb31869d85bb773e9d9c6950b": "0x0800000000020100000002000000000000000000000000000000000a4a4657454e49534348000016406a6677656e697363683a6d61747269782e6f72671463727970746f4077656e697363682e7465636800000b404a4657656e69736368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6bbf3f9dd9143a5fe6c31fcff28694469c3d4c1681270bdacf6edf7ec39bda6c68cf25738268b79": "0x0800000000020100000002000000000000000000000000000000001b494e46524153545255435455524520434f52504f524154494f4e00000020737570706f727440696e6672617374727563747572652d636f72702e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6c6796a808b7f32a8a99a7f49f1d3d72656674fea67bc18454325f00c9a5921ec6010c43409d43e": "0x0401000000020000000000000000000000000000000009496e66696e697479000012407a656230393a6d61747269782e6f7267107a656230394079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6d8287d03be1c4e906896c321ac4e1c5b1fbdbadbe087fcb428471c1fa9509bec0baaa61bd69c78": "0x0000000000000000000000000000000000124b7573616d6120436f6c6c656374696f6e0101011c6b7573616d612e636f6c6c656374696f6e40676d61696c2e636f6d000011404b7573616d61436f6c6c656374696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6df602a0447f12d4ec842ef2dc300df355e4193020bcdd204bdb78978963f5a97afefebeed4c43c": "0x00000000000000000000000000000000000942616d6f72696d5f00000015622e616d6f72696d303840676d61696c2e636f6d00000a4042616d6f72696d5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c6fc06d7099c81042ae8b4dd8a198039584f0bb410ba2a196dbbbbb5198d21b0932029e389c92c20": "0x00000000000000000000000000000000000a536f6e6963303538380e457667656e6969204f726c6f7600000000000b40536f6e696330353838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c706366b7fce759bea11db7fb06ce5dd7875ec9573d1c2666d4f079eb40a23df9a4e7295a72c3b56": "0x00000000000000000000000000000000000766727061726a0e46656c69706520416d6f72696d000000000011406d696e686176696461706163617461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c71b74a26f01154dee57f7f5b5354df1ba908ea77cd152cb3376295e904616bb8048e0ec0a731800": "0x00000000000000000000000000000000000a477265656e20446f6705466f4c69000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7289bc44ade334e8db5c746c14cf05e182b10576a9ee765265366c3b7fd53c41d43640c97f4a8b8": "0x040100000002000000000000000000000000000000001144617277696e6961204e6574776f726b1144617277696e6961204e6574776f726b1a68747470733a2f2f64617277696e69612e6e6574776f726b2f001768656c6c6f4064617277696e69612e6e6574776f726b0000114044617277696e69614e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7306504e44e5ca6b6e98494bfd1254db60b4239094d4ef9e9b0d011ae4b27419d31b265f52d3b1e": "0x00000000000000000000000000000000001054616c69736d616e204d696e74657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7431d97f66121b2fe0a9613f17e9a72fa193ef556525358015d183e34a58d63832eddb68fc78873": "0x0000000000000000000000000000000000094c696e6b53796e630e4c696e6b53796e63205465616d1768747470733a2f2f6c696e6b73796e632e746563682f00136e69636b406c696e6b73796e632e7465636800000f404c696e6b53796e635f54656368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c75dd7643a34b25812238aff71d46adf8a5d90a96a764310904cd460493fcfd8b59aec1e9a44781c": "0x00000000000000000000000000000000000c536e696666657220446f6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c75f3283311aa7a1ecbe5cbbe411d0184ebbea1f6e66191f16cf08b10394de1504377a522b67bc38": "0x0000000000000000000000000000000000084a616b2d50616e000011406a6b75623a6d61747269782e6f72670000000a404a616b50616e696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c76c5b0b61a843d020f7bade1ae4ca9f39f905afab90dc0973f36f6c6f4bf8a4869e074ff2fa7529": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7a8b14e7c045596a8f4e76e2abfd5c4ad2714c6882ee548d8bb2673a8c5fbd4d5d7d8f156d02c52": "0x000000000000000000000000000000000009417274466c616d6509417274466c616d6518696e7374616772616d2e636f6d2f6172746631616d652f000000000b40417274466c616d6535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7b5421a37e04c7cf27d586740d74313a7f109afe5b90bbbf4ce7bfaf6012e8cd417f517658bc665": "0x040100000002000000000000000000000000000000000f446f745363616e6e65722e636f6d0f446f745363616e6e65722e636f6d1768747470733a2f2f646f747363616e6e65722e636f6d001561646d696e40646f747363616e6e65722e636f6d00000f40546865446f745363616e6e6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7c50372810d645f1e58008212a2c39b0f3366f8698c6f4b3971fe5d694d943d60695da4c7307e7c": "0x040000000002000000000000000000000000000000000d57686974654861776b446f740000001777686974656861776b646f7440676d61696c2e636f6d00000e4057686974654861776b446f74000d77686974656861776b646f7400", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7d0409d778a3abd0a25fa0107b9d17ab528cfa9364e83d15ab9cb6b23cbb8e95434a10265e78861": "0x040100000002000000000000000000000000000000000a5369726975734c6565000018407369726975736c6c6565653a6d61747269782e6f726712616c653461696e40676d61696c2e636f6d00000c405369726975734c656565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7e1ca011cc6d3a254c2eb516540f8e793d64120867503bc75ab13dbd7d372a84deb2383dd34be37": "0x000000000000000000000000000000000006504c4b445406504c4b4454000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7e9bc04cc0841dad6030dd61ad78ca1900865d2b53dd163bbbb5b40c82f94d25cb6ecc750a93c25": "0x040000000002000000000000000000000000000000000d536166655374616b652e494f001568747470733a2f2f736166657374616b652e696f1640736166657374616b653a6d61747269782e6f726712696e666f40736166657374616b652e696f00000d40536166655374616b65494f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c7fb1e9c29198d8a5a85dc8a03b70155cfa555804f87078d55ce094d664b93ca4fcb691b04581b4b": "0x00000000000000000000000000000000000c4f6e65536978747954776f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c802b345e9db30fc5ee13a0870d2fe2f9fe52be9487d3981daacb54c0f5be2d258211757f2fabf45": "0x00000000000000000000000000000000000a5355534c4f20322e3000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c80d06b5de46ac115084e4f3181522430ad839d9f8ab908a9311f7bff7960d5620a4ece21dc6c373": "0x000000000000000000000000000000000003626e01010119656d697432746869734070726f746f6e6d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c81b2ea6aabcc47572d9e3049948847b9e6a6530644c05a2cb45c106837134cf856a850edb5d984c": "0x00000000000000000000000000000000000e62696e616e63655f6b736d5f310e62696e616e63655f6b736d5f31000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c84305f46d65de06525b16363e519b5050accad8bf325992eb4277f962c34a45908a3856d9b4df13": "0x040000000002000000000000000000000000000000001d4261626573205061706573207c20626162657370617065732e636f6d0000184062616265735f70617065733a6d61747269782e6f7267166f666669636540626162657370617065732e636f6d00000c4062616265737061706573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8459543e4138852ec8bcfca5a803b4b7ff05c9370c75a32eb54ea934d0b70a79e28f3cf6f083f7b": "0x000000000000000000000000000000000012566974616c696e61204b6f6b6f6c736b6109566974616c696e61000019766974616c692e6b6f6b6f6c736b40676d61696c2e636f6d00000f40566974615f4b6f6b6f6c736b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c87a0357c51f3bb52c12d0743cebb84ccae67b4976d38c592750755318e088a58787ed6748af1b06": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c880212d643a2db0cece410e91027546424d251e4f6b3ea9edda00a3436226fcfa0caf2d4abdd243": "0x00000000000000000000000000000000000a42697457697a6172640101010100000d40307842697457697a617264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c89160c2ea73fddbd66187af628f50edc02d990b6b1a67b9891a65885b9bb34c07ba4eda1b6c316a": "0x0000000000000000000000000000000000084d63466f726765000000174d63466f7267654070726f746f6e6d61696c2e636f6d00000a404d63466f7267655f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c89f64234957ad3efa26953ec6ea1b5ea142dc695d8b2d021297ad12925a3c8dab825c4b77eb3a71": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8bc7c91a9135daa9c41d150136ee8ce0413d0d3b8943a3b40012daec573830dc5380540965c287e": "0x00000000000000000000000000000000001674686f6375747431303230534d53466b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8bd1d64af2d39cd2aa84a3b6e4fa40f02ba25778f3b48821f93170a88a06541f5f4d0e98fb0d444": "0x0000000000000000000000000000000000086e656d626f6b6100000000000009406e656d626f6b61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8c652a6c6cc03c086b64d128a69e9b1029f83eb7bf9fb1df919eb2986dd79d22800df7090ab2410": "0x0000000000000000000000000000000000034246034246000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8c74a2a3e4f4b82be8ca3e846ae7a889e4c1da80d271e206587513f37f603af9fbb27d79cdca91d": "0x040100000002000000000000000000000000000000000d444953432d534f46542d30370e4469736320536f6674204c74641a68747470733a2f2f7777772e646973632d736f66742e636f6d154064697363736f66743a6d61747269782e6f72671876616c696461746f7240646973632d736f66742e636f6d00000e4044697363536f667457656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8cf8e50848b5813a6005418ec9127ff3a23ff34480dfe3434895be2245e6f8673f4d44423f99b6e": "0x00000000000000000000000000000000001454616c69736d616e5f465220f09f979defb88f0000000000000d4074616c69736d616e5f6672000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c8e58aea5331a2e440480cf82274010064f8deaa5c77dab6a2fa59daa455692ce54d12c9a994b269": "0x04010000000600000000000000000000000000000000094e46544261726f6e06526f676572010113726f67657231343940676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9004303b036c946663e90acdccbcfe743f4c5452f91ff1839756d4799ff6459b49aaa5a438fb754": "0x000000000000000000000000000000000008636174736f756c00000016636174736f756c626f737340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c91fe577b6a958b7284f0b64b6dee82e7183d0ba4c04670afd04ff4a63c9e1e14bda8a73f3b65450": "0x00000000000000000000000000000000001d4b7573616d612d437270746f666f6c6c6f776572202d20537461736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c92c1ed9cc10809adcc362696a6099c29778cd123cbb6d0f495e3f1a9e72afeed4b2db4f2139626e": "0x00000000000000000000000000000000000e4b7573616d6120436173696e6f0000001a6b7573616d612e636173696e6f40686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c936f994b872349594c58421e4f981eddc24e9609efe14d2a9842c941333909917c948007928f203": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c937b7672d52bb682e5bb027d9dd92dce26c209287f9d28539eafca5a061f4813518986f7a938824": "0x0400000000020000000000000000000000000000000006416c696e6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c96059c5a9afeefeba0cb35373e16ab18a85e196f1ee92c262bdcb1a5633bfd4e0d2de5566c7fb28": "0x000000000000000000000000000000000002410241010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c978425d9379314ea415a980463876c54b503c358613b5c02d8ac9781c13378797c54ab37fc07c05": "0x0000000000000000000000000000000000086564797a65726f086564797a65726f0014406564797a65726f3a6d61747269782e6f7267146564797a65726f40686f746d61696c2e636f6d000009406564797a65726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c98618f1bd5a9559866b5be7949c1d9d84c3dcb5261213de3a6de7673c9010f7228d3948025ea51e": "0x00000000000000000000000000000000000942657a53766574610b4b6f6e7374616e74696e2068747470733a2f2f6b617274696e696b692e776f726470726573732e636f6d0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9894f2fca6676bee29fdae6c638b84830ee42c3038d1422fa07f3b588f818d58652187753c99747": "0x00000000000000000000000000000000000d5472616465204f722044696500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c99f95af84d55e0f7c1e751284e8cddc8b0ba57858b136458feea7fc3d78913c2a222e1486b81951": "0x0000000000000000000000000000000000074e4b59323235074e4b59323235010101000008404e4b59323235000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9a1faf09b047ace962bea82e7158b909964ed9a4cda3c07f9ceec8a8f3150264e706fe9c323a91e": "0x040000000002000000000000000000000000000000000857656233456475001a656475636174696f6e2e776562332e666f756e646174696f6e0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9b1a3c984ec1527125166e9a73e926987e64576b3c811f492f4f68e014ea24d780d6442897b6226": "0x000000000000000000000000000000000005706c756b11446d6974727920566f726f7a686b696e000013706c756b3239303640676d61696c2e636f6d00000840706c756b3239000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9c02a3bfc8b9747e2b3d30136a5bf1ad99ed78efc1c0cfdc6a2c65d3e30d86b3303f3533e155032": "0x040100000002000000000000000000000000000000000a4d616e74726144414f0a4d616e74726144414f1b68747470733a2f2f7777772e6d616e74726164616f2e636f6d2f0016636f6e74616374406d616e74726164616f2e636f6d00000b404d414e54524144414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9cbe4bcf11c1191d2eb148157fb8d45267e129807f60a442f1ccc47ae4df830afa70d9f43a57b7c": "0x0400000000020000000000000000000000000000000011426c6f636b6f7073204e6574776f726b0000001d656e67696e656572696e6740626c6f636b6f70732e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9eb326fa16dfefb70220894f522a1bc8fbef6774ee1c8a5a9ec8d1279b87238a7e19dbd30e72240": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9ec7a14c6f069793af2efd3517588570b437e94d0681cb274292bcdc5691a669cc50c0359599419": "0x0000000000000000000000000000000000054375727500001140637572753a6d61747269782e6f72671363757275666972654067616d696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714c9f8fd074bd000b91e08d2544c9cd5587cbe30a3108cfc4cace618a9be8b454f063c9c572328a811": "0x00000000000000000000000000000000000544652e4b0101010100000a404b61726c69734433000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca0bdf2dfb6adbfd82bb64e45f4f9a337768606d2742d2d9a8f74c5b182538988f3f482385c5d710": "0x040000000002000000000000000000000000000000000e77332e6369736865722e636f6d000013406369736865723a6d61747269782e6f726713737570706f7274406369736865722e636f6d00000c406369736865725f6c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca359eff9e5c98c4540dee563747c9e9b41643cdab9e52e9af92a94e44f4c66dd6fa90f384c2384d": "0x00000000000000000000000000000000000542656e6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca36ea10611335000e26a5618f2b9e282f4d6638ed18fee981c6a14c8e9062fdbcb2e6d40f8c0e02": "0x0000000000000000000000000000000000135354414b4542414259204b534d205045525300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca6541d4aefa2e0e7e7ffb2550dcf65f92cfe6aa95b1a6a14f48c7cccbbb86dec448ce0bc7d1060e": "0x000000000000000000000000000000000008537573616e746f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca89595ab373b7c7cc441e3c9176c763162f1c4653557b5d8db2826617b3047c71304d56af3dbd45": "0x040100000002000000000000000000000000000000000954726f70696361720000000f74726f706963617240706d2e6d6500000b4054726f706963617233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ca8ae099693f9dabd8004911e882a05affdcf81aea45f611077f07a29dacf6b754bb69ab118ae067": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714caa21989ef628ddcbc63ced3f8fec642128f2aa9c37e989a9313a67e9635dd85e8bd689ae8d0ce1d": "0x040000000002000000000000000000000000000000001bf09f9191204b696e6720f09f9191204b7573616d6120f09f9191000018406b696e672d6b7573616d613a6d61747269782e6f7267156b696e676b7573616d6140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cab78cfc920692024cc2c4fe71152a41691987950d065635bc8c151be2a230ec84bd9fc8174b2414": "0x0000000000000000000000000000000000044a6f65074d65646c6579000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cad2d474a0dca84ae2a70ba05a38bfe12181cdbed954062cac47eb43b03bf8681d21ad3cd1622610": "0x0000000000000000000000000000000000086976693830353511596f656c2047757469c3a97272657a20000015796f656c736b6174653140676d61696c2e636f6d0000094069766938303535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cad415ee82b7dc86eca814d4775cf33d04650685b06650cf09795a82bb5190ae30f566fd4479c63d": "0x0000000000000000000000000000000000075349474d415201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cade31e76e0a70d17603f2862f044ccc7500542f4b7c1a506a906b92328e1f2b67bf5024d2af920c": "0x00000000000000000000000000000000000b504a53204b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714caf961ad1b6e226da072610f1e1ffade38a6d64df55a89e6b07f65ed2be0eb6efffdade4ca576c12": "0x040500000002000000000000000000000000000000000b4b6972696c6c5f6e6577000014406272797a67616c3a6d61747269782e6f72671b6b6972696c6c2e6272797a67616c6f7640676d61696c2e636f6d000011404b6972696c6c4272797a67616c6f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb01c78fd35d35a1947a4a4de496a602e3a59632dbae52cae69ec75b3553f4e23d65480bd892463e": "0x0000000000000000000000000000000000064d69616d690a4e6f207468616e6b730d6d6f6f6e6265616e732e696f00136d69616d69406d6f6f6e6265616e732e696f00000b406d69616d6973616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb0f792fe8070fe270499e87a23c3f1f543386563f418c35cc2be29aafabeb0cff59a0f15cddd465": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000013536b794c616220436f72706f726174696f6e001868747470733a2f2f736b796c6162636f72702e6e65742f0017627573696e657373406b727970746f7666782e636f6d00000d40536b794c616273436f7270000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb15c6b86fc6d4c40c6a06de638df5f682965b5fc5e146942a192ce193d18f9d16a5c83e1c2d0e67": "0x0000000000000000000000000000000000076465706f6f6c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb175b4b598df6c7d264719b38fdf6e7c0826edbe8f577806f45dfc22730cf9c9c880eb6ca4f1258": "0x00000000000000000000000000000000000753696179766f094b61746572696e6100001963727970746f6b6174653139383840676d61696c2e636f6d000009404541726f766161000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb2e9537050cc6d62c945b125c1ddc7093d9eb5108eb5fb03fd7f5b2a356a60550e74b9e64597d56": "0x00000000000000000000000000000000000954726176694f6c690954726176697320480000185472617669306c694070726f746f6e6d61696c2e636f6d00000a405472617669306c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb3200a490ec72062033f1e89095d22a9c51162dbcce5e28a6b12957fdcb4c3cf11ea8def5ea1e22": "0x040000000002000000000000000000000000000000000d426c6f636b20736869656c6400000017536869656c64626c6f636b734070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb33c8d6014b97d6009acf482631bef09c51464c57d5db30ddd875c5f21dd1199450ca32ef023955": "0x00000000000000000000000000000000000c4269674c69646f77736b690000001a6c69646f76736b692e63727970746f40676d61696c2e636f6d00000d404269674c69646f77736b69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb4a358712ffad148aee4e164d5d70ac67308f303c7e063e9156903e42c1087bbc530447487fa47f": "0x040000000002000000000000000000000000000000000b6c6f6c6d637368697a7a0000000000000c406c6f6c6d637368697a7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb682ba63a12c17de85518efd0a4dd7c45fdd8c606b0ee505a47a27d346217a2109408ee13274c5c": "0x0000000000000000000000000000000000064a44756273064a6573736500000000000a407761726d616e6a6d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb6a20ce60145023dc3ef96500d9246616e58c2621b52b0fe610b2877cc448729a0fa245d76c2e12": "0x04010000000600000000000000000000000000000000066a696865650a4a69686565204b696d0000156a656568656537383737406e617665722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb6fae720ea9e75188113b77ec9a05954eb87c58258f605a9e987cd76da77c6db8ba3fabeb8be144": "0x000000000000000000000000000000000006526f62627900000014726f6262796e66747340676d61696c2e636f6d00000c40526f6262795f4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb7cdfdf0c41b9fc9638b522bb7d9e74755fdaa96ac541ca9b3b1f287c413befaaa90d0dbeac2627": "0x00000000000000000000000000000000000b526f6e204d657869636f0000000000000a406a61647979637076000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb88098f8f0bdce5b8a47aa823c43efc9b5ffb19e212e2aa2cf3fd23347f618dbdb49319390fc870": "0x00000000000000000000000000000000000e43727970746f4368696d65726100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cb98884ad3631884800aab741beaf15ba953897b937ea73ec9d823b1f882e375e6e0863e1537d840": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbad766d1d5ed042d8af91f9bc822770333d322df946d3fd70b816725c14aa94fbbd668cfe1afd26": "0x00000000000000000000000000000000000a4e696e6554616c697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbb80a8be45d87d27c766a66c689aeb53cfadb70d916bc8a976d5732a3e8657a43ce679104dd115a": "0x04000000000200000000000000000000000000000000046b6d76000000146c6164616b6d76313340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbc6d5a0fa733344dc1f18d3495ab571a17c68c9c9142e58c590637c1f07c582969acb8d3ef67603": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbc819e175aad208ac2709eb9569c861e63940eefaec1f51ccb76eaa84544e56331adfcdec859911": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbe70110da64cd0f364ab212143283a263d9a026f023d91bca9053138592463508fa9eebbb597235": "0x0000000000000000000000000000000000074255424c4f5401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbeb065643b9d95a5e79c3b5b7ac8d930fa186708560edb94e9330c19942ba44830da6ee42171327": "0x00000000000000000000000000000000000b4475636b206f776e65720e446d6974726969204f726c6f760000176c6f7665636f6c6f72646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbf301ce3bba9ceb6ab369ac6c6a1d4c5f3b22db6653f8a9f69a1337c993e224329c82e7c0fa0d72": "0x00000000000000000000000000000000000b414c43455520424554540b414c4345552042455454127777772e616c636575626574742e636f6d0116616c6365756265747440686f746d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbf8387678df0b09a4b09d484bc36928c3153a6beeaab89e92572b30c1bc4cffd7ef086994d01324": "0x00000000000000000000000000000000000754616465636f0e54616465752053616e74616e6100001074616465636f406c6976652e636f6d00000f4074616465636f73616e74616e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cbfa34eb67b328eafaf4d633c738f86a7a26ef5c993a9079fd3fef82a565b65f14f9c4cc8e569e47": "0x00000000000000000000000000000000000453434f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc169cf732b5dc8c32b2070011076282b898fbaa43821fa6bb6dc3625b2698e52d79337b37c258d8": "0x00000000000000000000000000000000000c44696e6f20582044696e6f1144696e6f204d61696e2057616c6c65741768747470733a2f2f706c616e65746e656f2e636f6d2f001b6361707461696e2e6e656f6e40706c616e65746e656f2e636f6d00000c4044696e6f5844696e6f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc3222aeb2d95a7cf60bb5621e8977718636c7ccb5a45c83def9c670175c845b9b38455da2718014": "0x00000000000000000000000000000000000b4a6f61642e726d726b2000000000000010406a6f61645f726f6472696775657a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc35db54eb98ba1950e5130bfbe3f3c62d83fd50e01b839fd4d45ddf4e07b19faf39a183ec21a93a": "0x000000000000000000000000000000000009656c6f6e6d75736b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc38c8458a0ac5f12e4ec1a3f402d5b1d0164802b0aab98ae581a6c248cf84093634916377d2e733": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc718a6b9e9964318ef5289702f6b8c7d22b3562ffda7d5593a5f6414226925e72097efbf9b25720": "0x040100000003000000000000000000000000000000000d5265676973747261722023310d5265676973747261722023311868747470733a2f2f7777772e63686576646f722e636f6d144063686576646f723a6d61747269782e6f72671263686576646f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc73c26e52b725e15869e5f3b7da844b1638ae3d076f73a439bd4477701b2b95bd4137893bd0a727": "0x00000000000000000000000000000000000944616769654465650000000000000a404461676965446565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc8d0888d5d6f924400daf17b98e3592f65147d0fb6dbd1c322e5562ffeb11ebcf6763a171eb144d": "0x0000000000000000000000000000000000055354414e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc8de026a3642284a0e2ce7bf17dd65ae193d2b0a5723d089b5d2969045b2c7ca722a43d7efabf64": "0x040100000006000000000000000000000000000000000843727074646f740101011463727074686467373940676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cc9822c9da4c837c86b7409a11700afb027924cb40fa43889d98709ea35319d48fea85dd35004e64": "0x040000000003000000000000000000000000000000000ef09f8dba2047617620f09fa5831544722e20476176696e204a616d657320576f6f640c676176776f6f642e636f6d1c406761766f66796f726b3a6d61747269782e7061726974792e696f10676176696e407061726974792e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cca36d817010587dacdebce9d35e7cdf4793cd9eb2a1223e568c2ed0684d9b852fc21b70a0c86237": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34360f62696e616e63655f6b736d5f3436000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ccf50f8320382ca644da8d011a0f821b2e39d6151f8e17c417c0e09b664587dfe2021a194ee95d74": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd07125b43213e171c82102e4554587f23cbd4bfdb0f43c9d2879d18feb6102bbed977930f695f22": "0x040000000002000000000000000000000000000000000e444f5a454e4f4445532e434f4d00001240646f7a656e3a6d61747269782e6f726716636f6e7461637440646f7a656e6f6465732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd16bfe2352b1748923f2994a4c517694b0c566751a4670c49cd95c9b545e37c46b9af820dd7dd6e": "0x0000000000000000000000000000000000066465766f68000000146465766c696e407a65697467656973742e706d00000b4064627261626173736f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd1ac1ed28e6a58174b2a542bf7ec24dd9947ac9584d8352191f0154185cf7273f08a79e9ea75f00": "0x040000000002000000000000000000000000000000000e53504143455f494e564144455200001a4073706163655f696e76616465723a6d61747269782e6f72671b7370616365696e76616465722e646f7440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd23612967eaf930b8970463116cf97047eb507bc4cbaf1bf77b88216bb6e89b1da5672a44f02f4b": "0x040000000002000000000000000000000000000000000b414b617069746f6e6f76000014406b617032666f783a6d61747269782e6f7267126b617032666f7840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd367e518a4206c79653ea6fa2a3e4072178c4de671464a69d9c72c7ff7170bc76697b46b3947b0f": "0x00000000000000000000000000000000000453616d0d566c61642053616d6368756b000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd3c992836bd43255a17ce1052e06f947dda66c6144fffbbc07492394521bc16427f9b9851b48821": "0x00000000000000000000000000000000000642696767730000000000000a406269676773636d73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd4606afef2e28ca7eb19cdd47013d60f73e4c9b3e7e95c07dc40841c72d62951b8ed39d46d64a2a": "0x000000000000000000000000000000000005636f646500107777772e636f64656e6f64652e63610000000008405f5f63306433000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd489db0874b4738a6483f0d061421d62af3e621dccb1ed608a177e4043ba4d2d73e0935976fcf2a": "0x00000000000000000000000000000000000a6b666775736d63323100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd4a30ce889e7a55c04f1633da0ab6cb71f71ece4d1a5c32926d3f707d250f66ab712d65eb374b2d": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd5a4e9b4e3a205200778b6f2104578c212125b47b52181aed777a047f3b299353c36063a5028a11": "0x0000000000000000000000000000000000115468652041766572616765204170657300000019746865617665726167656170657340676d61696c2e636f6d00000e40617665726167655f61706573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd810312c75ed239feb72a25692ef5988cbd2a2b0d5712c47149820d2cb35f0c7fc97635b2eb4b4d": "0x0400000000020000000000000000000000000000000007477573746176000000166775737461762e6e69706540676d61696c2e636f6d00000c406775737461766e697065000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd8ba9536297030e5eb369d8759d592d5bab556aff1e2bac770979fc9bb30cb7dd503788a154826e": "0x000000000000000000000000000000000003445300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd92383c67926cf490b857bd025228fc9efe2f2ba5a58a0bacfb3c40dcc0557e484c17a63be1cb1b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cd9a6f0d7176c667f8903521d75aa8e9c24de8f9fea4011c1ba56c613da7b12bc9a894b896ae7a79": "0x00000000000000000000000000000000000c4d616e75616c204d696e740000001a737562737472796c75734070726f746f6e6d61696c2e636f6d00000d406d616e75616c5f6d696e74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cda0448328a47d986e78d0861320e3ba6c6b8eecb666b245d2bf06652c1fa86f7c150e9b2b6f772f": "0x00000000000000000000000000000000000a7061696e6b696c6c7a0e4d6f68616d6d616420417761640000157061696e6b696c6c7a4069636c6f75642e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cda070697bb44382d2cfdfb80cb90a4a5826c98846a367489fd25d3a2561838fa372f39f3f7fb138": "0x040000000002000000000000000000000000000000000c503250205354414b494e470c503250205354414b494e471868747470733a2f2f7032707374616b696e672e6f72672f1240316c3363353a6d61747269782e6f72671a7032707374616b696e674070726f746f6e6d61696c2e636f6d00000c405032705374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cda793c07d75efb0d4b3dfa23d4da0e7b854d81a2da2d369bd1358ff743fedff29aa5cc1f5fb6444": "0x040000000002000000000000000000000000000000001141495745423320636f6d6d756e6974790000001261686a7863727a40676d61696c2e636f6d0000094063616f5f6c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdb0222db39bc78600516484b2e6bac9fcaeeafa925b183ccd118b747074c475f188348e98d85644": "0x000000000000000000000000000000000009737544726f6e696301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdc30a2149db3bc32a5473f95881089686743849021bc41ddafe705b0654f4fbd84a8c7f7518ad49": "0x00000000000000000000000000000000000b4578706572316d656e7409416c6578616e6472000010636f6f6c36363640756b722e6e657400000c404578706572316d656e54000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdcaf2c89675be00ca5963dcd0af5bd2441dd34631995251b151baa252bfc5b80b78637b779b8518": "0x00000000000000000000000000000000000b4e6f5f53747265535f5300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdcb048b3228e1971c167f680b246a86565aa36eb8e525d2ccde935f9be8f53ff592326d7d7bec61": "0x00000000000000000000000000000000001c496e2070757273756974206f6620746865206d657461766572736501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdd9fdbc6dbda2f1362f9efe78a0d238501313e68a74a9b6257f406c5c62c9162d96852a13f79902": "0x00000000000000000000000000000000001853696b204e4654207c2063726966666572656e742e6465001768747470733a2f2f63726966666572656e742e64652f1540646576305f73696b3a6d61747269782e6f72671a73696d6f6e2e6b726175734063726966666572656e742e646500000a40646576305f73696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cde110fa4c51bbb438a48b1b98077c557c474ad091c854286fdf929b0e710299b16daae9e0ae4a77": "0x04000000000200000000000000000000000000000000084d65726d61696400001a406d65726d6169646f6e6c696e653a6d61747269782e6f7267196d65726d6169642e6f6e6c696e65407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cde412338d7923785ebe5000d4785e181f7f84d06445071b0d4f5a98cc30d7c566830811b6d33c5f": "0x00000000000000000000000000000000000c54657373615f4461776e310000000000000d4074657373615f6461776e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdf45b2bad669b8abcb3857cb91529a5fb21358b1ce837e4c12dac8c095e87e689a91dcd58e9bd3c": "0x040000000002000000000000000000000000000000000d426c6f636b2042726964676500000016626c6f636b6272696467654070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cdfdcd6d89826c1a521909b30a6816fa9a8796e5233ba76cae620e8577a525dd5606baf0797bcb6e": "0x00000000000000000000000000000000000d64726177696e676b656974680101011764726177696e676b6569746840676d61696c2e636f6d00000d406f6861796f6b6569746879000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce039cf8a6e0c411546c4b57539ccb82e3ca981340b2eee5b3c973798f1ffaa671d6276031a6d16f": "0x000000000000000000000000000000000007416e67656c6f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce0fc9b4caf7f03d56923fcb0c362b333a2833175025883860f6b93996233319503a4ac478b7b115": "0x040000000002000000000000000000000000000000000d414c474f207c205354414b45000016407368616465776f6c663a6d61747269782e6f726713696e666f40616c676f7374616b652e6e657400000b40416c676f5374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce591cccc3c347d0fc90e922a45ef6a5dc3c8abed38bb0aae5b9aa7efcd388fab60e329fe9c2d945": "0x04000000000200000000000000000000000000000000084252554d4d4945000017406a696d6d692e313939383a6d61747269782e6f726718756b2e6a696d6d692e3139393840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce5f7c846b1c490828bbb43cf5a770578c5bde89fbb3e4a71d3d19e7e28206bd70f41477984ca123": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce79163e5f308367344c5f7ce70559bb401142aaab72f4f6edbe78b4908e6769084cde89349fe63e": "0x000000000000000000000000000000000014546865204772697a7a6c792057697a6172642000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce8d111891bbfa55b4a5accc15f38c85625e18235ef02b0ac671d5016397b23c9d866706db431033": "0x00000000000000000000000000000000001143727970746f5f41726d6164696c6c6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce98d27dee4a6c1028258fd47fd5ab4a8e87741bad51dc7a17217617e1d7105bc9b2f8ae4b4fe708": "0x0000000000000000000000000000000000054c656e610000001763696c696e6761726a616e6140676d61696c2e636f6d00000f40656c656e613937363534333235000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce9a50917cf77bb19681fe005baa3099a7d9c03a46e539b173d2b3de75b11e86cd5fbb7d4e92993c": "0x00000000000000000000000000000000000a4c69676874736f6e650e506564726f204d6172717565731968747470733a2f2f7777772e726d74657272612e6f72672f00196c69676874736f6e656d7573696340676d61696c2e636f6d000010406c69676874736f6e656d75736963000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ce9f04748b26cc2d2a6bfaf3c320491696e649842333c75f041faf71e2676d8bfb45f71580372e48": "0x00000000000000000000000000000000000a417274204b697474790000001c6172746b697474792e73696e67756c617240676d61696c2e636f6d00000c404172745f4b697474795f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cea9b7b0be6d4be2f0e5ac8e356d7a3867e9919b8cb1984ee5a070b1659b6195deb85039a3b69928": "0x040400000002000000000000000000000000000000000b56344c494448344e44590000154076616c69646e64733a6d61747269782e6f7267166b75736e64734070726f746f6e6d61696c2e636f6d00000d4048616e647943727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ceac28e060489d6e601c5348ef25d1c6c432065db0ce29dc6c0b45abe9b5f5e7f2e8f57a49479b6e": "0x00000000000000000000000000000000000b706f6e79737461626c65011c68747470733a2f2f6e66742d65786869626974696f6e2e6172742f010100000c40706f6e79737461626c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ceb2fa92c621e2f85abce4b7d2e2b94046f1b7e77885b955a7cb214fa4a63055945accbf01debe17": "0x0000000000000000000000000000000000114152542047414c4c45525920494e432e0000001f73616c65732e61727467616c6c6572792e696e6340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ceca4f391ff42f7042316a3e69911695b705e5428a3be87a2b656a09126fdcdd2ef105995132de1e": "0x000000000000000000000000000000000014546f6b656e20576f726c642050726f6a6563740f4761627269656c2053616e746f731a61727473746174696f6e2e636f6d2f6761626f75776e65737300156a67616273616e746f7340676d61696c2e636f6d00000d404a4761626f75776e657373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cecd17edf1cf34fa3640cf6c8548a076a324a04190b30c74a44809ee11fd684f49a46134204aa47c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cecd3df8f50e86adfea23409b33280a4e0109a957dff8a732b88b7e8f85e415a124d64664176a155": "0x0000000000000000000000000000000000094d617279313636300a4d6172696131363630000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cedae9c81b8ef8ff42be75cb933073a967d8cb8c6c723028208a678c5a58f5e8f49a237eb33e1654": "0x040100000002000000000000000000000000000000000d4a61792043687261776e6e61001e68747470733a2f2f6c696e6b74722e65652f4a617943687261776e6e6119406a61792d63687261776e6e613a6d61747269782e6f7267194865794a617943687261776e6e6140676d61696c2e636f6d00000a40476c646e43616c66000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cef56560701eb05fbe5e55779d8749406e8ccc62030eafaeeaacb7fe4f583104b2c617c71f4ffb1d": "0x00000000000000000000000000000000000a42617272656c44616f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf11366ef8733f58e8926b5917a291918a2f0381c1213800798ff37689901f16b6cf42074c61f076": "0x00000000000000000000000000000000000d73756761204469636b736f6e00000016737567616469636b736f6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf1172ac1fb91b86c07040b1be7aedb10ffc0f136b7e147e4a1ad56944c1c76d6c2f6ca089cf316b": "0x04000000000200000000000000000000000000000000094252415645424154001668747470733a2f2f62726176656261742e696e666f154062726176656261743a6d61747269782e6f7267176272617665626174696e666f40676d61696c2e636f6d00000e404272617665426174496e666f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf126c7c679daef68cbc7210c46afb6cbcbcc10c096d3d5f2c9032242bb4e919abf56300abe3ba37": "0x00000000000000000000000000000000000d50617368613139383870726f214f6c656b73616e64722056696b746f726f7669636820486c61646368656e6b6f000019676c61646368656e6b6f3139383940676d61696c2e636f6d00000d40416c657832303231626574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf32922a67ceafba60ee9ce321ac84dee361edcc6f26a0e04a937a13c6ac1e9c5668805383331311": "0x040000000002000000000000000000000000000000000e42617a61722d5374616b696e670000001a65646f6172646f62617a7a6963613140676d61696c2e636f6d00000e405f43727970746f42617a6172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf5169125cd7414c8875bb054b7e9b35a2d84c19152d17947b1ff629edbf1759ddd9f04ce33b495b": "0x00000000000000000000000000000000000753636f7474790000000000000f4043727970746f5f5379646e6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cf9fb3a7967406dbd08ff136a249a1e0fa14d1dd102f4ca95436d000428a6bcf3dbc178afe19974d": "0x000000000000000000000000000000000009566976617269756d001868747470733a2f2f6372617a7963616e6172792e6f72670016766976617269756d6e667440676d61696c2e636f6d00000e40766976617269756d5f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cfab6a8090dafa3c00ad3ac9b1478e7fe24ec13e47acea1de9c52dc4b1dae34311524bacf23b5d0e": "0x04000000000200000000000000000000000000000000154a4741667261697343624379662d2d2d65644e3700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714cfe36321ef78340db0d6a32a5f2a51d3814658dfdb3c0f9448c57cb18a766c755a6310166dae3137": "0x00000000000000000000000000000000001e4c6567656e64617279204b696e6720262053776f72642042756e646c652142757920746865204b696e677e4765742045766572797468696e6720456c736500001a6e656d6573697364656675656e746540676d61696c2e636f6d00000d406b696e676d6f6f73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d001fc2ba95e343662be9aad248398097b439acd2534396228c1fbe87deb19fd5ba444715fe0e143": "0x00000000000000000000000000000000000d446562746f7665726c6f61640f54696d6f74687920436c616e63790101166d696c6f3837636c61737340676d61696c2e636f6d00000e40646562746f7665726c6f6164000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d00914612039bd0a8c2906642eb60a6fc2223771fc33c3a96e94eba9683bc50a6e2b5c70db6fbf2a": "0x000000000000000000000000000000000007506f6c6b613100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0122e96825a0068745a3099faa56c038133a62829a680ebda7b368b1659dde5237d8eb1a60efb30": "0x0000000000000000000000000000000000096c756b69636438380c44656a616e204c756b69630000186c756b69632e64656a616e383840676d61696c2e636f6d00000c404372797074446f673838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d013db7b7a6128798e6fef1631647c0defb15811a12f19e3a964322dbe0293f329824ff6d94e9805": "0x00000000000000000000000000000000000a6d636d61637374656e0e4d41524b2041205341594c45520000186d61726b2e7361796c6572313040676d61696c2e636f6d00000d404d61726b5361796c657232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0197e8e8f3672a578cb58e575019116c0f5e1d698210f9e1981eac0b1bdd419dc029ba193accf79": "0x000000000000000000000000000000000011f09fa5b04d414d4143495441f09fa5b000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0201be4d1c2cc92ee92a79760d0480aab1a940b0abab817dfcde83655e4d2c71682ce272b26ef0a": "0x040000000002000000000000000000000000000000000c4a6f73652e43727970746f0000000000000e404a30736552616661656c3132000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d022db95af4618a2a875793cd52c841f83f61d346cd7ba2f5d6219e8a6ddb951b73df0a1887c7619": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0524a63ed8afdc650df6ec6f3dbb1134df6fd1d572d4dfdbe1058fca0e7197ef8d0f3d05a720f5e": "0x040000000002000000000000000000000000000000000a446f6d694e6f646573001568747470733a2f2f646f6d696e6f6465732e696f001368656c6c6f40646f6d696e6f6465732e696f00000b40646f6d696e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0569ffc10d41f9a4c70ba55ca8bec67d63f35b1a88daf1bae874e0f8df029e9b026447c3f025917": "0x040000000002000000000000000000000000000000000a56616c6c65746563680d56616c6c65746563682041421568747470733a2f2f76616c6c65746563682e65750012696e666f4076616c6c65746563682e6575000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0579c696be22af2a8b653aaf32a9addc7d2ed4216a147eb03688ceccf00ec0970dcf2a3b01c0227": "0x0000000000000000000000000000000000134a616d696526e282bf6974636f696ee2938b0101010100000a404a504b3130383120000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0588fe1333a77f1467535f6ed22a8ec7da3d7e7529f8c68380ffda3201bcecaf2d4d86c45618d78": "0x04000000000200000000000000000000000000000000084d656c616e67650000134070616c6163653a747a636861742e6f72671a6d656c616e67652e7374616b696e6740676d61696c2e636f6d00000b406f6d676c6f6c323437000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d086b21014fcda260a50bd5098bfc45338fed742fc7a935aff9ed058c5377b20116585907f106201": "0x040100000002000000000000000000000000000000000f44656c6567614e6574776f726b73001268747470733a2f2f64656c6567612e696f1440636f736d6175743a6d61747269782e6f72671664656c6567614070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d08db4c7456c2d34dab5043bb5134f4438965a1abaf5d431109935a6f973b5b9355c6e4811688f2e": "0x00000000000000000000000000000000000f4368616f7469632042696174636800000000000010406368616f7469635f626961746368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d09bef61f6731fab549209edfbe534c3455d7fee7e340f8f8c8c78e4af36250ef8771556f5006d0d": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34340f62696e616e63655f6b736d5f3434000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d09eaf34f53d7c401480bc228ee751c1aca34061c4952efb304aa94beed8e38fd9c5e693f62c3f26": "0x040000000002000000000000000000000000000000000d63657361722063727970746f00000016636573617267653133303240676d61696c2e636f6d00000b4063657361725f676573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0a4a707f90f5d345a1351655f559e75b557ba12681698329a54cb32af516149d3022170a8e9da2e": "0x000000000000000000000000000000000012f09f98902067686f7374207c20f09faaac000016407265706c67686f73743a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0a70cfbeda907dac69dc00ee1c6849e18d9c051c8c1b1b0ceb69ae18ab0d65ef7c47a2bddee462b": "0x00000000000000000000000000000000000d4a61684a61684a61684a616800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0b071ed4c82c6f2523d37e118dbbad00009bf4c20c246c8b2b671bfb53d1fcb43d9471c932db910": "0x00000000000000000000000000000000000d52756675732054616e67656e00147777772e727566757374616e67656e2e636f6d0016727566757374616e67656e40676d61696c2e636f6d00000e4072756675735f74616e67656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0c787a6865b130b8edef9f52ba1a7f47dc10e12cb4744142161796b5b5c7e75d680bc3b81c90a2a": "0x00000000000000000000000000000000000c5366792047656e6573697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0d9546392e1385bfcb1063d22c8af6fcd6eadf0954652aabfd55276889537d52a30cf388380a503": "0x00000000000000000000000000000000000c43727970746f67656e696b001568747470733a2f2f73796e63626f6e642e636f6d000000000d4043727970746f67656e696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0dbdf366d9f3ca08ec383bdee26bce0aa83397a3b9bb7ba40991930ba4aee2d9f2d34243e89c217": "0x00000000000000000000000000000000000c43726f77642d4c6f6e6572001768747470733a2f2f6269742e6c792f3330354e635250000000000d4053616d3837313632353637000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0df4de4538d923df2a82c1d57641de66f431f758780229672378cd679da86f6eba0b433162d8003": "0x00000000000000000000000000000000000f4275726e696e67204368726f6d6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d0fb318e6895ef127add073714bbf9da81fe49db63778e918217e56c55e4f81f68e7d2e7d0e59d0e": "0x04000000000200000000000000000000000000000000114c696768746e696e6720426c6f636b7300001c406c696768746e696e67626c6f636b733a6d61747269782e6f72671b636f6e74616374406c696768746e696e67626c6f636b732e696f000011404c696768746e696e67426c6f636b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d11ea423e08f049a7a7c74e948826a6398a493f365bf1804333f3c11e86f19836d5c10586a66cd47": "0x0000000000000000000000000000000000174b7573616d6120666f72205375627374726170756e6b1c5368656c646f6e20417274696d7573204c65746f6e20446561727200000000000e40417274696d75734c65746f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d1310d7acc9400e91e434355bc1417f634ec3ee756d9dad562220624b106c1dbc756953a47784d72": "0x00000000000000000000000000000000000441756e0b4b696d206a7579656f6e00000000000b406b696d6a7931303239000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d1366f9ff3873f7d487410e002435daffbfedffa6d8618013f1e36554abbacb543030be0b7967b54": "0x00000000000000000000000000000000000b6d617472696d2e65746800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d13778bef3c90858128b1857f835ab1569c06a71e4de49df3154a9d5a5fabfa2a4f1ab1c458bc140": "0x040000000002000000000000000000000000000000000b50415354415354414b450000174070617374617374616b653a6d61747269782e6f72671570617374617374616b654070726f746f6e2e6d6500000c4070617374617374616b65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d14a0dfd491494bd5c57aa62fff146488c4f113b98906af70fc9ab8ec3684b907674631e68dbb60c": "0x0000000000000000000000000000000000054164616d06576f726c64156a6176617363726970743a616c6572742831293b156a6176617363726970743a616c6572742831293b1877656268756e7465727332323640676d61696c2e636f6d0000156a6176617363726970743a616c6572742831293b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d164f9f8d9b541902e69ac91dc2b3e54afd2d74736e7dfd95faa1e738dab066c80328980c7c9076e": "0x04010000000200000000000000000000000000000000054572696305457269630014406433636b6172643a6d61747269782e6f72670d6572316340747574612e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d17427312158ad52740a79bb171acbce71d00d7b3ba20b473c97e24210b6fc72709437cb2f255232": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d19c764f1166955be6618c285b3ffd78f73aca116933544ad022b9144c2b610e7e608e267d529060": "0x00000000000000000000000000000000000952657a69737465720747656f7267651f7777772e626568616e63652e6e65742f47656f7267656f72756439323861001947656f7267656f2e727564646b6f40676d61696c2e636f6d00000c4052657a69737465725476000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d1ae9c278f9f249deccc7facbab0732bef0a1feacbf9ba3330b0cfa4869ee8176fbe89bcb0e36e67": "0x0000000000000000000000000000000000115961727a61722020f09f87b2f09f87b200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d1c6a0460fda08feac9e892f6429cb00d736600e22204ad08382011d46fb5493ef1463d04346417a": "0x040000000002000000000000000000000000000000000d4445564741494e532e434f4d000015406465766761696e733a6d61747269782e6f7267126d61696c406465766761696e732e636f6d00001040446576656c6f7065724761696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d1dd5241c7691a93e48a9217aed06778d9f2b22fb910dc2344aea38e5746bfe344094f33de9ceb2d": "0x00000000000000000000000000000000000747656f42697400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d21419bdc819121d18b69aebec4f5274c289716bb8b61f192243046dd34040a3f3c7a8d5ae9dff7c": "0x0000000000000000000000000000000000046b6970116769726c7320737461666620636f6f6b000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d21b6f71d23b15bb1ea86f3c82538c486a25d8abca26760e57e76a01212419c7f1c8b510121fca73": "0x04000000000200000000000000000000000000000000074761746f727300001d406761746f72732e76616c696461746f723a6d61747269782e6f72671b6761746f72732e76616c696461746f7240676d61696c2e636f6d000011404761746f727356616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d22a996b9e9b22ce7c26453f69b2035a88c47342946a277c38c8f0b186edc76c70669d1cada5cf61": "0x0000000000000000000000000000000000096172676f6c61627300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d22cff40d8b99c1922a526d0737cdeb4db20761888e847735b40344277d06c13cd4c691a1ec5a45b": "0x00000000000000000000000000000000000749414d594f5500147777772e69616d796f756d757369632e636f6d184069616d796f756d757369633a6d61747269782e6f72671f69616d77686f796f757468696e6b796f7561726540676d61696c2e636f6d0000104049414d594f554f4646494349414c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2350e1f5f2021c3d2170dd5961428199af9e238cfb231d3396505876859e13d08e89e39d7b4201e": "0x040000000002000000000000000000000000000000000e4b5553414d4150524f5048455400001a406b7573616d6170726f706865743a6d61747269782e6f72671870726f706865746b7573616d6140676d61696c2e636f6d00000f404b7573616d6150726f70686574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d23775b734524690003c82da67b26395b86b46bf7528a984e5593a9305e598b18829c1a9409b8c52": "0x000000000000000000000000000000000007627562626c650000000000000c403078696e766573746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d24c3c8c823f5e00224346ed63fa298c8064eddece0712330342a50f2f152a5fafb454f009a56855": "0x0400000000030000000000000000000000000000000011416c20736369656e7469737420773366000019616c6973746169723a776562332e666f756e646174696f6e00000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d25b2b83caf5ac06d857fcac7bd9bb03551d70b9743895a98b74b06e54bdc34f1b27ab240356857d": "0x04000000000200000000000000000000000000000000065465736c610000001b7465736c612e76616c69646174696f6e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d264c3aadfa8b5d504926a875678c28947f61c56cd0a8fc948ff18e48315721fe44aa4be38489476": "0x00000000000000000000000000000000000b4172746572614c616273001768747470733a2f2f6172746572616c6162732e6f7267000000000c404172746572614c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d265ee733a44472d560fbd75b3db96ef71e33b61600e3f37a926400887daaaae380d3636949c0767": "0x0000000000000000000000000000000000064a6f736879000019406a6f7368796f726e646f7266663a6d61747269782e696f0000000f406a6f7368796f726e646f726666000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d26b218cd225b87f20b9f0216e1f1c33834df5b215115336368c549891ac1171e9710c2126753c00": "0x000000000000000000000000000000000020f09f90b2204b7573616d6120447261676f6e7320546573742057616c6c6574002068747470733a2f2f6c696e6b74722e65652f4b7573616d61647261676f6e7300186b7573616d61647261676f6e7340676d61696c2e636f6d00000e404b7573616d61447261676f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d29a5a781e83f345f618d8489511f00682df9f7d794d081cf5716b012d014846c01a162e94091d15": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2ccbf0f9e33bffd5446c059c4c78c9ead43f0694ab1eda254de55c5db245c4f8e45d95fc62def47": "0x000000000000000000000000000000000006576176657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2d52954fa3e2a736ad94ba63e2b5f27cdf2b293076d03d6fdff2c14a4613668d3f37596a78c9847": "0x00000000000000000000000000000000000e4669676d656e7420427261766f001368747470733a2f2f6669676d656e742e696f0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2f1f3681fa9bb4720112dff656489548b0a7815a06d3a59f93880ea46ee2662a6439bb431bab046": "0x04000000000200000000000000000000000000000000096c7578382e6e657400001540616d6133313333373a6d61747269782e6f72670e696e666f406c7578382e6e6574000009406c7578386e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2fad4b1e4fea8e60e04422d0a8edc33aac00d194877069ce2b3b5827b78bfe9b54124a24294d811": "0x00000000000000000000000000000000000b426974537461636b2d31001568747470733a2f2f626974737461636b2e636f6d0010626440626974737461636b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d2fd31147177f387ca4b1c51a3bf66af076145f088443de0ef7cd283e0db88a50032a1cd34f3232a": "0x0000000000000000000000000000000000064b4f4e414e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d308cb70d43f28085c2a5b5f64917252f743cfd8fec900587436c383086598aa71c93692661e5f59": "0x000000000000000000000000000000000008546865204d697400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d30c2eb96b5970eebe15890524198006c60a31bcd93a4bbf321e5ae01bc561da4e64bbbcc6e9b359": "0x00000000000000000000000000000000000e4d616e7461204e6574776f726b0e4d616e7461204e6574776f726b16687474703a2f2f6d616e74612e6e6574776f726b2f0016636f6e74616374406d616e74612e6e6574776f726b00000e406d616e74616e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d30ea9c98411c92b82ec846c0a52b9c033f68406b9a83aa780305272c0cdb723aac4bcda7595b640": "0x04000000000200000000000000000000000000000000086269672d626167000014406269672d6261673a6d61747269782e6f726715692e66617a756c6c696e4079616e6465782e7275000000001338393038393431303039393835343133353300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d32859a272c0a2203614bc16c1df6ff786504c9b02854f49a59bf5379f5e23cfefad24e77cf00152": "0x00000000000000000000000000000000000f42696e616e63655f4b534d5f32340f42696e616e63655f4b534d5f3234000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d344c21842905461f4561fb4cff90fcf5afefa2f170eabe539b19c1dd5d9d5df5dead7b26c98cf19": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d347ee113906d431bc8411a57314390768f469e76222ad677bfcddb342ad54dd76c3116593faea3a": "0x00000000000000000000000000000000000c4761627269656c566f6c7408457667656e69790000176469766f7261766f6c74393140676d61696c2e636f6d0000114038346c6870774277646e4753486833000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d37aeb944733e681aa19053750bfb4dfacdab0e8ea94e0914fbb1b0aed9450755bc38df95f13f441": "0x00000000000000000000000000000000000b416e677279204269726400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d391d9d986f924c71875965235d98860a9695076ca95b03f5c532d79f0d0b8a53fa6247090fe1505": "0x00000000000000000000000000000000000b5261696e626f774e46540016646973636f72642e67672f416743557a443537377600157261696e626f776e667440676d61696c2e636f6d00000c407261696e626f776e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3a269b657e1dfd090a4c78f16c247b4b438a25734d0479b32c196cacb25ecc95a79480dfc6cee7c": "0x04000000000200000000000000000000000000000000077368616d6230000013407368616d62303a6d61747269782e6f726713722e7261616a657940676d61696c2e636f6d00000940307368616d6230000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3b4bb9b7ce70c8d4e3711ff0fdcfc953c9ff93355ed42146e442c256b6010ddd5b5fe0ee8b8ac1c": "0x0800000000020100000002000000000000000000000000000000000f43727970746f537461636b696e6700001b4063727970746f737461636b696e673a6d61747269782e6f72672176616c696461746f724063727970746f737461636b696e672e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3c431103710ce4ece8ab75ebb8a44502bc0a55f439d421f8d59372b5d9bba22e31b770e0317c236": "0x0000000000000000000000000000000000154f7263686964784d616368696e61202844414f2900126f7263686964786d616368696e612e696f0000000010406f7263686964786d616368696e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3d814d7f08cf77d28b199c10b2b388ce480499767f81d871cd1bc381f7106d810f69183ff0bb600": "0x0000000000000000000000000000000000097073796368656d79097073796368656d791568747470733a2f2f7073796368656d792e756b2f0011696e666f407073796368656d792e756b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3ede878555e1dcebebf5aa73bf19935376f19460dacf00bf0dcd021ca37d6a2284cc6347dfbb13b": "0x04000000000200000000000000000000000000000000115354415244555354205354414b494e4700001d4073746172647573742d7374616b696e673a6d61747269782e6f726719696e666f4073746172647573747374616b696e672e636f6d0000114053746172647573745374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d3f55d2a3bdb036484de146db749ad6f982921078e8dec36432724c2e58ee2523018794d66b4b33e": "0x00000000000000000000000000000000000f646f7473616d612067726565656700000017646f7473616d612e6772656740676d61696c2e636f6d00000d40637261696777696c6c3733000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4033833f41b67add80d0b0a6fe11c8257ab574e3379491172cf2e6398fdc12413ff1e8cb0dca602": "0x00000000000000000000000000000000000746524f444f4c1044414e49454c20564143554cc38d4b00001137766163613740676d61696c2e636f6d00000840377661636137000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d414938ade2ffd6ad42bdf23d39282dc625dad8b2ffc0b8682b15b2fe16386a8b7d7670ef49c1034": "0x00000000000000000000000000000000000b64616e69656c74616e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d423ef3f47b52bf7c48a7d8c907eda4ec2ea41d9bc09584ef7bdf9771212672f0fc065a28eb5d809": "0x00000000000000000000000000000000000e50756e6b205661756c7420233400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d426b9c30d551db958a7854669ff1e281e737aae0f84d013eec326ab95a273c0c1632d009f02361b": "0x00000000000000000000000000000000001241646d6972616c204869726e77757273740000000000000f4061646d5f6869726e7775727374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d42a0215208f31fdb6ccd54659f4b9ffd747e6ba2dbebfd5d2a64ad3ab8dcf6b647965c20fde4b26": "0x000000000000000000000000000000000008416264204e46540e416264616c6c6168204661697a00001b616264616c6c616864657665736f756c40676d61696c2e636f6d000008404162644e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4351e7307bc37c8d82318297ca7af51ac2546ea6bd24acca272e1627db952e2ca35df527a3cf257": "0x0401000000020000000000000000000000000000000007416e6e76616c00001340616e6e76616c3a6d61747269782e6f726714616d3539333137383640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d435a9777e7ecc393c5862ed65c524b7bb3564776a81904218f44f3d7c35162a608e39dbadbcda05": "0x00000000000000000000000000000000000f4e6174506f6c6b6177616c6c6574134e6f7220536166696e617a20417a726169650000166e73612e70796e7574323840676d61696c2e636f6d00000b405379615f50794e6174000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d452102e2cdc7c6d0615a0ee03c20ebb5fa2073580dbeb208997a4cfec6d0c45eb6aacae346e7341": "0x000000000000000000000000000000000010546865204b696c74204d61737465720000000000000f405468654b696c744d6173746572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d454f28df46217c3a413aba1432d6c746556ce43688ff333612f6abe674cd018143a0f819f9ae011": "0x000000000000000000000000000000000010556e646572646f6741636164656d790000000000000f40556e646572646f674163646d79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4615d4a4674bc89b80441d3a9d744772eef9c1d6f9babafdc2cbd1b641134372accd4cba23b602a": "0x0400000000020000000000000000000000000000000019464353206b7573616d61207374617368206163636f756e741946696e6f6120436f6e73656e7375732053657276696365731668747470733a2f2f7777772e66696e6f612e696f2f001b636f6e7461637440636f6e73656e7375732e66696e6f612e696f00000a4046696e6f615f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d483e0981fcc955908f241657b6fafb70ad61e1d2ca48854400ac5499472047e2313837f22dbdb34": "0x00000000000000000000000000000000000559657469125969c49f697420c4b0c3a7696e6465726500001879696769746963696e6465726540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4860cb6eb01ff314c5586b7da01ac92974de944023354a80c57d22758be9e56ccc8fd3fce706556": "0x000000000000000000000000000000000005736562691253656261737469616e205265796e6172640000197461737465736c696b6570756e6b40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d498e8af62b9b81f48cd9f664b904e5fa2943cb433f83c4747aa5503b65db20c3323ef45e3533c52": "0x040000000002000000000000000000000000000000000b4d6178426f6f6b50726f000017406d6178626f6f6b70726f3a6d61747269782e6f7267156d61786a6c7565646b6540676d61696c2e636f6d00000c404d6178426f6f6b50726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4bbaded83232e480a7ddf52460667c3f7adff6e3940814273085004a1ea440514c031b04273840d": "0x00000000000000000000000000000000000c427573696e6573736d616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4c23f7b6dead31a72f6d064648a26d887389b6693722008d4caf3806559b92fb1ee8dfa0a45d033": "0x00000000000000000000000000000000001c63796265726f6d616e6f76202f2f2f20686f775f746f5f6e6f6465001968747470733a2f2f742e6d652f686f775f746f5f6e6f64650000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4ed4dd340a2cebbbc486ed2f394da6e6b58b130687b48d3d19f756ba6d0655d37bf58ff0f59f974": "0x04010000000200000000000000000000000000000000124164616d5f436c61795f53746565626572124164616d20436c6179205374656562657200154061737465656265723a6d61747269782e6f7267176164616d2e7374656562657240676d61696c2e636f6d00000e406164616d7374656562657231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4efb6a7c466273b168cf2d861c66db1a3fbaf0ecf25df661c7d55787615a390763518e98de0b747": "0x00000000000000000000000000000000000e426565667920426f76696e65730000000000000e404265656679426f76696e6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d4f3cca21e8eadd0dc3b9a6dced09d3d392ba7a559c5505304cb3bec0168909d1ef3ddea59bc3f40": "0x000000000000000000000000000000000008436173744f6f62064b656d6574010940436173744f6f620100000940436173744f6f62000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d509c5c59195b1ec5c3739d60301126756a7510e34f9d656d4435cd4fe64bbd001f1f3473bc9c333": "0x04000000000200000000000000000000000000000000055a656b65000012407a6d6f73743a6d61747269782e6f7267137a2e6d6f73746f7640676d61696c2e636f6d00000c405a656b654d6f73746f76000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d513a4d26b535221784eec0cca663bb2db534e9f62df416453ba125d1b7164fbd0e57cd3e8e97b16": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d53d5d90d84924fe4677245c32c396fb92974ba9bf94b8fd84a6ac489a98bbde7c24ac48b1105160": "0x040000000002000000000000000000000000000000000b5374616b656177656562000017407374616b6561776565623a6d61747269782e6f7267157374616b65617765656240676d61696c2e636f6d00000c407374616b656177656562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d55375322bd7510232888663bc260532b200b41cc9ef2fc128b68e8d533e3a7a948f9ac39f50ee0e": "0x0000000000000000000000000000000000104c6f776b6579204c75636369616e6f194e69636f6cc3a173204c756369616e6f20546172676973650f7777772e636176697065782e6d781b406c6f776b65796c75636369616e6f3a6d61747269782e6f7267196e69636f6c75636369616e6f323540676d61696c2e636f6d000010404c6f776b65794c75636369616e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5591ec3b4ca405c90dae70c96bd25cc1a05708607846a56409ac0f5583da69993dbe51e9c745e71": "0x000000000000000000000000000000000006526f73696500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d55aed6a285552b8eea608b429d85b4dc655283ea9eab1228082aef03aeac6cdae6f54490cd08d1e": "0x00000000000000000000000000000000000e486f6e6579636f6d6220322e3000001b4064726970736c6f776d6f74696f6e3a6d61747269782e6f72671e64726970736c6f776d6f74696f6e4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d574ca61fe1791bf8286f065125f13ef660e4862d9c37ba16bf863ebb5190027c011da51d818d020": "0x00000000000000000000000000000000000a4c61204261737572611d74726173682067617262616765206e6f6e73656e7365207472697065000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d577f5c3d9252401dcda723fe1d35644330dd76fb23e8a054ea173de8662658abd8c01b92215496c": "0x00000000000000000000000000000000000c43727970746f70617468200f4865726d616e6e2054726f67657213436861696e6578706c61696e65642e636f6d0011667269736972406b75666e65742e61740000104074726f6765725f6865726d616e6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d58baa61c0bbca6b0294d53df32ffcce69720bff43ef091c4bb98746625ccd872c83020b6e60b92b": "0x0000000000000000000000000000000000094b534d5f6b696e67094b534d5f6b696e67000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5a0db274f5df4e104d8d6a7936466d0f9d111e89f97ba11695c0525bb136b68d9924299df236638": "0x04010000000100f0373a0002000000000000000000000000000000000000000000000000000011506f6c6b61646f74204dc3a97869636f11506f6c6b61646f74204dc3a97869636f0000187465616d40706f6c6b61646f746d657869636f2e636f6d00001140506f6c6b61646f744d657869636f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5b36f8aabe01a6052dac5497bbdd42583d07aa46102790d54aacdcbfac8877189e3b609117a2915": "0x040000000002000000000000000000000000000000000453656200001b4073656261737469616e3a776562332e666f756e646174696f6e1a73656261737469616e40776562332e666f756e646174696f6e000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5ce1fd9020fbeba60b791f8467410a5ce2e880cc222933ad50705664917bc9d190a52596b987121": "0x040000000002000000000000000000000000000000001146494c494752414e2d5354414b494e4700001a40746f6d61732e7374616b696e673a6d61747269782e6f72671e746f6d61732e616e646572736f6e2e3230303440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5dc001e58cc1a2dc0e9999cf8e2137f6aa333a591dd91aae131fc563931ab47986d637283c7ed29": "0x00000000000000000000000000000000000f566976656b2773204b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d5e66d23eb784c1150fa056fe8636d5041e3a460e63839603087bf789ce60514f00bb2473b728e4b": "0x000000000000000000000000000000000014506f6c6b61646f74202d2050432047616d65720000001973657267696f2e6f746176696f4069636c6f75642e636f6d00000f4061706f6c6c6f74686562756c6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d609065d758b7e8b9c8427ec1489648401391189a706384709fb9e657de816f41564e5b2cc9dcd3d": "0x000000000000000000000000000000000021536565722050726f6772616d204e4654204172746973742053686f776361736501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d60ed63674d67c971018f7a7cfcea5146f42a9f7514fd5873e7c0d523e8a244bc0662bd1d98e7a59": "0x0000000000000000000000000000000000096d666572686f646c096d666572686f646c00000000000a406d666572686f646c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d618b703260a53b98a5c48370385dbc1ceaddee2196bd1ea5e5617d5d6b8149a17d6dd4adaad8667": "0x000000000000000000000000000000000009666172756b30353813c3b66d657220666172756b206172736c616e00001a666172756b6172736c616e353840686f746d61696c2e636f6d000010406f666172756b6172736c616e3538000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6397f35e3bd3d7aa4da8ad5b663d506866eb429c70a606e73d6b78aaf04279691ae408213e6e206": "0x00000000000000000000000000000000000774736f6d697300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d65a76a86282a40a861cb62f476c70b7b610b759887b412fe5ccaf41056e76cb9702b6683309e329": "0x000000000000000000000000000000000008547269756d706800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6672f8dabe56cfafc605754e335954ecf919857633f415d774d4d12712e213cceca16852f12d34d": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6924a2febf0176cec55dae9d39f6758a5c07537eb7c64be8bb7417347bff0473ada40639784e33e": "0x040100000002000000000000000000000000000000001053756e7368696e654175746f732d5300001f4073756e7368696e656175746f736e6f6465733a6d61747269782e6f72671c73756e7368696e656175746f73696e666f40676d61696c2e636f6d0000114053756e7368696e655f4175746f735f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d696aaec0094a128f47313bfedaddff9c793fb87f947bc9444658705a5a1060cc6314f5a1986a90c": "0x00000000000000000000000000000000000a4b61636b766f67656c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d69a25a402c5611e0c803a3771c8a186638032d9b7a49c853dd6277eaf7a2360dce82c0ec79a5755": "0x0000000000000000000000000000000000064e6f6a61580017687474703a2f2f6e6f6a61782e74696c64612e77732f00156e6f6a6178737765657440676d61696c2e636f6d000008406e6f6a615f78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6cf502341600d556c519d42e162875d1d3c3c77e651f508aa6b0acb837c742d2708946f5927af2c": "0x0000000000000000000000000000000000085a45524f2e494f001068747470733a2f2f7a65726f2e696f000b6871407a65726f2e696f00000b407a65726f646f74696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6e8d01b506d9006a41e9f37a05aaac44e5eb8370e4bbffc6e80041574668571e5eaef0483ff7b09": "0x040000000002000000000000000000000000000000000b42617274616c616d65770000174062617274616c616d65773a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6f4a0256fc9f716e0edb40f22c7d63c19a54e07562c062b1eb09447d51f5cf6ab734ada60793a44": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d6fb5b84c25006bdc63c43b6438923bccf2d45e4c2f40cdd0487f6fa2642850b7a01df18dd27825f": "0x000000000000000000000000000000000004706f79024100000000000b40706f797369616e3033000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d70a505217b108b4ac17e441d94f220689361662feeadf1c5c14876375a72a392dd67f276e538706": "0x0000000000000000000000000000000000086269676d66657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d722c1e7fc34a853ec007f25ffe88b5e993645de184a0c7c32050eb68b8f47f05e9fa06844ac0f40": "0x0000000000000000000000000000000000174665656c20746865204c69666520596f75204c697665001e68747470733a2f2f74686174676f6f646f6c6665656c696e2e636f6d2f001b74686174676f6f646f6c6665656c696e40676d61696c2e636f6d0000114054686174476f6f646f6c4665656c6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d73fd3a82863eee47ee233c6f97eaf8689fe85222c2e2b701c2e654d4c8dacb45fcc574f6f438e26": "0x0000000000000000000000000000000000095368726f6f6d697a01117777772e7368726f6f6d697a2e636f6d01127368726f6f6d697a6e667440706d2e6d6500000d407368726f6f6d697a6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7553e6d8d0f99e5f66b0ab84c0ad724138f81ce24ed1fa17897d6e75a6356c4115cf44d09e19e48": "0x00000000000000000000000000000000000776766172646906566164696d1b68747470733a2f2f7777772e67726963656e6b6f762e636f6d2f0016766164696d6b61746f323540676d61696c2e636f6d0000094076766172726469000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7685dfbd65585fb86bdd82d59404ffe1d6120c6358c14c1bef69a013fa91771c2594f6fa310187e": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000761726b7061721141726b61646979205061726f6e79616e1a68747470733a2f2f6769746875622e636f6d2f61726b7061720000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d78969895bcedfdf5a3a1533b0a9025b41803b18e26fdbc2d218a87b27b1c31a1fae6d8098b3e457": "0x00000000000000000000000000000000000a72616a61746e616e6f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d78ad17ef6e9b32a3c1defc518e6b625f5a9efd940404a1672285b33a1dcbb88b50209b76b79a74c": "0x0000000000000000000000000000000000065069616e6f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d78b6631bad4877c52d49f4667f10ded3c5d8ada0c31d7f397ae650a30cd8ad7663b8f3bd7bfc355": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d78c16b89566f655563544356fb79169a553ad9bd500e2cc88159f56ece7c1fb8015872c68b0e522": "0x000000000000000000000000000000000011536572686969204d697368757374696e00000011666e6174756b40676d61696c2e636f6d00000840666e6174756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7a964305986fe6726b41bc4436bb3f47662366696bd1233bde29446c80949e3b92a435146462436": "0x00000000000000000000000000000000000a4b756d6163636869200000000000000e404b756d61636368695f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7ae9fa2edfac512d4da8f91c6a4e472fbebceb3a995c6b3e6de9c452f9d72b57a56b28be0f0b323": "0x000000000000000000000000000000000006486f72736100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7b596e66afccd2bd89ea70e822e338b7519379e4a4685595da674fd167b7bd12dbfd10c9bc2b50e": "0x00000000000000000000000000000000000d44415245444556494c337837000000134372797970746f7040676d61696c2e636f6d00000e4064617265646576696c337837000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7dd8684dd09ce27e8799eea1483bb11f30100b2a239f6fbb5098c5723dcd0d6bb4987abcf443642": "0x00000000000000000000000000000000000550756e6b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7e6c03d3b7013c492818e6a3df21899a1f1f3f2d3573e4c978bc23c05317715e288434396eeb155": "0x000000000000000000000000000000000006656452756d0365642168747470733a2f2f7777772e696e7374616772616d2e636f6d2f65643872756d001165643872756d40676d61696c2e636f6d0000084065643872756d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7ef9a5ad88206463e968701c6259a89d5d0f6c7fba46ad0694cc8c66f4b21d4e174744376039402": "0x0000000000000000000000000000000000107472616e747579656e626e30333034107472616e747579656e626e3033303401010100000c40676f6f676c6562657374000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d7efccf788fb1a6528d50241999da5b300f01f3004a67a25a11854608f1f437ab86ed2e115243a43": "0x00000000000000000000000000000000000a4b7261746973746f7300196b72617469737430732e756e6976657273616c2e7061676500184b72617469737430736e66747340676d61696c2e636f6d00000b406b7261746973743073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d807711226d31b907054f0231a7bb2c4d8e1b64b4b2a77e7216e5d225552d00235201b1889dc0e5d": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f34310f62696e616e63655f6b736d5f3431000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d809a68f462b1287c285c81a263217572329f43c38dcee6f67b0cd9f25bae69e895080f546f6ba31": "0x0000000000000000000000000000000000076a6178646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8120c83cf91181312e6a9ab0eee280b366c26e0d43e7826406e7c9c2058ba0f8f31efede72c8653": "0x00000000000000000000000000000000000c626f6f6b77617272696f721f5468652043726561746f72206f66204c6962726172792047656e657369731368747470733a2f2f6c696267656e2e66756e0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d82897aac9ed9c653a68259c764c7a1aca790853256861dfb65ea084c82d10d40f8eb1dffe45e77b": "0x00000000000000000000000000000000000c7375706572737072697465000000187a6d616b696e616f6b73616e6140676d61696c2e636f6d00000f4073757065727370726974653134000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d84deb4759f2e2e9f6a7fa830da55dde09b411ff877ed0ee8fd1ceb2009067ab5bc0ffdc54af4065": "0x0400000000020000000000000000000000000000000006416e6b616e00001140616e6b616e3a7061726974792e696f10616e6b616e407061726974792e696f000008405f616e6b346e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d851abfc5265e96b5015c74ff78d632ca10ecfc0d0fa9fa2009cb4e644d73f6518260f5cb9c34633": "0x00000000000000000000000000000000000947723379686f6f64010b343434657665722e6361010100000d40626c617369616e77616c6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d86d654f0eadeda8ee73cfdef6c4ba205b9b7afadb214de4510b3fdd98d5b7284e09b350e277cf2c": "0x00000000000000000000000000000000000b6672616e6b7977696c6400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d87333d9765befa4e643e4515fa656d6d830c088ec251ab76ba6cebd85be7e7d6362eafff654e222": "0x040000000002000000000000000000000000000000000e534f4e59412d5354414b494e4700001840706572656368656e6b6f733a6d61747269782e6f726716706572656368656e6b6f7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d87f50ab0b5f9643ec5909db1fe8581fbe80eaf39b4577c12a99d5abc87131bc3d4363f623412f42": "0x04000000000200000000000000000000000000000000097363686d6961747a000000167363686d69747a4064632d7363686d69747a2e6465000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d88c6fec2fd9c900b8687aa6d3e0c8659930f6d8f8066260b6633445304d2a3e657a6edc2e42a849": "0x0000000000000000000000000000000000055468656f00157777772e7468656f6a616d696c6c65722e636f6d000000000e407468656f6a616d696c6c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d894f8bb10a8b63f0a06fa6798320860c09dd8b4880aef12921f0d1c03b90d5426aa94a8192ada3f": "0x040000000002000000000000000000000000000000000b4b616f7320496e204241000000166a6f736562656c6f73736940676d61696c2e636f6d00000e40706570656172617563616e6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8a98d8378f930af20836789ec1d218962edb199c7d65158e0edbe4e5ce0db190f6993b64d4aec42": "0x000000000000000000000000000000000006494f594f49011e68747470733a2f2f74727973686f7774696d652e636f6d2f494f594f49010100000c40696f796f69696f616f69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8aa498f3b53b82dc203ae26c4e67f3dfd9c338f9f5f605abe950945d6077c23db6345041818e73b": "0x000000000000000000000000000000000009417572656c697573104d617263757320417572656c69757300001c417572656c6975735f4e46544070726f746f6e6d61696c2e636f6d00000e40417572656c6975735f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8c344e11655410c54fda5a0e241e5497283afebd81b53f6a0235abf62a9bd39594be3f42d291e7f": "0x0400000000020000000000000000000000000000000008537461747574650000001b73746174757465636f72704070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8cb784790741db174dcae90cfd7a3fc9a75e4cc21bd550113b44888ffbf67741c8081c6d121d306": "0x0000000000000000000000000000000000094d69746368336c6c0000000000000d406d69746368336c6c5f5f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8cc1e377a948511bed8e57427b9ba0d58dfeec1e37715621b7216c6953afbfdcfe181c2f6a2ca6e": "0x0000000000000000000000000000000000094372616967657273001a687474703a2f2f6c696e6b74722e65652f6372616967657273001863727970746f6172746e66747340676d61696c2e636f6d000010404372616967536d69746841727431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8cf92a45f6a096b5401c2b936283c6674f9f30be30276a706373c0bd7b7a8dd511e1ceaf4ce1932": "0x00000000000000000000000000000000000c6b7573616d615f6b65726d0dd09ad0b5d180d0bcd0b8d18201010100000d406b7573616d615f6b65726d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d8fccba6b760676a5a98b9e09c1d2e5a120a1be952593d0d542ceb6f6843133f6d64c674b736ae55": "0x00000000000000000000000000000000000c4b7573616d61736872656500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d906663357299afc882e4951811038cfeb6e891c2c574e88d2d950aaf23d6cea7b030e17ab9c6569": "0x04000000000200000000000000000000000000000000094c6974656e747279194c6974656e74727920466f756e646174696f6e204c74642e1a68747470733a2f2f7777772e6c6974656e7472792e636f6d2f164068656177656e3131303a6d61747269782e6f726712696e666f406c6974656e7472792e636f6d00000a406c6974656e747279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d942aa586baec2e388c16bc644b9877b22f0fc11c18bf143398267feb48c3ac9cc110440e9a5d873": "0x00000000000000000000000000000000000953657661546f7267074d616b73696d010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d946b6c106a956cc7cfa423244c9a3bf66c12432dd93d3806d184e01b58e3eb75b4b19b26bf61a75": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d94bcf5481a16dedec03e526f073255828e91779339158fc05b68430ebf66df109820b79c1da4053": "0x00000000000000000000000000000000001d5370656e63657220486172726973207c20426173696e204c6f6769780f5370656e63657220486172726973001540746967657274776f3a6d61747269782e6f7267197370656e636572626840626173696e6c6f6769782e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d954df8fd662305d365572e4f9d2762cc1c4312399485b3b3bbfe113fe2b5a12a73f9ffb5b9e694b": "0x0000000000000000000000000000000000066d696c6f7300000000000011404d696c6f73436f7374616e74696e69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d97b21772959b4b83870abfd18505f673c1808b61dd0d7067a810a9719c2ddee18f9b879752f4c50": "0x040000000002000000000000000000000000000000000a53746173526f766572000016406b61346f6b313333313a6d61747269782e6f72671873746173726f7665723133333140676d61696c2e636f6d000000001373746173726f76657231333331233632363300", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d994ff06d05e1d5898989f74514aeaf57d4f41069770242a83d619c9ae5d46cc05b85136edd53776": "0x0400000000020000000000000000000000000000000010426c6f636b636861696e2053696465000000196172636869656772616e6437373740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9984fac3c81ec12248ba6a719705efdd003caab9383ce61c9bba7e7bd914a96be918a4ab12d7251": "0x0000000000000000000000000000000000087479726f6e657a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9aa60f59932d95d362c1f2bbb4871a52be7e6f8354082c4d83f54fd249689fc820be7e5c672cc69": "0x040100000002000000000000000000000000000000000943484c4c2e4f4e450d4b726973746572204178656c1568747470733a2f2f7777772e63686c6c2e6f6e6517406368696c6c66696c74723a6d61747269782e6f726714696e666f406368696c6c66696c74722e636f6d00000c406368696c6c66696c7472000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9aacd1a800a357c2822e6207970510d1c0d65af57522c8832c810f86d512a09f960efd78f570110": "0x00000000000000000000000000000000000a506f6c6b61546f747301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9c21406bc86d487b46a62619c41606297ea55f07d4c2ff4e3abec149e1f9fe241cf6ea0b12c7a15": "0x04010000000100fc8d0e8000000000000000000000000000000000000000000000000000000018475245474f52592054484520494c4c554d494e41544f52064c554d2d411668747470733a2f2f7777772e6c756d2d612e636f6d1540677265676f72795f3a6d61747269782e6f72670f696e666f406c756d2d612e636f6d00001040464c41545f455f415f525f545f48000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9ce7cfdde49af449a9495310a1c0626605d804f4fff2446ca5a6dad3d2372ded3b1a049ee71df6d": "0x00000000000000000000000000000000000b546865204c2046756e64000000000000104054686547616c6c65727931313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9d39ccedf4c2000b463dd5343005043ca12d524c7dd5d64ca6dfc3ad830665130a214da689d5078": "0x040000000002000000000000000000000000000000000b4d616462757374617a7a0000000e616c696461646140626b2e7275000011406976616e736d69726e6f7670697273000d2e6976616e736d69726e6f7600", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9e7b18acf37afc5109ac2869eb1def6cc0654c320d9aeda6a800ae69b1d90efe0ad42850616e614": "0x000000000000000000000000000000000009536c6f77726973650000000000000a40736c6f775f646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9f5cf21929f1a4c4acd55e7e637540708f860361c1ec0c092cf8169b300d9a4bdeb58faa8a52053": "0x0000000000000000000000000000000000184269726473206f66204368616f73206f6666696369616c1d4e6f7420616666696c69617465642077697468204368616f7344414f00000000000d406368616f735f6269726473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714d9f5e42a995ae306029b3f206024f24646fac96836b670bb999eac5b44eda65ab262ccc0a4a6b542": "0x00000000000000000000000000000000000962656d74696b7275000000000000104062656d74696b72755f6d69746368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da1658728cb5fb3c82299cce0c148ac684639df678476effcae36c4eb8cf15592c511512a857e745": "0x040000000002000000000000000000000000000000000d44696f6e79737573f09f8d87001a68747470733a2f2f64696f6e797375732e6e6574776f726b2f1f4064696f6e797375732e76616c696461746f723a6d61747269782e6f72671468694064696f6e797375732e6e6574776f726b00000f4044696f6e7973757356616c6964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da1bc1fea1f074aac68a07f4359b73788575a33635beb03280ef3c52062d5bd01f825e2f463e0b4c": "0x00000000000000000000000000000000000e41786f4b656c2053747564696f001e687474703a2f2f61786f6b656c73747564696f2e74696c64612e77732f001761786f6b656c73747564696f40676d61696c2e636f6d00000f4061786f6b656c5f73747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da23f4f6f4d9e6bc96140a201be6f41e63c5b3bf6b02f67da3f232c6715397302494f894f964ac78": "0x040500000002000000000000000000000000000000001156696e6365436f72736963615f4b534d1856696e63656e74204469204769616d626174746973746100001076696e6365407061726974792e696f0000114056696e63656e7444694769616d6231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da40d28d53abbfcf16f9415c34da11ca5a35f3f18627af4ef312d90777ed086ea20e364b11656921": "0x00000000000000000000000000000000000647454e47450667656e676500124067656e67653a6d61747269782e6f72671667656e67656b7573616d6140676d61696c2e636f6d00000d4067656e67656b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da4eb90d88caf07f5c2341c52e242c57f00d78b9f40cb486714dee3e10bcaefba283e1e4df0e5f75": "0x00000000000000000000000000000000000f4465736b746f702d4b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da569c826c2fd86b76739ac0320c03658b64366855bd6ab037488fb23fa0d183f53b989106e25a2d": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da7ade542996fb4cb6631de2987e1fa759f6aef3e72550a528749c4c52cf38710602bfbac9af7305": "0x0000000000000000000000000000000000064d2d455343174d696775656c20416e67656c20457363616d696c6c6100001773657669796f6e31303740686f746d61696c2e636f6d00000e4044657361726f6c6c61646f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714da9b32cffd9fd809beef167bab8457606e5de5733ed8762eb7d0aea76041e7cdc691a21b95e67013": "0x00000000000000000000000000000000000654696e6e6905524d524b00000000000f4054696e6e693839313936333138000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714daa1ed579e87685ab8f0171b9d40e58e80585aa9997bab2ae23d35557b5442824ad73deba484e36d": "0x000000000000000000000000000000000009597567656e65383900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dac410871d142aa90a53d0ced11a23bb33da1a2fa77b236ad1de8272b61bef478771f5bdd344fc06": "0x00000000000000000000000000000000000e43797068657220526561646572000000186379706865722e72656164657240676d61696c2e636f6d00000f406379706865725f726561646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dae3f8d26516ccd80224ef86df87db7c4c36488f6f2c49f554c73fcf4a1572b0b1dcd79155784740": "0x00000000000000000000000000000000000e456c656e655f5473756b696b6f002168747470733a2f2f7777772e696e7374616772616d2e636f6d2f456c656e655f000000000b405473756b696b6f456c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714daef22360126f077784ee8a444a606185328b11e83357bfa6541dde1e05b95e69879b1b716f7a247": "0x0000000000000000000000000000000000095375626461696c79001468747470733a2f2f7375626461696c792e696f000000000d407375626461696c795f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714daf69a211b7a8ea508a23d4b915d29be5d2aa20f36649e004c6ee8df393064edad697934281bd51f": "0x040000000002000000000000000000000000000000000a6c75636173796f6461000016406c75636173796f64613a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dafe1c73fef256963e7af6741991062099fd8cf649f36396d77271db62ee03370c1e53ff12cb2642": "0x0400000000020000000000000000000000000000000005454b415400001440655f6b5f615f743a6d61747269782e6f7267146b7573616d612d65314070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db13904a8fd920d916f2af47aa45d69386e441ad73b7ec1ba5065bdd787f7ab7b2d8eb428c5b6967": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db2524c5144787d7780dfaafebd37476b57e181c3636209591f2df438004ae02ef2d759092832870": "0x0000000000000000000000000000000000094561727468415254115061766c6f20504f5a485944414945560000137061756c646a656440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db2d56e31fe5a23ba827364a1e01162f7f1647ff0fc967a83f1ef1d8c8da59414d312de7514c1678": "0x04040000000100902f50090000000000000000000000000000000000000000000000000000000965746853706c69740000000000000a406e7468657269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db3176a845829b906e0417d9e62b75535a2c606b13a74bdde967684d6971d58cd0cad8986e3b3044": "0x0000000000000000000000000000000000075374616b6558001668747470733a2f2f7777772e7374616b65782e6368000f696e666f407374616b65782e6368000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db4738c957436cf21e9c00f9c0788391f63681ed1addd7984e37aa04a96cb887beac70eda9b4766d": "0x00000000000000000000000000000000000c43727970746f44616464790000000000000d4043727970746f4461446431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db51125ce2e8c4560c2017a4f115c013d899b494c955a7ec4cc9786a3997f1823baacc213896a35a": "0x000000000000000000000000000000000011506172616c6c656c2046696e616e6365000c706172616c6c656c2e6669000000001f68747470733a2f2f747769747465722e636f6d2f506172616c6c656c4669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db564ac3abd62540844152eccf08725bea8ce898d6fc5362ff2d0bc9dfc21ed15fd138438d160622": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000164b7573616d61204865746176616c69646174696f6e002068747470733a2f2f7777772e6865746176616c69646174696f6e2e636f6d2f1540686574616972696f3a6d61747269782e6f72671a4865746169726f6931384070726f746f6e6d61696c2e636f6d00000b404865746169726f6934000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db70f2601c34332880a135db57d4d35273d9a4f661d3dad8f153a1b5bad478f9b0e5223657aabc0b": "0x040000000002000000000000000000000000000000000d574f4c465f5354414b494e470000184070657465726b6576696e733a6d61747269782e6f72671b70657465726b6576696e732e3139393940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714db89725fce7ce8f3bc61b0519cbf119fe5dd6b22fdab9032f2af003c27b432e081cca41eb8621c3c": "0x0000000000000000000000000000000000154e4654204162737472616374205061696e74657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dbc1bb2de0590492cca2a0719fad006090aad6536ca8b7d8c527589be01b0012564dbdd36d9a4923": "0x04000000000200000000000000000000000000000000066c6f626973000012406c6f6269733a6d61747269782e6f72670e6c756973406f6269732e646576000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dbcec1429555e3577a5c2500b0c12120ca4683d8b1046a98d324b1cc45461c2bf69ee7e2f4708207": "0x00000000000000000000000000000000000b6a6f736870656c6b6579000f6a6f736870656c6b65792e636f6d000000000c406a6f736870656c6b6579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dbf0bac829c264486eea07ae188cf16042168843c5c29299196e610dfda7d9efd3f0421119629a61": "0x00000000000000000000000000000000000d56616c6565765f52696e61740d56616c6565762052696e61740000127672722e69646f40676d61696c2e636f6d00000e4052696e617456616c65657637000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc22c730a7ef5a54488b87e574eee2f9b8e7810eb3567edffc303c4f9c76946da200ce429b444d59": "0x040000000002000000000000000000000000000000000a4d617843726970746f000000166d617863726970746f6f6b40676d61696c2e636f6d00000c406d61785f63726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc5cbe2cf41cf8f57a66844d9bd974ceeab7c9da2b3870bf98bb2179a0d385d644c5f73593aa7f16": "0x00000000000000000000000000000000001b5a57485f46616d696c795f54727573746c6573735f5472757374000000157a61636b77696c64654069636c6f75642e636f6d00000d407a61636b68616e6466616d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc6abb1030271996440465c2ff462a9545455781afd16c1d7f650935bbb34f696ebe205c14baa307": "0x00000000000000000000000000000000000c417373657420546f6b656e0e4b727970746f204c6174696e61127777772e6173736574746f6b656e2e696f0013696e666f406173736574746f6b656e2e696f00000c406173736574746f6b656e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc70be881faf5789f2de250cbcc6a3881f004a862ae661a9794596c3ebdeb829a131989617f49e76": "0x00000000000000000000000000000000000f4973616163204368616f7344414f00000014616d656e6c6f39406f75746c6f6f6b2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc78925c32b0b66c0aba8ac93a0d8898810acf42a8b311fa20407dc181383901c240b041b34bf015": "0x000000000000000000000000000000000011506f6c6b61646f7442616c65617265730000001b706f6c6b61646f7462616c656172657340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc795a6b3289958b5678de8caf6f90c813fe5addb356e8154ea5e52463886d566cc8deaa0907e761": "0x00000000000000000000000000000000001543616f74696320506978656c2053747564696f73124a756e65204361726c204d616c61706974147777772e63616f746963706978656c2e636f6d0018636f6e746163744063616f746963706978656c2e636f6d00000d4043616f746963506978656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc90c8e009d95f3e24d573f4df9151235e457956765e6446cf33077033bbca48d8d5c6c9a1d7fd33": "0x000000000000000000000000000000000010524d524b20312e30204d696e746572011168747470733a2f2f726d726b2e6170700111636f6e7461637440726d726b2e61707000000940726d726b617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dc97a320776a16d2f495309d22f770f6e7335dce5ba63efbe4cf7b429a83f4b7761f1c7f45a8d86a": "0x000000000000000000000000000000000009416c20446967697409416c20446967697400000000000a40416c5f44696a6974000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dcacdfdedda85ff952e73898bf4601f9c9a7fa052de0cc313b159dd368d458f4cb0341eedcd6d818": "0x040100000002000000000000000000000000000000000f436f696e6261736520436c6f75640e436f696e6261736520496e632e1f68747470733a2f2f7777772e636f696e626173652e636f6d2f636c6f7564001b636c6f75642d737570706f727440636f696e626173652e636f6d00000f40436f696e62617365436c6f7564000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dcbb9839570e5bf3e6587e304800d0184b470738807816bc1eb4b2a045521c2cb60bb15952866236": "0x0401000000020000000000000000000000000000000005566956690000001c766976697472616e313131314070726f746f6e6d61696c2e636f6d00000e40766976697472616e31313131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dcd3c1c3ae6b80e00c082ad8b544e64abc3af5764db1b455bf32231202ba50e5d0fad1794df7c905": "0x0000000000000000000000000000000000074b534d20453200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dcd8cda22151133450ac31b94e7738d9d7a0cf56f4333a3344218e1ae2dd80a6e0b676fee8049305": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dcdc014dbdae7ca15446b847834ce2b1208193849f7e824c3796b03fc99bd11222a01047e4e33823": "0x0000000000000000000000000000000000075441524f3039105048414e2051554f432043554f4e4700001871756f6363756f6e673039383440676d61696c2e636f6d00000f4071756f6363756f6e6730393834000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd1a53046ed0d2c60ec568f29d8aa8acbe44da52d65d455d583494cfc2f0f5ce14e463f0b9e5a559": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd1ffac41df06f48cc41c23d8c527a9a9899831a5500fd27c799b5cd404f1757fcc7506e4a86cb6d": "0x040100000002000000000000000000000000000000000f6d617474656f6361736f6e61746f104d617474656f204361736f6e61746f1a68747470733a2f2f6769746875622e636f6d2f30784361736f1b406d617474656f6361736f6e61746f3a6d61747269782e6f72671e6d617474656f6361736f6e61746f4070726f746f6e6d61696c2e636f6d0000084030784361736f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd3470a836ea9a4008c15279d0e5f0a7dd1171cbc78cbdf7fa5899b48955e7cfe05629cff078b40a": "0x000000000000000000000000000000000006446f6e416e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd3ebffa43946729c8c5e44031d85024e4bce12bfa0652da14d359159b1a8727acaf716a6b677e62": "0x0000000000000000000000000000000000084d656e646f7a610000000000001140496e666c75656e6333537068657265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd5ac43b991d5bfdf68fd95ffc9cc02f15e28ce9df041da32f3b564e249fb4a8caa1c5135b1fad4d": "0x040000000002000000000000000000000000000000000549676779001e6c696e6b6564696e2e636f6d2f696e2f69676e6173692d616c6265726f001869676e6173692e616c6265726f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd87ceda2aeb7b22302ee7cf59c56eaea2db6946c671da40489f9259e33eaffc7cd2cacec048a915": "0x0000000000000000000000000000000000096b6163637570313200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dd96490c9cce24c2deeba6321bbb28a052a289d857b882b77b9bb36b3f5d8f6b9d6bab2a8e173b38": "0x0000000000000000000000000000000000084f646f7672656e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dda1f8e340e37b261c39ef78e57f239200072aa865312f87edfcb4d4133c6ccc0a7e33f5c799e201": "0x040000000002000000000000000000000000000000000c546974616e204e6f64657300001740746974616e6e6f6465733a6d61747269782e6f726714696e666f40746974616e6e6f6465732e6e6574000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ddd3fac950db81638ae535ed048c6144428c430959118e0a34ff1150662b13143fcd1dc9a31a4773": "0x000000000000000000000000000000000005414d313600000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ddebe5e9c243fb0a8cd03b329ea85dc19992ffdee21b7fb481915cf496571a4c3d6ef6a998077e42": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de0cc3ec4dab1c451e9b8842daafe40d555921fb6b47e66eb9907b10587a20add8f3676451b2e913": "0x00000000000000000000000000000000000a42756c6261436f696e000000196c7569736d61797374657231323340676d61696c2e636f6d00000e4042756c626173617572696f37000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de10278d56e138a554624f504797213920029ad9a9e11f06218c5f20ca160d66fda311650ce84e2e": "0x0000000000000000000000000000000000074e6574686e79074e6574686e79000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de11e082d85cbef160f94710848d9dce161724f257a240494c901728bdf2fa51c138fc5580ee3134": "0x00000000000000000000000000000000000e4e69776167616261204a6f61620e4e69776167616261204a6f616200001b6e697761676162616a6f61623130303040676d61696c2e636f6d00000f404e697761676162614a6f616232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de14b81ebe1d9b57fe4f532d7c92cf5241deddb7cc69437c1e14dd7a485a66e558b6e1277c130f32": "0x04010000000200000000000000000000000000000000106e6f74617261737062657272797069104e4f544152415350424552525950490015406b736368657965723a6d61747269782e6f72671f6e6f746172617370626572727970694070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de17584cd268e75b0277ce02b2ac78ceeb9ae4fa0a595005489bf3f5f77898415e32a3e9504a5314": "0x040000000002000000000000000000000000000000001e436861696e68756220616e6420546578617320426c6f636b636861696e00001440737269766973683a6d61747269782e6f7267186d654073726972616d7669736877616e6174682e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de3cf3ad0cf1a2ef6c2c6040c18e9e1c7787a3205eddc2b25866a7bb9f4b37d08fb99a303b1aaa76": "0x000000000000000000000000000000000008446f6c7068696e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de3f92404566ce2002d9033615be834251d1be3c49ef6824c62c23cf6c63670d6b525f113f7ec913": "0x0000000000000000000000000000000000054449434f00086469636f2e696f000b6869406469636f2e696f00002168747470733a2f2f747769747465722e636f6d2f4449434f3033323739373034000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de4c51814f3dc0aaaa8c84c6ba3df3fb3e74c82f7c4d6821f3182367db869a24a695c6c79b9cfa06": "0x000000000000000000000000000000000006526f62696e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de5c954dd6e8db73648bc880ddbc0f57d62d59f061c800d012e1a7592043d167fc0cc2c3a9da211d": "0x00000000000000000000000000000000000b4c65652042616e6e65720b4c65652042616e6e65721c68747470733a2f2f696e6372656469626c6563726f632e636f6d2f1b4049433a7777772e696e6372656469626c6563726f632e636f6d19696e6372656469626c6563726f6340676d61696c2e636f6d0000104043726f63496e6372656469626c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de635c0c26aa1285ced5f8289b742dd10e1346513b73e55878f5c758bcffee3b7b3aa2d591ac8f67": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de6f7157368189985cb1053f8515e1f6085856998ac902f61b60ae84eff323ea3fa5570e9856082d": "0x0000000000000000000000000000000000094c656f2053756d6f010114406c656f73756d6f3a6d61747269782e6f726701000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714de9c4d94174cd2477a74b06ace59a364d8c066e99d6019a3817505a1c8956316d65ad161e4a6f737": "0x0000000000000000000000000000000000066e6577203400000015424e6164657a646131304079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dea25247eaaa9075fe395dbcd412fb61e933d36cda92b15ccfcdc46c73d697cb59b0590a44e50c30": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f32390f42696e616e63655f6b736d5f3239000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dea8918004244b5bae0ce04d8021516cbf0a10c00c4e721319c1e91c729402b232942f9e2c152320": "0x040000000002000000000000000000000000000000000653544156520000001561646f6d69786931326140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714decae94c7ca0c861584d715bcb7a2d3b6a3120891dba91b19b12df42cd50f1c76103e2581d5b4274": "0x040000000002000000000000000000000000000000000b4f6c6976657220e29aa100001d406f6c697665722e74616c652d79617a64693a7061726974792e696f126f6c697665724074617374792e6c696d6f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ded9112c2a84a8aa64f39f9d8db7d1f258b28769521e66ca79b2c1d7d0d001c1f5be2c7370948209": "0x0000000000000000000000000000000000084169724c6f76650000000000000b406169726c6f76655f33000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dedbc2ce55177a93544ddc80d8569f43d39aa1e46f3d1a9a1aedc6d645d7aacde0184ef69ee9de76": "0x0000000000000000000000000000000000086a696e6e79383500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714deef5a3a1ff7e51fc0f9ad73d248c215a9d3c09543dc4f739068837ff478226cf0e5bf6c32071c76": "0x04040000000200000000000000000000000000000000097a68616e6773616e000015406a756e6975736c693a6d61747269782e6f7267146a756e697573406c6974656e7472792e636f6d000010406a756e6975733939333233323139000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714deefb32e6fa3ca98ea6ac7bc02091c06ee39e01af4e3aad2d0bd738e65b8874e522e7cde04762a23": "0x0000000000000000000000000000000000176162726168616d20504f4c4b4120415353454d424c59104142524148414d204d55474953484100001c6162726168616d6d75676973686134303140676d61696c2e636f6d000008404162757a7441000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df06261193a58ff6b0a8c24ac3491a353ac33a297990382a17a4f06945b7e8488024aad838e3be1f": "0x04040000000200000000000000000000000000000000084e696b6c617573000000156665692e6c6975406c6974656e7472792e636f6d0000094066657977756465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df39159abba55c6a2a221984248f769c6ee496bfc2c813cf000d2c2e10a7e19a67a4f4264a1b204a": "0x00000000000000000000000000000000000f42696e616e63655f6b736d5f33310f42696e616e63655f6b736d5f3331000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df3ef2b86fcb50a608b7835785fff5f3ce266a55391bfa52c22fa622a1e48cb29490118a8f55e657": "0x0000000000000000000000000000000000096e61696c615f5f6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df448953262dc4272a7dc6c670411c7f086514b9bb46732ed1e6a2045669bc883bfe540979366a70": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df50361da6149e1c9ec43214602db413abd2dd38bf27fc7fc76be1715f3a2a53e0c15f0be434a323": "0x040000000002000000000000000000000000000000000768696c75786500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df6216cf6db2390b967253bc4d2a74802f60bab1ee14e013e29df6605aad937e3bf3af3d06f01036": "0x04000000000200000000000000000000000000000000073154524942450000001931747269626572657075626c696340676d61696c2e636f6d00000b40317472696265646162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df658b757ba3a7aa702baf94343fc34fc6b80b225c14758484c91816726a7b3951bc0ce1daae9f53": "0x000000000000000000000000000000000005696e6b21001168747470733a2f2f7573652e696e6b2f000000000a40696e6b5f6c616e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df81a03ab44db94de209cc11caff247c55ac63eea5e65246dfca0d3fa13caf596422e617add11c6a": "0x000000000000000000000000000000000014506f6c6b61646f742077616c6c6574202d203200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df83b335782ebc49a02ec4c0ee5ece6ebb979e895f5f677cc5af9c792057d4a16845ac03d866380e": "0x000000000000000000000000000000000007766963746f7207766963746f72000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714df9611452ac38ef494947b0c3d8d505f78a6945db572e9c264debb16f4bf269cb5d45570ce90e325": "0x0000000000000000000000000000000000084368617a626f740101010100000a406368617a626f745f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfc59388da763570a87d5cc741b2db1901f13828456972aee17a7fd298dd4f58d4cbd4764d205c74": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfc6a79ef6d03ce998b1bc55dfaaac7c42b022a3389ac81fde184e7cf7e4bfb6f1762efacc9dcd0e": "0x00000000000000000000000000000000000e526f636b585f4b7573616d6132001668747470733a2f2f7777772e726f636b782e636f6d0012737570706f727440726f636b782e636f6d00001040726f636b785f6f6666696369616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfcec3c491888b3ac25812ad6fd4ccdb20b9e39ae8869b92f24bcb112c27a1f8870cf73e3af40d01": "0x0000000000000000000000000000000000044d4f54044d4f54000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfd89ee5d28bdb06ee6f9eb0e537bdeea4b952e9232516a5fbb9c8fb3d49522da2dac4fec6b4d952": "0x000000000000000000000000000000000009537461686c646f740000000000000b40537461686c5f646f74000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfda9759c850e63fcad4349f82754f223d99182a3f9de949c41ff94e672f7f548e7f4e66c04b5c1b": "0x040000000002000000000000000000000000000000000a537465616b43686566000017407374616b652d636865663a6d61747269782e6f72671868656c6c6f40737465616b636865662e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfdd2a5f61982fba4297a93d2faba768a0be3c2a69bee7a17d73264b9adebae51e28e7b37463f91d": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000064e3444524f000000156e3464726f4070726f746f6e6d61696c2e636f6d000007404e3444524f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dfe1e40570dd88f27c1178a97d52454f0c0b621adf94ed9ae7f5bcadd73d78918cd5f2e369afd539": "0x00000000000000000000000000000000000454696d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dff9d344c62cc1a2a89a9920a98f3591ccc0a1a4bc827a0adfba37b75fcc108ae3c7191bb9a32750": "0x040000000002000000000000000000000000000000000a50756c73656d6973730000001b64756661756c7472617175696c64697340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714dffd6f88a42d7fac960e13bfebea36ecf357ec2e813c2c06cbe61c8b789f5e06250d51244ec65f2c": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e01262497050cc2b2e75870b38698bb3f2bd133e571bb0207310369eb624f12e27b640997c9fd079": "0x000000000000000000000000000000000005524b523200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e021d1dc17893ea928b07966a96b6a1985a177e15d42d894b3fb7792127b6fe90c2fd282eb4c897d": "0x00000000000000000000000000000000001a416c666f6e736f204b7573616d6120496e766573746d656e7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e02cfa2f68a3d5d68c634afce5c235c94eb221a35c3f8cde8f45b961d713780f16dc561e98537e7a": "0x0000000000000000000000000000000000046e667404506174000000000010405061747269636b53616d61313830000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e030fba8f6a1ab9562268ef984602bd656ee3f4ffd59ee4f91fb1b8dacc81561165acf09cb04b437": "0x0000000000000000000000000000000000114e6f205269736b202d204e6f2046756e00000000000010404d6178696d654164656c76696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0557f0ae534aab028991ea1e64fe9abfa42ca2c940b83440041f53c1eacebcaaf946800df88bd65": "0x0000000000000000000000000000000000026d01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e056f1b2e24fa5d8887a4b3bf904dff1bd2b9db7d434a8293190a442e264f019255c799cc8755f10": "0x0000000000000000000000000000000000074d616d61544c01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e06d0f11fae617ffc00c1b295efcdc9a094f31f425d1728677ea4c978ba553d30a9df39737a6ec07": "0x00000000000000000000000000000000000d4869676843686956696577730e436872697320436f6c6f6d6265000011636f6c6f6d626540776973632e656475000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e082b4d27c3e325290028c5f7ac635cc45299d9de9e04681d2d935461bb79e83faf9fe9021407001": "0x00000000000000000000000000000000000a466f7220706561636500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e09f03562c3730f22cd74deae018fa587decf7492a527329f06e44e9e9725c6e7c48dbf6fe3a0c61": "0x00000000000000000000000000000000001c4b656570696e672055702057697468205468652043727970746f731c4b656570696e672055702057697468205468652043727970746f731768747470733a2f2f6269742e6c792f334f686d6847410000000010404b656570696e6743727970746f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0a7bda9cabb2697382c2b16eff91187f088ea8902a92fd101c647fcf8fad4995dcda013f5674146": "0x00000000000000000000000000000000000a4e38746f72696f757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0b7b989a9a7b3882a26e8ab44149c0eca39f384f5461ac94d9db482f7048bcf01fa03ac974e9f74": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0bcb14a63a8f407f082e865cb1640b9d304e0112f2a853fefab59cb646742a87b6efddba380bc51": "0x00000000000000000000000000000000000e446f7473616d612050756e6b730e446f7473616d612050756e6b7300000000000e40646f7473616d6170756e6b73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0c1c0b1ba68c50b38442c5d5813e8982e7d0e48b0902a2fcd7dca14bcbcb2018b3be02ddd0baf2b": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f33330f62696e616e63655f6b736d5f3333000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0d88f101c60b968860b9c3afa9056b5861ea3252c32d4ceee039d5a328210b2f106e2362564c327": "0x0000000000000000000000000000000000174368616f7344414f2042616e6e6572204d696e746572000d6368616f7364616f2e6f7267000000000a404368616f7344414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0e206491404b059c229d8ccc5e5650d17760ce2b7c42bdae5f6afc6e8bab249ec77f3f779ee5a65": "0x040000000002000000000000000000000000000000000b4e6f64616d61746963730f4e6f64616d6174696373204c74641768747470733a2f2f6e6f64616d61746963732e636f6d14406162633a6e6f64616d61746963732e636f6d13616263406e6f64616d61746963732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e0f9f6d0a22b7f4d7c101b5a4517817aa0e05d07291dc0f020daf435432ce8ef6996fa8fdf722a58": "0x00000000000000000000000000000000000a4d61747420437a617001117777772e6d617474637a61702e636f6d010100000a406d617474637a6170000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e10f7130f3342868be48e86fb92b88b2cd58af2e0f83ce19054a1710f3285ec16cfa21c533070038": "0x0000000000000000000000000000000000076861727065720768617270657200000000000f406a6572656d696168736f6c7431000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e14b7899b9364c96f4ee3ef446661d9952ca201eb16aed93217c14c48970106092ab7e3f2b4ae713": "0x00000000000000000000000000000000001048616e77656e207c204c69746d75730000001468616e77656e406c6974656e7472792e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e14f996a74ee6952fc76f7807f64bd43133d613e69b76210fd9613946365c01aece14d487d07c71d": "0x0000000000000000000000000000000000054265653700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e17e6feedc6d6c3e024f853befcdb3963b6c6405cd765edfdb6323afdc79c0a842154ba7e8bd7e4a": "0x040000000002000000000000000000000000000000000844656c616e65790000174064656c616e65795f73633a6d61747269782e6f7267136c6f70736c69746540676d61696c2e636f6d000011405363727567677344656c3639353636000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e18ec3dbed3906928c2dee8f9acfbd0ace6ba1c804e4f592e39e4c9c895646d1cf376179a4de7d73": "0x0000000000000000000000000000000000086963656265726700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e192bdc41ba8b8537a4ea4898b3670047a9a245b16814151fe047e7f4317274b2322bc16bfc86777": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1b9d02d9a1f50ab16da5bff34fefd1880608641996167d42ddf2832ad360eaaf26bd480f8b11510": "0x00000000000000000000000000000000000c597572694e6f6e6475616c0d597572692050657475736b6f001840797572696e6f6e6475616c3a6d61747269782e6f7267167975726970657475736b6f40676d61696c2e636f6d00000d405975726970657475736b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1c590c2d461a2919affd71d6553897322cbc27d841267cbd0f4f61d5b2e1b55f1ccc4dee3dbbf29": "0x00000000000000000000000000000000000e676c6175626572626e756e65731a476c617562657220426172626172726f737361204e756e65732068747470733a2f2f6c696e6b74722e65652f676c6175626572626e756e65731a40676c6175626572626e756e65733a6d61747269782e6f72671a676c6175626572626e756e657340686f746d61696c2e636f6d00000f40676c6175626572626e756e6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1cc7e9a208fec062a60ef494b4278138c41a5abfaf31a98703d16cb817c121bffd6fe29922a717e": "0x0000000000000000000000000000000000075a6f6f6579730000000000000c40706978656c7472697070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1d72d8b8fd19c1e180e0bbab137521c05b4d905878159e631e8d58f8f98eb54bcde45355a64a42d": "0x0000000000000000000000000000000000054e4f4e4f0000000000000a404e6f6e6f5f646761000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1e4563d8107381d90bc0687ec4207718cf796657debc704ddcd040fb7bfaf024a0112085e3bf44c": "0x00000000000000000000000000000000000f4f7374726f696e76657374696e6700000000000010404f7374726f496e76657374696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1e83d6e28cd24a1cc5fb20e015e196772a14adb90f25ad646b55261cf41ba556058b2cf05e1d14d": "0x00000000000000000000000000000000000b617065586368696d707a001d68747470733a2f2f6c696e6b74722e65652f617065586368696d707a0015746f75636840617065786368696d707a2e636f6d00000c40617065586368696d707a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1ea5606e60d1e1b6ec662611fe307a35f5071d69b7e38993e7ff1b0c887eb742ad5d4a5161fd10a": "0x00000000000000000000000000000000000b466c756666795f666f780956616c657269612000000000000e40466c756666795f465f6f5f78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e1edcfad4e61061fce792e53c1b7b7375ed58cfe1a68a88fc0dde4bd604942f99a5e93ff3b249d2c": "0x00000000000000000000000000000000001048696b617269204e616b616d75726f000000000000104048696b6172694e616b616d75726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2082f50f907e5d5a48539457aa2e54048493ccaf980be18253d8cabd6eecd295e6b62e6a357352f": "0x0400000000020000000000000000000000000000000009616c66616b696e6900001540616c66616b696e693a6d61747269782e6f72670000000a40616c66616b696e69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e21241c1f77eea219c34bbbde6bff80d45a0e9f3500e7aebd52d558fcd919b2e0d788dd8728a047a": "0x000000000000000000000000000000000010416e61656c6c65204c54444049425000001740616e61656c6c656c74643a6d61747269782e6f726715616e61656c6c656c746440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e21499c80ca854b48c82bbbbb9667ffba6391a9562295f4138dc0d28c4a062c98c71892a3e149e33": "0x0000000000000000000000000000000000054d617279124d617279204f6d612d57696c6c69616d7300001c6d6172796f6d6177696c6c69616d7340686f746d61696c2e636f6d000010406d61727977696c6c69616d735f6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e233542478d579cace65b4f9996573027bb9ed1f267033177462f9019642f1fa0b14a0ce41994525": "0x04000000000200000000000000000000000000000000084e4f434f314b53000017406e6f636f63727970746f3a6d61747269782e6f7267156e6f636f63727970746f40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e267ed189b260f34e860a0f82dfd893ebf69b3ca5867e58dde45e4c03acc88dcf1881c05a1cbb624": "0x000000000000000000000000000000000007627269616e3100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e26aa6ab4f40124e083f39607241c8ebb62919ab2ed816cb6b20c7d0abad78a92570030d2f96c63c": "0x040000000002000000000000000000000000000000001443727970746f204a61636b2053706172726f7700001e406a61636b73706172726f7763727970746f3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e29cc92a3efbdcb4fade8b2ef9730e55caad79c952c433082849c133e8f4303c959124f881cff002": "0x00000000000000000000000000000000000c6172676f6c616273202d7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2b5c6849bd31d1a68a7a410afcdad03bb86018eb32bb188ce81f4a7bbac85f9a161511b4939252a": "0x00000000000000000000000000000000000a6368696c6477696c6408616e61746f6c79000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2d6e1cbb0d68059803a44e8667a858bf0cb69c031e7623d560e962c6bfd9b1d28438d6ef6a20e5a": "0x000000000000000000000000000000000010506f7274656c61204361706974616c10506f7274656c61204361706974616c01011a706f7274656c612e6361706974616c40676d61696c2e636f6d00001140506f7274656c615f4361706974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2dbccbe79b6bc23a0c9c8a74436d2554b9a0249994899e527008da53b2e33dd45b51d07d0d3125e": "0x0000000000000000000000000000000000146172676f6c6162732d636f6e74726f6c6c657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2e24cb03e478499c2f8c1243fbad7e55982b37dc983137e4b9df19f5b31b5b35c5809d81cc4d03b": "0x00000000000000000000000000000000000e42494e414e43455f4b534d5f390e42494e414e43455f4b534d5f39000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e2ee33ee9eb984f7467d94f60ca2fec8bdfc843926088df5ad274feb4a8c2cd0465ca8cb78f54c72": "0x04020000000200000000000000000000000000000000075472616e7358075472616e73581268747470733a2f2f7472616e73782e696f13407472616e73783a6d61747269782e6f72671173696c766572407472616e73782e696f00000a405472616e73583131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3090a8f14b0a8a7e8fc78d54db8818125e186950a295ac7db278b9c83b6c04416ccf38869451405": "0x00000000000000000000000000000000000b44616e69656c20426172001768747470733a2f2f7777772e6269746677642e636f6d154073706c61736865733a6d61747269782e6f72671264616e69656c406269746677642e78797a00000c4064616e69656c74626172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e31041f839b1c98afe111b571b0ba64cb8365c7e9bba1e412d6fd57634a54bd1996314689e061a68": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e31e32af7d282fd42cf0838b05fb182718de859525fa1e6d53d557e5fcf631ee9ff44c619810d43b": "0x0800000000020100000003000000000000000000000000000000000843686576646f72001868747470733a2f2f7777772e63686576646f722e636f6d144063686576646f723a6d61747269782e6f72671263686576646f7240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3246305c87cacb27c660ea631e3433e76cda4223da22d0f40ff51d0790f9531c6dc017f04526454": "0x00000000000000000000000000000000000c4755494c4c49544f4c4d4f000000166775696c6c69746f6c6d6f40676d61696c2e636f6d00000f406775696c6c69746f6c6d6f6473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e32b208e65130e522045da46c7766eb3f515007cbcfa48187fd157189adcde4b0a36f5069661c147": "0x00000000000000000000000000000000000a4f6c61736b61417274074f6c61736b6100000000000b404f6c61736b61417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3450541d8d8d0681af27d40bf7e664781d62d3e0953bf49a7b6accab06d48acbea4c0497a285135": "0x040000000002000000000000000000000000000000000d426172616e2042617964656e0000001662617964656e5f62314064656e69736f6e2e656475000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e35b67b937cc75caa81dfbac142664eb6f7ff61c5c0b2c8a180059b27ccb68ccc6b9c152be120b70": "0x040000000002000000000000000000000000000000000c6669616c6b612e6c697665001468747470733a2f2f6669616c6b612e6c6976650012706f6c6b61406669616c6b612e6c69766500000c406669616c6b61706f6f6c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e36e578a8e8879d6882cb987c0812a6223eccca2b949a700f23956c0fd0e078998aa202fbb3dd258": "0x0000000000000000000000000000000000084261746177696c094d6f68616d6d6564000013796565656573383840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e38a55733df8b59a8afadb56a14267be2968192955ea0946c4c7654bf57edf48b8e2a0026ebb5c16": "0x00000000000000000000000000000000000e476f72676f6e7475615f4e46540000000000000f40476f72676f6e7475615f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e39df08f4aede84f78bd7b1645db34388b2de98519122d04ce82685b60b092e4a1a6b79495b06435": "0x0000000000000000000000000000000000086d7766696c686f1b4d6f697365732057656c746d616e2041627265752046696c686f0000126d7766696c686f40676d61696c2e636f6d00000a406d7766696c686f32000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3a4e80562b259ac10b09f2da2f405ee165a9288afdf2a8d28f77abedc0c71c2322d1e7bbf824573": "0x00000000000000000000000000000000000d446d69747279566973696f6e07446d69747279000017766973696f6e646d6974727940676d61696c2e636f6d00000f40646d697472795f766973696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3a998fba5b8bbd73c747e495e89089d355e243e1d3818a46c83423d4d230f6fbb516ca1f9a69498": "0x0000000000000000000000000000000000104b5553414d415f54524541535552591847656e736869726f20627920457175696c69627269756d2068747470733a2f2f67656e736869726f2e657175696c69627269756d2e696f214070657465725f7374723a6d61747269782e6f72674070657465725f7374723a1770657465722e7340657175696c69627269756d2e696f00000e4047656e736869726f44654669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3aace461a41787e00dd250306b8d5d95cfcf010f9197aa6a23ac456c4dfa242648b45f3d7d73062": "0x00000000000000000000000000000000000d466f756e646174696f6e2e5100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3b37bd998e2d5ae02e8b488ad53f796a30d332f94f9b86da98c5b4045e09dbec4b520787f2cc568": "0x00000000000000000000000000000000000b4b7573416d617a696e670b4b7573416d617a696e670000156b7573616d617a696e6740676d61696c2e636f6d00000c406b7573616d617a696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3cc564421272ae1661e75c54ec564a0e3af9c0a50860fa942d9d1b02d73712fbf855ddef81f4b1f": "0x00000000000000000000000000000000000f5761737465206f6620796f75746809536f756c20726f741d46616d6f7573204368696e657365205061696e74657273402e636f6d0111536f756c726f74406d6565742e636f6d00000a404d7578696e617969000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3e27ff656075247d2553b686fdb9fcb522543211a26d6e2ec15fbe051b49ebd03c7ea920ab03a79": "0x00000000000000000000000000000000000b77617465726d656c6f6e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3e9a46b476478204c4769cc1bf4774f19c7433e31a5b8cb686944cdd758e193d264410d4918b120": "0x0400000000020000000000000000000000000000000009506172616d69746f00001540706172616d69746f3a6d61747269782e6f726715737570706f727440706172616d69746f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e3ee646b3e2aebc288214b102388d1c4506c188c7ed7e7d306c03c5bc6e3fa5e4e16b84ceb86ca7d": "0x0000000000000000000000000000000000066c6f756b61000000126c756b6f6c6172696340756e696e2e687200000d406c756b616b6170746f6c31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e415276d670b78fbbc8581a5550ab573ee71a5eb5424ffcf3669a47d5b165fbae9979c2232eafd35": "0x00000000000000000000000000000000000a4f7468657257524c440f4161726f6e205370616e676c6572000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4153a7e275b66f81c35024ca6ebe0f04f37160246226252f758640bc7fbdfd7d1862d1cc0709706": "0x04000000000200000000000000000000000000000000094e656f506f77657200000000000011404e656f506f7765724469676974616c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4173fbb2e6bce95ea7e253f4ef614f3461f1b20259ff57dc1ed75397f9028c4446a3c49348d9610": "0x00000000000000000000000000000000000762616e64616900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e41ae28131a0427194b43554ce1f4d12431ecd9e98b526c8a2365c73c4df302762afe817f2014725": "0x04040000000200000000000000000000000000000000057074716100000011676f6431373540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e424960c1224933864e05e73625f3f0991e3062733ad8480c5589a710a24beacbaa555f1c4a7f064": "0x0400000000020000000000000000000000000000000014f09f8db750726f6f664f6654727565f09f8dbe000014407665727374616b3a6d61747269782e6f72671870726f6f662e6f662e7472756540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e43bc3dbea2aea278cec9d853f1e271b254904cbaad9b96cf5674111df2712e106782b6d03ad4a02": "0x000000000000000000000000000000000004496b650000000000000a40496b654275696a73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e45b9c4b5333e7a93e814767c06c6f8cfbe0c531c5bc2545ec897f41427faeed5f2a796107c98425": "0x0000000000000000000000000000000000064f7369656c064f7369656c00001a6f7369656c2e6d6d6d6f72616c657340676d61696c2e636f6d00000f404f7369656c3035333933323130000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e46a0a1f27bec44a52b901aa3d7b55a32518b419e7759d281a620269621b460dc2f44c1d8d49ec3c": "0x040000000002000000000000000000000000000000000d4d4943484953414d412049490000001a6d69636861656c2e7361726e69747a40676d61696c2e636f6d00000e406d696368697361726e69747a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e47308a662ac61d8ec748cd857304d85365e8189c61bd414d5553f1aa4190b6743f528b30dc43939": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4862976694931a99c188166a98813c80bd47da8c69317282ba30fda0052e8f26c9afd4226793553": "0x0000000000000000000000000000000000074a6f736569370b4a4f5345204d4154454f1a68747470733a2f2f7777772e6b6170617a6b6179612e636f6d16406b6170617a6b6179613a6d61747269782e636f6d146b6170617a6b61796140676d61696c2e636f6d00000b406b6170617a6b617961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e48e1e2716de291fb003e858a649acbfde98acf1d9e7863397984405fc8e0ff9d91fa4c9025afc27": "0x04010000000200000000000000000000000000000000184b41474f4d45204b7573616d612076616c696461746f72000014406b616d696c73613a6d61747269782e6f72670b6b40716472766d2e696f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e497fbc93f6011c0ce1120d245e6912eab85477f9a806728f4bf82ee50ccb4f8750ae14feb7d9c7e": "0x0000000000000000000000000000000000084d6f6f6e4b6f6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4a7b18b604b590ebe4b9973a7f6a5586a38fa295ec8e64d4026aa878c840630a7ccfa7f3914d162": "0x040000000002000000000000000000000000000000000b476f626c696e53616d6100001740676f626c696e73616d613a6d61747269782e6f726719676f626c696e73616d616e6f646540676d61696c2e636f6d00001040676f626c696e73616d616e6f6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4a9fa782e599e6e54bbe132da515c57b551b15452d06341ce9212859c8a0d8d5eba38b9f82f486f": "0x0000000000000000000000000000000000114576726c6f6f74204f6666696369616c00107777772e6576726c6f6f742e636f6d00116c757575406576726c6f6f742e636f6d000009404556524c303054000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4adb7a829a6d528623f9120f5e76a9988d6273e32e15a6a3db3ff0bbc551c081bf8716a6f152d22": "0x0000000000000000000000000000000000000000001544414f6e32456172746840676d61696c2e636f6d00000d4044414f6e546f4561727468000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4b32bdcfe8a21ed50b428a44aee6d7d7971bc278208f295b647bd1cd44985423c3cf405adc2e336": "0x00000000000000000000000000000000000b6d616c696b656c626179001c68747470733a2f2f7777772e6d616c696b656c6261792e636f6d2f0013686579406d616c696b656c6261792e636f6d00000c406d616c696b656c626179000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4b5facde9bf411dee16a0a68c6bb00ee88ee56a12ad67e778bbee540f868ead35fb6851fc522c0e": "0x040000000002000000000000000000000000000000000959414f20476d6268000000176c756b6162616c6173686f7640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4cea58d581e6c8f707c9246c1c227f1495885cb2f4c59297248ec5abeff2d0f68495075a16bc17a": "0x04000000000200000000000000000000000000000000034147001668747470733a2f2f76616c696461746f722e61672f154061677831303030303a6d61747269782e6f72671368656c6c6f4076616c696461746f722e61670000084041477831306b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4d0c3afd0945f3b8eebe1699e80aa195f76826c2c9da998095018f6d60a0446b6074736a68b3922": "0x00000000000000000000000000000000000c50756d706173617572757300000000000010407069636b61736175727573303037000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4f24b48776a5907d860c42aad31e29765a88620672b42628634a6901e9a2e327b3b77de463a4051": "0x00000000000000000000000000000000000a53545238204641433300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e4f801fde83ab27b86d96411e256368ca351706e72275f29a0190becaf81dacd4983d5f17e41442e": "0x00000000000000000000000000000000000b4261727279204f6e797800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e51a8e774114148a1cb8c4e3b0331a1d7db9a12dad422096a3b2ea8634aba36a00947686d818077a": "0x0000000000000000000000000000000000095376656e67616c69010115407376656e67616c693a6d61747269782e6f72671963727970746f747261707065727a40676d61696c2e636f6d00000f40756e636c657376656e67616c69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5226b3101e1a2cf16ea73eab943eeb2bbf8c6c5e5ac7bd92004c3c395f2db8e095b8c4afc063324": "0x04010000000200000000000000000000000000000000094465436f6d6d6173094465436f6d6d61731568747470733a2f2f6465636f6d6d61732e696f2f000d6d4033636f6d6d61732e696f00000a406465636f6d6d6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e54b0dce3847be9f2a9aefeadfe561f9c27106bf951d4d362b26fff6beff8b7949881071c973ee63": "0x000000000000000000000000000000000008497a204172747303497a1a7777772e696e7374616772616d2e636f6d2f697a64726177730019697a7a61636f6d6d697373696f6e40676d61696c2e636f6d00000940697a6172747373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e560702c07b98769501c6522acab8faebe0aeb74bc5cfb6e0c0062134ce4139b2b4d29e690306942": "0x00000000000000000000000000000000000e4b7573616d615f77616c6c657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e57b6fff5aa31fc5dc73e84c4d039277ae7819cf959a0092683ea8e6e7e9d2447c918d8aa89d681e": "0x0401000000020000000000000000000000000000000009456c2050696e746f09456c2050696e746f1768747470733a2f2f63616e6172796e6573742e696f2f0015656c70696e746f6d616e40676d61696c2e636f6d00001040416c6550696e745f43727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5838dc3419931bafcee617f4c62eba023c5dd5bd4b3c4168e6c5cfdf504b50d611c0550fd078557": "0x000000000000000000000000000000000013456c656d656e7473206f66204b7573616d6113456c656d656e7473206f66204b7573616d612068747470733a2f2f7777772e656c656d656e74736b7573616d612e636f6d2f0015566f6c74756d2e6e667440676d61696c2e636f6d00001040456c656d656e74734b7573616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5c3e4a6b7f9ce9d1a3064ba1947c88f8d8e8d68296a5504fd3c1f3261509b4ce40b92b1b75c7174": "0x040000000002000000000000000000000000000000000a54657261204368616400000010676d40626c646e6f6465732e6f7267000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5c7849de4c2d8485cccaa999b535cd15c18bb2d22db70e4d7e8c83bb85bcbd3efbbd71f29c5d401": "0x00000000000000000000000000000000001257656c746879204d6f6c65732044657673002168747470733a2f2f6d656469756d2e636f6d2f4077656c7468796d6f6c65732f000000000d4057656c7468794d6f6c6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5d8672abc761749fad2d3a08e033ef653430391e3b208f9e17119de384eab78084c1dd817893439": "0x00000000000000000000000000000000000b416c616264756c6c616800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5e12c84a1884bd50a6ef463d858cf46d27ad2129b04f078a6b009eb588f9d651e399bce59fff579": "0x0000000000000000000000000000000000054a494c4c00127777772e6a696c6c73656e66742e636f6d000000000b404a696c6c53656e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5e77e17df143c51388c3c690f7ce15672f086b6a5e3ad7263b36986392cd5c8a70ee62f11554553": "0x000000000000000000000000000000000021547269636b79204e46542052657365617263682644657374726f792044657074001868747470733a2f2f747269636b792d6e66742e6172742f000000000d40547269636b795f4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5ec7a33cbbb8d9e04f3da939fa351c562c7e06e1e3716976b5e14230e83a45995cbad9086f49e17": "0x040000000002000000000000000000000000000000000a506f6c6b61476174650a506f6c6b61676174651668747470733a2f2f706f6c6b61676174652e78797a1640706f6c6b61676174653a6d61747269782e6f726716706f6c6b6167617465406f75746c6f6f6b2e636f6d00000b40706f6c6b6167617465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5efd10bd264dbe62c0adc4df234352b61fd60a32c2890fc64c2c0a3de5e33ee1c5bc9d8f581642d": "0x0400000000020000000000000000000000000000000017f09fa7b12053656974616e20426c6f636b20f09fa7b10000184073656974616e626c6f636b3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5f35c89aa222ad08a0b27e25e4d62869f8aaf9e23c69e9b494b1fc617d0ebeb4c8afdcf1fd1aa59": "0x00000000000000000000000000000000001246757475726520426c6f636b636861696e000000166768726973746f7636343340676d61696c2e636f6d00000e4046757475726542636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5f95c682343769f3070122f5a708702492ef47c9113a8896a9d4bd33a24a071cead7303e1158f26": "0x00000000000000000000000000000000000f4069696c696e67776f7274683232194a6f686e205269636861726420496c6c696e67776f72746800001e696c6c696e67776f7274682e7269636861726440676d61696c2e636f6d00000f40696c6c696e67776f7274683232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e5f9a2fa2a6ae21fc86f4ad4a9c9032c14426b27d2b899a9813ade10664beb503c3076f78a87ca09": "0x00000000000000000000000000000000001b576f6c66207cf09f97bb4261736563616d70205374616b696e6700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e60d3fee20a9683954802ea0b430910788de53c221bf8c0f1a349719284af18c1ea1f2807c4fec44": "0x0000000000000000000000000000000000104149207769746820612042727573680000001761697769746861627275736840676d61696c2e636f6d00000e40414977697468614272757368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e61845ff24d5cc1e342f12106e62dc91fd042c6ea03f570502e69314d5cdf9128c3ca1deab6d904c": "0x000000000000000000000000000000000011596f75646c6544414f204d696e7465720a596f75646c6544414f1a696e76617263682e6e6574776f726b2f796f75646c6564616f000000000b40596f75646c6544414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e61c50b0b7f382f3fa8f1542a5136431ffaf6e46fd95cf784931de839ea17d154a4eee41308adb5b": "0x0000000000000000000000000000000000066c696c6c6f066c6564696f00000000000c406e6f5f757333725f6964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e61e63d1b5d2c29a1c90f53e61c20041e1a3df81248b4a6bfa420ec7cd5ad1dc37050bd50253be56": "0x00000000000000000000000000000000000f426c6f636b6174686f6e2044414f0f426c6f636b6174686f6e2044414f0f426c6f636b6174686f6e2e78797a0016626c6f636b6174686f6e406269746677642e78797a00001040426c6f636b6174686f6e5f44414f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e62a1248b05d3350b0a503c9745bfe83420884d860baa41869bec8a251e640d5769134e92119343c": "0x040100000002000000000000000000000000000000000d4c756e617220417669617279001368747470733a2f2f6269726463752e6c742f17406c756e61722d6563686f3a6d61747269782e6f72671c6c756e61725f6176696172794070726f746f6e6d61696c2e636f6d00000d404c756e6172417669617279000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e62a64b055ddf8da2c8781410fcdb4a98b0d87447f73e46c2c5a285cbe3338e73cf213f4fa48851b": "0x040000000002000000000000000000000000000000000a6d6172697361727a65000016406d6172697361727a653a6d61747269782e6f726714666c79706574726f764079616e6465782e727500000b40666c79706574726f76000a6d6172697361727a6500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6344678166f5ea4ce632205bea89e6a30ed4e150402ba7997fa946739dbff2d8bda1fbb73f6d461": "0x00000000000000000000000000000000001a4d41494e54454e414e43452043555241544f522050524f585900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e640a57f005246e16cc99fecae54278eb06aab56467bb644500ac7301cb1b9dd2f7b3bf8014cb40d": "0x0000000000000000000000000000000000065061626c6f067061626c6f00000000000940626974636f696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6571ba184d1dd340e24ef1865f800083d91176db91ceb22bc12386f4ad085843c7c2b1d2e457f61": "0x000000000000000000000000000000000006506f7070790000000000001040506f7070794f6e5468654d6f6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6641b78daaaa70c127d0bf5a272c4fce4b744027090fd032cd8dd569c52b8301727192d6df42f78": "0x0400000000020000000000000000000000000000000010f09f9a80616c6b6f393839f09f8c9b00001440616c6b6f3938393a6d61747269782e6f726712616c6b6f39383940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e669931fb1d70de1e63bad33d41d23e049d4f9efea39e4f44426b3f82104800ef6a9f29fbaa18667": "0x00000000000000000000000000000000000547616265184761627269656c20466163636f206465204172727564611368747470733a2f2f67616265732e73697465194061727275646167617465733a6d6f7a696c6c612e6f726716617272756461676174657340676d61696c2e636f6d00000c4054696e6b657247616265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e67690be6715ac6dd24fb92b0c4972591887fd6bd35c641d80c2f6341c8ed8231afb779e4e26ea4b": "0x0000000000000000000000000000000000204d495353494f4e20434f4e54524f4c207c20434f4d4d554e4954594e46203500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e682263d2b1ef24bbc2d28f57741ea9f160b1dfa892f5ec7d27794a10faf0eaf864e3cec1f935c6b": "0x040000000002000000000000000000000000000000000747726f6d7a790000134067726f6d7a793a6d61747269782e6f72671367726f6d7a79313540676d61696c2e636f6d00000000085f67726f6d7a7900", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6a2e00133e91fa9b60df42b347f1fef9ff33a82e6cf842ee1cf51547ddb4ef66da57194e7b8ba4b": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000094465436f6d6d61731533436f6d6d617320546563686e6f6c6f676965731568747470733a2f2f6465636f6d6d61732e696f2f1640696f736966313937373a6d61747269782e6f726716732e7368616d616e6f764033636f6d6d61732e696f00000a406465636f6d6d6173000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6a4ed08608c10747cd59ba5ff4fb96195e2ccb9eaccd78bff982e0f15db7e942d72d1b957a2fc0a": "0x00000000000000000000000000000000000774657566656c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6a7928211b426f8dc4cec4724b20afc1dc35f89679f2163a184c121c8dd74e00ee15114b471fb3b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6a7b17e0dc24fffb6c276d432f4efd1f1d1dac4ffe8b237884c3eff170579883e24752c4179f30b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6b52eb564f74eb652620328072469a6ddfdefbe41728a7de41dc26c6287529f220e562bc5030e63": "0x00000000000000000000000000000000000d456c656b74726f76656e696b00000015737472656c6f6b37353940676d61696c2e636f6d00000a40737472656c5f6f6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6bd40c93fa096fd767cba4f8c9944d922ec038b8e49798ded82982594176648e88846bab4dfb116": "0x0000000000000000000000000000000000084d65727269636b0101010100000c404d65727269636b323439000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6be2ef10957c7f700cc6d75d48ed09a1a77df6336e1de6610bd6cb012617f5adc7a0a0088589d60": "0x040000000002000000000000000000000000000000000b4c6f72656e61204b534d000014406c6f72656e61663a6d61747269782e6f7267166c6661627269733139373440676d61696c2e636f6d00000a40626c6f636b79615f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6bf80afef0f87a4e8c096adce479e487ffbb318c037b5a6e6d3743f89f83c5f32aee60590fb325a": "0x040000000002000000000000000000000000000000000a47656f7267695f6967000000126a69673737303940676d61696c2e636f6d00000b406a696763727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6c2c15d71b57c80a8cc040d5d391967b6c50b54d81dbc18acf06fd13a704decc7df6f464679051b": "0x0401000000020000000000000000000000000000000008456c656e6f646500001740656c656e74726f6e69783a6d61747269782e6f72671b656c656e33393874726f6e6978626f7840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6e4f10f4a2d38dbb6511f13375482ec7f64612a9b23a6f9d0922d052b8ff65756e97640607d2476": "0x040000000002000000000000000000000000000000000a4e654e6120f09f8cbb000016406e616d6574616b656e3a6d61747269782e6f7267196d796d696e647365746f6e796f7540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6ea262a4e57686c7c95ac8365f9f4fc5f0979c438adaaa4766871c3080ab274904837315cdc8b26": "0x000000000000000000000000000000000008417274204c61620644617679640000156172746c61626e66747340676d61696c2e636f6d00000d404172744c61625f4e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e6ffdcce232e42d1f047d33d085908d48fd886c98b56792757c6dcc79df7549921a456c1500ad75c": "0x0000000000000000000000000000000000094e6f67617264657210416c69204361676c617220557a756e01010100000c404c6f626973696c696369000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e76389c26b279edcfcc3adb5fd50be07e63c0711e10bf94a5e81e3049f58b4a1c0f78b7c63436a3e": "0x00000000000000000000000000000000000c446f776e736964655075740c446f776e73696465507574010101000008404e4b59323235000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7720d47146ee75b84ea64de1c450d5e719041fc2fe8cfb61bfbb8eb42790de3ff6f7bcf41ae432c": "0x00000000000000000000000000000000000a5f476f676f676f676f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e77aa7455b2fe961fe4c363ca5fbd7818a873e807261aff6288a5c83f9464cbfa0fa0f280a9a7a31": "0x040000000002000000000000000000000000000000000761726b6177610000001461726b61776136303640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e78e73a25356ee263028097756f2e6b331a1ab76fd0abe787b6a1e60d0174c9dfe44c4adae5bff42": "0x00000000000000000000000000000000001031706f73697469766576696265733100000017637572746973657472697070407961686f6f2e636f6d00000d4032676f6f64766962657331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e792229345a703fc4ec57d4ea0756ce490ae612b7566f87fd99d946fbb0acf030c3642807189ad04": "0x000000000000000000000000000000000014456d6d617320284164616d204173676172642900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7a7f99c4fdd18b6aa45f39ba0061f8a7e5d4df583d003a9f11c89f09c6e0650be230552dbde8d65": "0x00000000000000000000000000000000000942657274696e686f144a6fc3a36f20466964616c676f2053696c76610000186a6f616f6166666273696c766140676d61696c2e636f6d00000e407075746f62657274696e686f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7a9bfdf07bafce9e604df3ebc0fe5cf21a4b4be4c8f0b28a1c458b455316215b41da6f136f7910c": "0x00000000000000000000000000000000000b746f726f647261676f6e01010117746176726f736472616b6f6e40676d61696c2e636f6d00000c40746f726f647261676f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7aeab5136b2e1a4182cf6a4edda25060a732818ecd359268b7cfe3c9ed503cd5a76fb4dfd8a1c5e": "0x00000000000000000000000000000000000f696f667468656265686f646c657205494f54422168747470733a2f2f6c696e6b74722e65652f696f667468656265686f646c6572000000001040696f667468656265686f646c6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7cb8e1a29da70a064f4c7e6a5f3f25b4d063e5461bf3882569aad883b6db400695ccfd7c6e6ef22": "0x00000000000000000000000000000000000c5843417374726f6e6175740744616b6f74611968747470733a2f2f696e76617263682e6e6574776f726b2f1940696e766172636869746563743a6d61747269782e6f72671764616b6f746140696e76617263682e6e6574776f726b00000d405843417374726f6e617574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e7cfb082496967f7ec22eb74dea33d78388ca084d35bb754ab5256d4d606d83818f639d0c63dd541": "0x040000000002000000000000000000000000000000001145617420596f75722043727970746f7300000019656174796f757263727970746f7340676d61696c2e636f6d00001040656174796f757263727970746f73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e806de170873b7f5bc955504a40c50ded178a8082516a78a68f503348c16b106fb2a1aa2c594743e": "0x04010000000200000000000000000000000000000000074d616179616e0e4d616179616e204b65736865741468747470733a2f2f6d616179616e6b2e636f6d14406d616179616e6b3a6d61747269782e6f7267136d616179616e406d616179616e6b2e636f6d00000e406d616179616e6b6573686574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8132b78f5a4f887e6c77cda38a3c7f46fa96464dccc96f4d36f31ba1f4487c06dc83b5c8e45ad04": "0x00000000000000000000000000000000000f4b727970746f686f617264696e670000001364616d6f6d616e6740676d61696c2e636f6d00000d404b696e674461736f727461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e816cc3d6733171beecf668b36de6a7e53932f2a13c6e7a76ba18de1293eec95f2ab73259ccc9461": "0x04040000000200000000000000000000000000000000076c756967686f000000136c756967686f393540676d61696c2e636f6d000009404c756967686f31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e82fc91783bf46accadffbe2995ae2867e82d0509dd5b7e3f392bcc1c3f72d5c7c22b6992cea506c": "0x00000000000000000000000000000000000a506978656c20417274054e465473010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e842dd34520b9eb24cc814dbc865ac0e41bf2d9c39177665f32cadb7d01093e2ad40cdca1d40b53f": "0x000000000000000000000000000000000015427564647920486f757365206f66204368616f730000000000000e404d6161743734333936343630000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e84a92dfe79fe371cc16be5e77dbadcc7038bd9d447475d68dc4a9af67e3ecb92ca374c7cff9365f": "0x0000000000000000000000000000000000064d6172696e00096d6172312e646576000e6d61723164657640706d2e6d65000009406d617231646576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e85d0bcdbe07f1da309409e68f563d9e9160bc30f7418cbe5735e3e2dc9922db1826807029b8ba5e": "0x0000000000000000000000000000000000104d61785f43727970746f7a696c6c61044d6178001c406d61785f63727970746f7a696c6c613a6d61747269782e6f72671963727970746f7a696c6c616d617840676d61696c2e636f6d0000104043727970746f7a696c6c615f6d670009406d61785468656f00", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e866dbe58dd02dc15480a8c33e4f8c5fe4fc96bf837793ce57e7e01fc24f3e49380c1da287dd0942": "0x000000000000000000000000000000000011506f6c6b61646f74205065727369616e0e4661726465656e20486171756500001968617175656661726465656e353040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e86ac2d54fd84df0f4914e62f037cdb798c40ea01fd56e555b77635e0e9b7175b98bc9514021756c": "0x04040000000200000000000000000000000000000000094461726b737461720000001c6461726b73746172313938324070726f746f6e6d61696c2e636f6d0000114044466f726b6c6573736e6174696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8937a43ac980f1586f33a7ca64a28019e30c3d51516a96b2b2ac8686a25b6bed4d8755dc865d317": "0x000000000000000000000000000000000007726f6737333313526f676572696f204420466167756e646573000011726f6737333340676d61696c2e636f6d00000940726f6737333331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8b0540980af6a340eecdc6635148c341055535da240f7acccb21659afb5aee9f9948c99359f3439": "0x00000000000000000000000000000000000d53616e63686f2050616e73610a416c656b73616e64720000177361766368696b2e776f726b40676d61696c2e636f6d0000104063727970746f617065735f6b736d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8ea76be2017f4a28655c4ccb0364b450b7d2061b3c8dc099342216338374f2480b91cdb49c1033a": "0x040000000002000000000000000000000000000000000a6f67756e6b7563616e000000146f67756e6b7563616e40676d61696c2e636f6d00000b406f67756e6b7563616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8eb9b60e1513484462331eafa624d8d83071075364f17bd15016b013864863fff94db04a29deb56": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000a4d4943484953414d410000001a6d69636861656c2e7361726e69747a40676d61696c2e636f6d00000e406d696368697361726e69747a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e8f8b7184f9a04c0ca72d01b6c36c383e4ba984681b7b467dafefec8f44dab1ed507ae6ab2704c30": "0x00000000000000000000000000000000000a307854617973616d610000000000000b4030785461796c6f725f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e905397499085a5cd08b2f1e5fe95f103948c86163819e4cc144ab447ba4018277b63592ab942b29": "0x0000000000000000000000000000000000076e69636e616301136e69637363726561746976656c61622e6361011a6e69637363726561746976656c616240676d61696c2e636f6d000011406e69637363726561746976656c6162000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e907703340da1e8f2e0b113a373a48400516429c6d481bc521ae1784536e67ad6208da18d4d0df19": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f32300f42494e414e43455f4b534d5f3230000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e93245b557944f937e6a72893ffcd787d41621e01d10074d0d1425d910ed402a489111173fec4113": "0x00000000000000000000000000000000000e4173686c6579204475507265650e4173686c657920447550726565187777772e7468656173686c65796475707265652e636f6d011b6173686c6579407468656173686c65796475707265652e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9422a057a1bb64b70c74263021641934d8ead99b5f41c35cef39e6381314c3b0818941196cebb35": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f343900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e944e964592233816e6a5f27e6e082241bacc990628ee760ceaee069a8a67c753d8018f040f31703": "0x00000000000000000000000000000000000b526f6c6d696e61746f7208526f6c616e646f010119726f6c616e646f676c7a3139383340676d61696c2e636f6d00000c40526f6c6d696e61746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e94531e277a1ad52dcb38c186bf97625f108b4832981d966ebed50d939349d4437a6f538d40d5676": "0x040000000002000000000000000000000000000000000f57696c64436f7573696e2e636f6d0000184077696c64636f7573696e673a6d61747269782e6f72671c77696c6c692e7365726b6b754070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e94ce4f5193d45cf523700038ad442ddbadaa480e8faa91c55e9c0c4af0e2f76fa05c0a69065bb72": "0x00000000000000000000000000000000000d426f777365722053746178780000000000000d40426f777365725374617878000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9521ce485bf220366a4d150e1799ed9ffa721e7e95397c4484db801fb7f26fbc4f27e1d158ef839": "0x0401000000020000000000000000000000000000000004545831000014406f6c6567616e5f3a6d61747269782e6f7267116163656f6c6d4079616e6465782e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e95a2208b7916b225ce252657fba00b03c44e644c81a7c49f72fa99ec13aad281507b60c599bb82b": "0x040400000002000000000000000000000000000000000a6b61796c6132303231000014406b617977616e673a6d61747269782e6f7267136b61796c61406c6974656e7472792e636f6d00000e406b61796c6177616e676e6f77000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e964b9924326e5859a226ee3bd37742f15c3dc4d267c60397718524d88a1fcab129877e2933c675c": "0x040000000002000000000000000000000000000000000d4d616e74726920436c6f7564000018406d616e7472696e6f6465733a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e965b8ae173f1e967eaf727c21c8d3283dc379bd1241c2ac3ac744966bf2412ae8d7979a87894550": "0x00000000000000000000000000000000000d426f726e20696e204d657461001e7777772e696e7374616772616d2e636f6d2f626f726e696e6d6574612f0015626f726e696e6d65746140676d61696c2e636f6d00000c40626f726e696e6d657461000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9705190c69f75e984a135c14c92b678df586c20c8e3ca3511043f0dc8bfd88017d0bb97bfcff63a": "0x040000000002000000000000000000000000000000000a476f6c44204a615773000000136a61756d6540676f6c646a6177732e636f6d00000c40476f6c5f445f4a617773000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e98578a74df70c3f7ef355626ce3b4bc8af2d9db491ff132f0127fbee6133a00ed09ff161fc2f70c": "0x040100000002000000000000000000000000000000000f4a61656c20522e2042616b617269001868747470733a2f2f6a61656c7262616b6172692e636f6d00166a61656c7262616b61726940676d61696c2e636f6d00000d406a61656c7262616b617269000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e991a1b779e8a17838ae9a751c06cfc8b4bfb06f4d0b8d88df80fc88317415ad6f1b9bb6ca114941": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e99a82a5baf61a80de039a1751705e01c71d2be0ba56442f016e7cfbd1f71e9fdf4d0dc0ededf87c": "0x00000000000000000000000000000000000e45766572647265616d536f66741145766572647265616d536f66742053411e68747470733a2f2f7777772e65766572647265616d736f66742e636f6d0000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e99e99015b0c69cb32da9fa3f73d7e9b211d6808b7bd15d9daa8a7372b48c13322a7371190793f0a": "0x00000000000000000000000000000000000b4b442053696d706c65780000000000000b4068756d626c656c656f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9a6cafc1c447d4fc2a82d0740d343bbcf853665019f2afe81ddeb884f76dbb5c74533610f72a732": "0x04000000000200000000000000000000000000000000114c65707265636861756ee29898efb88f00001c40706f6c6b616c65707265636861756e3a6d61747269782e6f72671b69726973686c65707265636861756e4079616e6465782e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9a810681c9b059d2a343a2b14c98d087a4cea739c23d62d9db79ed4933881d78a3ac20bab83766f": "0x000000000000000000000000000000000008506564726f203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9a8697c66e5c9b7b8e39e87c0fec96f7d012d31a4c27b44bfb504ab359662112e4270e380c84341": "0x00000000000000000000000000000000000f647a6d697472792d6c61686f64610f447a6d69747279204c61686f64612068747470733a2f2f7777772e636f6d706f7361626c652e66696e616e63652f1b40647a6d697472792d6c61686f64613a6d61747269782e6f72671b647a6d6974727940636f6d706f7361626c652e66696e616e636500000f40436f6d706f7361626c6546696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9a938ca9a4abd3102b2b0de562a79b5ad9c666c3f9e7752955f3b2c2b4a17c71125b2668ea9ce5a": "0x0400000000020000000000000000000000000000000007676c692e616c00001240676c69616c3a6d61747269782e6f72670e6b7573616d6140676c692e616c00000a40676c696f63797465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9a948cc19db68dda45d1343d565c182e0e1cd3da2d6c0b1ab5b17a77ca165457d9620db19439a64": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9b38311201d0c95cc79494a220a3cbaeb376cb092a438dffe13a31923d884592f34bfb0c4a8a447": "0x00000000000000000000000000000000000c576f6e64657277696c64730d4a6572656d792042616b657210776f6e64657277696c64732e636f6d0020776f6e64657277696c6473406a6572656d7962616b6572617274732e636f6d00000a404a6572627a576565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9b876e9759b44dcc4d56916477150c0fe18c59b3fc21ed58a435a7fbf27c391353a1a4bbf90d305": "0x00000000000000000000000000000000000552616b750552616b7500000000000840307872616b75000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9c3058e8b7da671be86d32d322797f67dd5d386d29d8285cb32504a767956fc58ed8f04ff703c4a": "0x04000000000200000000000000000000000000000000057475677900001440747567797475723a6d61747269782e6f7267107475677940616d666f72632e636f6d0000094074756779747572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714e9e499f3604f59e52c7807a22744a056fbecff1ecfbe7eba8b1936dde4dc054417c5cf2562bc2b0d": "0x0000000000000000000000000000000000154f6f2d626c612d6465652d6f622d626c612d646105f09f94a500001a6e656d6573697364656675656e746540676d61696c2e636f6d00000d406b696e676d6f6f73616d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea141d97c8b7bff6a84f5ec52d8e52699f686e95df25a2350fc0b43df597617b09e8f0a5e45be779": "0x0000000000000000000000000000000000064a6573757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea37edebb810a51f664657582db1ee9d6b05c183b0bf9d05794c88b96fd98ffabf1e03524a079f07": "0x00000000000000000000000000000000000c5068616e7461736d616765001e7777772e696e7374616772616d2e636f6d2f7068616e7461736d6167650000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea3dd7f24f32b641be7ed37a86e99b9c1197ff8fa3a5e4b6403b540196f6cd09af2fbc43ea9a5773": "0x0401000000020000000000000000000000000000000011776562336974616c792020203b2d29290a776562336974616c791f68747470733a2f2f776562336974616c792e706f6c6b61646f742e70726f0017776562336974616c7940706f6c6b61646f742e70726f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea41c7234ed3632dc50f089e43c19f3f4ce606cd994bbecc50bf8dc53e970c0c1c592304f651966f": "0x040000000002000000000000000000000000000000000f466f726b6c6573734e6174696f6e0000001868656c6c6f40666f726b6c6573736e6174696f6e2e696f00001040466f726b6c6573734e6174696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea5174161abd84b3180e530fef04fbbe11194fb02ee20db23f2c6f1d5ab928cca1e1c6b4c1d9812b": "0x0000000000000000000000000000000000086d796b736d363900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea659cd23e1b406c58efadc57a1952fc5829948986e5b86e2b7873ee16510800628e8bfd0344ac5a": "0x040000000002000000000000000000000000000000000d444f545f4b534d5f504f4f4c0000001577696c6c6f6e6c79323340676d61696c2e636f6d00000c4057696c6c79536f6e3233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea6e9e7ff4584b959e5ba1a3731a16d3b5c632a184389a6e63f53fd33bc1f099f8973549b2e45818": "0x000000000000000000000000000000000009537469636b69657309537469636b69657300000000000e40537469636b696573524d524b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea707eb9aaeed5b71ecccf5102c89a45733719ed85e43885b5354623e6e90ccc488ba2773a6d737a": "0x000000000000000000000000000000000007425453756c6c114272616e646f6e2053756c6c6976616e010117627473756c6c6976616e393140676d61696c2e636f6d00000e40627473756c6c6976616e3931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea93374d7f1324e97e131d8f9ad19a2ca2dde965022455099c4e35f369fab9a66717bb32dc5b821c": "0x00000000000000000000000000000000000a5a454e5449454e54530b5a454e5449454e5453201f68747470733a2f2f747769747465722e636f6d2f5a5a656e7469656e747300145a454e5449454e545340474d41494c2e434f4d00000c405a5a656e7469656e7473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea98afdd050adf1030b7a3a137092d0c4a8f82cec3a75dedd955c4f0547467e659c07dacbf787f7b": "0x00000000000000000000000000000000000644584d4f4e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ea99648ce61b6d52d86dba437fa4388bc312e57328e808cb1d37cd49143b90c338714703867edd7a": "0x0400000000020000000000000000000000000000000015f09f8d8041524953544f5048414e4553f09f8d80135079746861676f726173204361706974616c1f68747470733a2f2f7079746861676f7261732d6361706974616c2e6e65741b407079746861676f7261732e632e693a6d61747269782e6f7267207079746861676f7261732e6361706974616c40747574616e6f74612e636f6d00000e405079746861676f7261734349000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eaa1427619fd84d8aefc61195d8e3f213b241816aace9f79fa086f868616c9892555158be75bc252": "0x0402000000020000000000000000000000000000000007537562426f78094b6576696e53756e1b68747470733a2f2f6769746875622e636f6d2f7375622d626f7814406b6576696e636e3a6d61747269782e6f7267126e6f346c6f6e6740676d61696c2e636f6d00000b406b616968756173756e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eac64c1f4e558ab7d60c75740987ee89dac9107fb640ad94539c0aa174a045bfd788ba367246c00f": "0x00000000000000000000000000000000000d4d756c6c65722042415349430e446d7974726f204d656c6e796b0000196d64622e63727970746f3230323140676d61696c2e636f6d00000f40446d79747279694d656c6e796b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eacb05ddd012a5e58ed26dda286bde16d2dd807510bd269c8cebd598bbc85a528a87ce2a86123123": "0x00000000000000000000000000000000000c435f70657373656c6c696e0a63726973746869616e00001d63726973746869616e2e706573656c6c696e40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ead73865098b4e268cbdf5f8b94b1e3e50d5258a934f3f005ce2ab97c47af0fae918b1135e29b67c": "0x040000000002000000000000000000000000000000001452656b7420537472656574204361706974616c0000174072656b747374726565743a6d61747269782e6f72671872656b747374726565746361706974616c40706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eada65ead440e226c0e28f6cce9440f36b1e0218286e2d618d3a96c63321eeafc17aaeaa627bbf5d": "0x0000000000000000000000000000000000115468654375744c6f737353747564696f115468654375744c6f737353747564696f155468654375744c6f737353747564696f2e636f6d001b7468656375746c6f737373747564696f40676d61696c2e636f6d00000f404375744c6f737353747564696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eb447064e6bf7505cec975ab53753aa239ab05d83392a564b6b26fcde4b1e07b1e5a692d011e3428": "0x040100000002000000000000000000000000000000000f4d696775656c204d617271756573001d68747470733a2f2f74696e7975726c2e636f6d2f7963626f3479786315406d722e62726f776e3a6d61747269782e6f72671b6d696775656c2e6d617271756573373040676d61696c2e636f6d000011404d696775656c4d6172717565733730000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eb7cf6adf6bf0eeb8a69eee1f91f7a4c18dd0f200bf9dab5149f0b5131d144024fd8d91fce375860": "0x0000000000000000000000000000000000164d79427572676572427261696ef09f8d94f09fa7a0001b68747470733a2f2f6d79627572676572627261696e2e636f6d2f00186d79627572676572627261696e40676d61696c2e636f6d00000f404d79427572676572427261696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eb8a84fc1f2672fdf6eed613aedc88afa977c2982319ee6fbaf9aec7f8a285ce88f08c0dc84d4b0a": "0x0404000000020000000000000000000000000000000009717571757a6f6e6500001540717571757a6f6e653a6d61747269782e6f7267116c656f406c6974656e7472792e636f6d00000a40717571757a6f6e65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eba9e3af1be4519454d7eca7197b7feb6cc79725fcf5b873f1495add94c771682584d7d254163713": "0x00000000000000000000000000000000000a476c6f62616c45524e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebb9d8077a7da3fe98672c4edf6d578c3151aa2e8d55431cc874360eff95c4592d917fb09a6b6316": "0x040000000002000000000000000000000000000000000a4d61676963205461620000001564656e7665727437383440676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebc3901876e1bb583cdf41f721ca5269ae0eeb4343cb60721fd8cbac7022328cf959d7c3e728d969": "0x00000000000000000000000000000000000547656172184765617220546563686e6f6c6f676965732c20496e632e1a68747470733a2f2f7777772e676561722d746563682e696f2f001368656c6c6f40676561722d746563682e696f00000c40676561725f7465636873000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebcbc6c0c66547df8c4c81f382ae2c201eed4b0b519f352aa9c0c8593122418b30ac9760844de2fa": "0x0400000000020000000000000000000000000000000009436f6c6f73737573001a68747470733a2f2f636f6c6f737375732e6469676974616c2f1d40636f6c6f737375732e6469676974616c3a6d61747269782e6f726716696e666f40636f6c6f737375732e6469676974616c00000f40436f6c6f737375734974616c79000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebe794990a349ea52ee8bb0f7ce771455d55e6bb0908b243c0c4805e6733c0ebbd91bea2ff5a4526": "0x00000000000000000000000000000000000b6a75636163656a75646f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebee8c2dc7e37890e84b20a21cd1f35835bb85d8e27d3b6d02bf08300998555443ec4cd3206ec37a": "0x0000000000000000000000000000000000114a757374696e65204372757a204172740d4a757374696e65204372757a010115726a6e65706f6372757a40676d61696c2e636f6d000010406a757374696e656372757a617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ebfc2e29a73f2803cc1ba006a1715e894b621a36169165cb72343b1c6ad4ba2230d394be4033a645": "0x00000000000000000000000000000000000e7765616c6c64697361677265650000000000000f407765616c6c6469736167726565000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ec33a2010bbc1c6a108079cf7fc4da7010feec2a6d3435947ca526d185fffa4c13b816eb9d38a107": "0x04040000000100902f5009000000000000000000000000000000000000000000000000000000046d656c000000126d656c7a406c6974656e7472792e636f6d00000b406d656c5f7a686f7531000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ec3c3e9502045f3b68c1fc61924efb992b4e4c2c7a21d528dca21d3073fd304f536fd99a5cf1794a": "0x00000000000000000000000000000000000bf09f9088e2808de2ac9b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ec423cda65dba1eeb21a6e8672731908c93ced8be633bb99e8535a8af267463d92a2dd37b6999e4d": "0x000000000000000000000000000000000011f09fa5b04d414d4143495441f09fa5b000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ec514a5caaf1ccf5be28e6585d6eba8b92193cdbeaa65fbb64f3b22a2f3043481f088e875f8fb816": "0x0000000000000000000000000000000000086265656a616579094f6c616b756e6c6500001262656562616e7140676d61696c2e636f6d00000d4067616d656f666761696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ec9971789d54b940607b422f959ab305856c1621be625a1776d2ffddfac9a03446da3052d7cd3a58": "0x0400000000020000000000000000000000000000000009434f5645524c4554000013406164653030373a6d61747269782e6f72671461646576617261747540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eca845b41c8481b56a54690cc83eb7ead60699dddf84173f229fc713de735bc849b0b5d0164d971b": "0x000000000000000000000000000000000006676b686e3000000000000009403078676f6b755f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ecb301dad8fcf04b9e1f6008fd792e78fa56b6ae00b4f8b73b98d260ad04b38623d1a3423ada0957": "0x0400000000020000000000000000000000000000000004616e790000000000000a40616e796441707073000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ecc10f82c1c9c473fe7ecf56bcdfd2f5c5570574eb8971fdc5b2ff7d929767b730066666a1493177": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eccde6810f3e4a3bbae434c3ce18cf1d398e23149fcc31fd5997284a7812839ca3bd6b477f449565": "0x040100000002000000000000000000000000000000000b4a6f736570685f4144561b6a6f736570682073616e6368657a2076616c646562656e69746f1768747470733a2f2f6269742e6c792f334d614f675741001b6a6f736570682e73616e6368657a2e7640676d61696c2e636f6d00000d406a6f736570686873763231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ecd56384808aea349692fa834a36faff24619a5a9559ce35082ea5247cfb0657e8ce2fe5fcce2d3e": "0x000000000000000000000000000000000007534b554c4c5a0000000000000c40534b554c4c5a5f585858000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ece0cbfbc8b2ac0fb69dfe53765f807ba212f4c0f8c5f2c557143761c734f58ab36f1a584d77592f": "0x0400000000020000000000000000000000000000000019f09f939c20486f6c7920436f6e73656e73757320f09f939c000015406d6f67696f6d616e3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ecf2bd08370f7bd96c1c4ce21343d4de9268561b0872178a5f017362e2632e6d4019b17e73fd9a5b": "0x04010000000200000000000000000000000000000000134d2d5665727365204152542053747564696f064e696b546f18687474703a2f2f7777772e72617269746574732e636f6d001a646d2e646f6c676f6c65742e62697440676d61696c2e636f6d000011405579326c384547644677514d4c474a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ecfb9de5210ebb4164f5867915d7d9c1a1f95f772891efe46ada7f2c25a7124c55c7d08bcada7250": "0x00000000000000000000000000000000000a536576656e2041727400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed170e36fed4d7829c7c545141ea2dd84fe5ef7d567ea450f59967e7afa68e5f1ff7f7c46db19627": "0x04010000000200000000000000000000000000000000085032502e4f5247085032502e4f52471068747470733a2f2f7032702e6f7267000f6c657473676f407032702e6f726700000e4050325076616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed2422d97d69412f3848140170bdea2ed343c6cde80ba53793d9158f57f7160e5f5d78b1ac2ae124": "0x00000000000000000000000000000000000c4d61657878696d697a65720000000000000e405f6d61657878696d697a6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed256f19624cd5e520bdacc287bbcbea07e8fad8f43e5dcb222c425acd92d88da92131542f706827": "0x000000000000000000000000000000000006534b41455201010113736b6165726e667440676d61696c2e636f6d00000b40736b6165725f6e6674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed28496342047e2cd2a250fe4fd3437ab1adf1aaecfa369933dd022c08ca5c5718a4843cf7fbfe32": "0x0000000000000000000000000000000000076b7573616d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed2ea848bf9923e24a53c0383caec5273b6cd82cd4c343130767c2550df0fec0c5c7c76db58ded61": "0x00000000000000000000000000000000000d466f756e646174696f6e2e5a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed3dc3fca3bb7956b608ce37459ac5d38405203ab8b429207b21fe8aac7ee28aa964da0ae12fc970": "0x0000000000000000000000000000000000116b616d616c61696d6d6163756c617465124b616d616c6120496d6d6163756c61746500001b6b616d616c61696d6d6163756c61746540676d61696c2e636f6d00000d404b616d616c61496d6d6163000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed614c0e929782758c5359d2bdc1550dc83587f9fca8a411099eab04cc37f8d3480c0bc2daca9f4c": "0x00000000000000000000000000000000000f426c6173c3a920426f6e6f626f730000001b626c617365626f6e6f626f2e6b6e667440676d61696c2e636f6d00001140426c617365426f6e6f626f734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed61cc174562abef5a9635e41381688cc05f8f2a2abc1d3a020f4f6726998721f201a3e3fe061336": "0x00000000000000000000000000000000000e4b5553414d41205748414c45530e4b5553414d41205748414c455300000000000e406b7573616d617768616c6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed782455066cea4ee6f56f064baa721a0d8d32e52c80ddcb1f3ec711b3535f6ab6ee30510b88824c": "0x0000000000000000000000000000000000064162616e64000f68747470733a2f2f612e62616e640000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ed9f378fe91a8125c4de4f9f5568e51e59a99d289673364dea82a180b4cff619e121c1ebf4e42735": "0x00000000000000000000000000000000000b43727970746f436f6f7000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714edb9597552dee00bf6e36d6ffac19bf2cde9b8a6189939d02019b614729f72aa3fb4e95c5460b95c": "0x00000000000000000000000000000000000b505249534f4e455253200a574f524c445749444500001b707269736f6e657273776f726c6440686f746d61696c2e636f6d00001140707269736f6e6572735f776f726c64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714edbd8e7a024325c3c0b08670875a44574a20f29df8e415a84e87548aee41a90dca4de6dace851c06": "0x0000000000000000000000000000000000057065726c000000137065726c6c676c6740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714edcb62732d88d5a1983ac92a9005b595553a62a3522499a38af23ae77e0c71f3b617abf004147e5b": "0x00000000000000000000000000000000000f5041524954592054495020424f5400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714edd6a8685a4d3345b2bc481201f051dc46499103c6d0947c70967af1dcfacc2b34f5a1065256303b": "0x00000000000000000000000000000000000f416e64726561732053746f636b200f416e64726561732053746f636b202068747470733a2f2f7777772e6269662e64652f616e647265617373746f636b0011706f737440726f6c6c737465722e646500001040416e647265617353746f636b3135000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eddc9e78603ad40bc8ef2ec23b4f86d82dce53a0569f1f1f1cac8b7eac2a36aae89ab1312720d51f": "0x04050000000200000000000000000000000000000000046d616b00000013746f406d6f7264616d61782e6f6e6c696e650000096d6f7264616d6178000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714edf0122a60d52d7dbc5054d8ce14774d438c9376642f6410f0ec0f9b02c20247923889ec58250227": "0x0000000000000000000000000000000000044f62690000000000000e404469676974616c706c75746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee0ce2c47daf1aaa5268f1c62243ca2f0e0ca3c43ac74c89c4d4f2aaf3135d5922b38679523b5704": "0x00000000000000000000000000000000000a4675747572654c656f0000000000000b404675747572654c656f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee0e3a74bdfdeb1c92346d7a04f8c10608fff8e59d18ad02f32d018f562d61d58f7b4ed9d42b9602": "0x0000000000000000000000000000000000084b616c6541727400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee2bc658fa0d1fc5fa8edfccb16e4748eadc9c5ec4e84fa3f9cd096b78dc8b6fa28b06e0b4945c31": "0x000000000000000000000000000000000013524d524b61626c65204372656174757265730000000000000e40524d524b61626c654e465473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee37cb203df4b717dae56db2d898e18d0a96a0db1732e27d6c8d2a448649348b3d7b2b7a8b819e00": "0x00000000000000000000000000000000000459534101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee577071e47d1ba7b8a40f17f9fc62194fe1b12c10e8a2bfb5efc7057b119f4ca3b05ba96eb7da6b": "0x040000000002000000000000000000000000000000000b7374656c6c61726a6574000017407374656c6c61726a65743a6d61747269782e6f72671762696c6c69626f6e7337373740676d61696c2e636f6d00000d405a616b68416c656b736579000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee7dbc12bc9252112ebd1171c5fcf0d3387bce6cbb7119410ca169b272b310775b1816de710d046c": "0x00000000000000000000000000000000000a444b2053747564696f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee8578075072e96cde26e94d5a74a70872172314f92fb0fd0d1c9fe186c38b594ad50e6079ca1218": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee877a7a3953392aecdb6dcb19a0a30a0007a4cc863d9a3079801900d0e26493a9712f3a595c276c": "0x040000000002000000000000000000000000000000000d424245574f4e44455246554c00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee89fee2b887b471a8274537b1ed72b005b2ae6e3c0e14273235d9c5556ade786172d842a2059e3d": "0x040000000002000000000000000000000000000000000a50726f66696747656e0000164070726f66697467656e3a6d61747269782e6f72671564696d61676f6c796f7540676d61696c2e636f6d00000e405a616c613131373634333039000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee9086e3eb095e4cd80e7cac81873a2f2b98cbe3f9a22fb2c640721759559dc7c074f558f274450e": "0x0000000000000000000000000000000000084269677a696e6501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee977649867b775e26f6ba0b2c596d1a471444945c9fdbdfe25e3f8862096f8f6de11d87da1a7111": "0x00000000000000000000000000000000000f546865205068756e6b79204f6e650000001a7468657068756e6b79314070726f746f6e6d61696c2e636f6d00000c407468657068756e6b7931000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ee9be5f0b44a2889287e6f010e50f642775dab59f39ee4de313fe6325181ca603824399cf4d42c08": "0x04000000000200000000000000000000000000000000074d65726c696e000000166d65726c696e6e6f6465734070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eeb1fc610455dcdf22e0d42710f5fd45705ee39dadbc4a849457777499de8e0b28099344dc31dc53": "0x000000000000000000000000000000000005446f677a0000001763687670786a787264766e406f75746c6f6f6b2e667200000d406d786e65796a787264766e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x040000000002000000000000000000000000000000000d506f6c6b61646f747465727300001440706d656e73696b3a6d61747269782e6f72671c706f6c6b61646f74746572734070726f746f6e6d61696c2e636f6d00000f40506f6c6b61646f747465727331000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eec1d763f95c70cb16eaf9666bd95a04bc6ed619c30a4809a43fd7265e414284c11b27b8c666fd23": "0x04000000000200000000000000000000000000000000084b686173746f72000014406b686173746f723a6d61747269782e6f7267127374616b65406b686173746f722e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eeca900939080fcf9e4e11a50a1089b5e3c69cc838363d16616d94d9efb701ff2f53c08da7fd8062": "0x00000000000000000000000000000000000c46726f7374587472656d6500000000000010406c756361735f6b6f6666656d616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eed3ee9b432687319609bc709020ebb74d5976e8a8632dddb6575b2faf53c0fc541578a0f67ec933": "0x0000000000000000000000000000000000104b7573616d612050726f706f73616c21476c6f20446576656c6f706d656e7420466f756e646174696f6e2c20496e632e1b68747470733a2f2f7777772e676c6f646f6c6c61722e6f72672f00136a65666640676c6f646f6c6c61722e6f726700000b40676c6f646f6c6c6172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eed7b5cd81ad90b934bc724bcd5c1a70cf8b27cee684404418666711f575d681780171cb7a1b6238": "0x040000000002000000000000000000000000000000000a66696e616c6269747300001240617269666b3a6d61747269782e6f726717696e666f4066696e616c626974732e6e6574776f726b000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714eedb21dd29e41c9e08862e05b832f2754899119b7a1c9ae77b3a70f67950ba318a4381a78eaa3b57": "0x0000000000000000000000000000000000095361736861646f6b0000000000000d405361736861646f6b4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef04f719a88861a1b08e12e3ae9711ae774eb42da22da000579ed96da9412dcf15c934e7072c287e": "0x00000000000000000000000000000000000b54776565747962697264000002400240000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef0a650cbf57826cbe5a0623e6c466eb58b6768fa79f2844a7c3bbec1fbb686efb86159d2884aa10": "0x00000000000000000000000000000000000c476f676f205975626172690000000000001040476f676f5975626172695f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef1664294ee5e16e2e266f5e99f682a4439635c39dd3a9a0d8b35131cd0191ae0874b84c472b9e54": "0x00000000000000000000000000000000000f4d6f74696f6e2041707065746974001f68747470733a2f2f7777772e6d6f74696f6e617070657469742e636f6d2f000000000f40417070657469744d6f74696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef171686ae87d77572062f1b364867349593e0708e8b30cdc6f7bde5604d422bfae96ffcd2122d07": "0x00000000000000000000000000000000000830785369676d6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef2cb41d52259dc702d45a8cec8dc7ffa0ea3341fece5555c72125cfcb5f1664526b3b67bacee47b": "0x000000000000000000000000000000000008612e6b6976657201010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef545c0b52a14ce5fc8da8cd554b5256f00c5e43f8a30b62f77e2d9b34730eb823e819e141c029b1": "0x0400000000020000000000000000000000000000000015546865204b7573204b534d2044656c656761746500000016686579407468656b7573616d617269616e2e78797a00000f405468654b7573616d617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef58128d4ea34ecdcee02f04a44b248f0b7d6cf65d98e1cf6206e73af3e3bd66b2f9a3a9aafc573a": "0x00000000000000000000000000000000000b417263686976657273650b41726368697665727365137777772e617263686976657273652e61727400186172636869766572736538383840676d61696c2e636f6d00000f4061726368697665727365383838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef6f4d8caafffa157a4a576c540eec2cc92a7b102e14205d349e8cb1fad5c68ba8eaba619031b820": "0x0000000000000000000000000000000000106b72616b61746f612d7061796f757400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef7c516a16dc564edcb79cfb39e4a600a5f4782e73f48a4810604e9271ab8e26fb588f0ef4c6472f": "0x000000000000000000000000000000000010546572726120496e636f676e69746100187465727261696e63756b2e62616e6463616d702e636f6d001b7465727261696e636f676e697461756b40676d61696c2e636f6d00000c407465727261696e63756b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ef8e518f1522f7a6266cdd851a163dbc01f5c86d9c37b330e1a7bc66adef3ebbc6d59e2c1e61007e": "0x08000000000100902f5009000000000000000000000001000000020000000000000000000000000000000011475241424249545920e29ca8f09f9087001568747470733a2f2f67726162626974792e6e6574154067726162626974793a6d61747269782e6f72671368656c6c6f4067726162626974792e6e657400000d4067726162626974796e6574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714efed57a5e9a3be1756825262aeddf95b1791f9553de6d166e7d00f337e6db4e9434714bc1164ea01": "0x00000000000000000000000000000000000a446f7473616d614d580000000000000b40446f7473616d614d78000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f01934f45473693bdc53fda731682da4b15562fd4fe5007eb94dc36215862ca3c59cbb2a13ce6941": "0x00000000000000000000000000000000000f536f756e644f6653696c656e636501010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f03497ce90d500570e687e3b4f19439aaa16f96132712ef6b7da695e0fb0844ebd9d0e8b901b8b6a": "0x0400000000020000000000000000000000000000000004303430000000143034306e657430343040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f035a0d786dbcf44868cd54faea1a0e45836635b2bf658733436ec69c5567d651be592392cbb69dc": "0x040200000002000000000000000000000000000000000d5374616b6572205370616365001568747470733a2f2f7374616b65722e73706163651740676e6f737369656e6c693a6d61747269782e6f72671368656c6c6f407374616b65722e7370616365000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f048620c32a1d7b6f420fff29f5ae4603668ff450ac4cbb0e7159abd5f5c094c552414a235452940": "0x00000000000000000000000000000000000b616d70657273616e64690a4150204d7572726179000016616d70657273616e64694069636c6f75642e636f6d00000e4077656973656e6865696d3372000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f04f158721b89173b8ab024c586021c3755f9a592871796b7cf47213b9cf94534dc45e86e5e10e55": "0x00000000000000000000000000000000000a6475636b77696c646500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f04f805bb261ed68c0c8a73a690ab59186f16852e70a2406e1690d7d6f18419d0599f6a77a67ff64": "0x00000000000000000000000000000000000d4475627374617264204b534d001568747470733a2f2f64756273746172642e636f6d001c4578706563744368616f734b534d4064756273746172642e636f6d00000a406475627374617264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f04fc71c9051dc296467fd4e7038b925c2422357380d8cc0c5f17d272f639af8fcfd1f1156de7040": "0x04010000000200000000000000000000000000000000087265616c6761720d706f6c6b61646f742e70726f1568747470733a2f2f706f6c6b61646f742e70726f14407265616c6761723a6d61747269782e6f72671368656c6c6f40706f6c6b61646f742e70726f000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0548bed301be4ead497f54d401fe4c1ef4db2cba6f186f4404256684bf2a521ee1a996f8ed41717": "0x00000000000000000000000000000000000b43727970746f5f4d616d0c5265616c204d6f7468657200001843727970746f5f4d616d6d6d7940676d61696c2e636f6d0000104043727970746f5f6d616d756c7961000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f055b74881490c4efee7b1c489dd25c0a0e860ddf45d685ae6f7dc9b2653833fad6f6df61dc52313": "0x00000000000000000000000000000000000a506f6c6b61746f646400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f092b7bcded3683bf06c3b60a5829f2e3712cbd93b0e13ff0c3501636335339563df022ab1a7f16c": "0x00000000000000000000000000000000000941565645204152540000000000000a40617676655f617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f09bc0b626451c722aa5ba3cdeeff59135a45ca06af01181ad0015f5faf0161a5a9b9c50af228526": "0x00000000000000000000000000000000000e524d524b206f6666696369616c01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0a0c6f78c3f1dec12210b384d6a6efb1d26a87c58d54edf034e8808df223c74b87ad9d798204b3c": "0x0000000000000000000000000000000000074b6f6f63757500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0a750638d9b7c707658c8264ec0bd92d2493d772b1a6cc1fb7c338f08bafa4338b82e25a6543208": "0x04010000000200000000000000000000000000000000076b6c65766572001268747470733a2f2f6b6c657665722e696f0013666565646261636b406b6c657665722e696f00000b406b6c657665725f696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0db9ccb0fefbacde2016ad920a3b5d87e07a224e968ab74fe1e802a77c02010a7bd84a9e1cc853c": "0x00000000000000000000000000000000000b6e6b6f6e756b6f763834000000146e676f72656c6b6f7640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0ee0b687c5103e11ea2e788aba3561f0b05ba66ceb0aa5b95d9bdef6217e73e2685d744ab28dd64": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f0ee90ce47dd48389a46e76d7d1df5103771b0336b07765a168d2c4a123d08960b3577b39d6e204e": "0x0000000000000000000000000000000000075061706572730a5061706572732041471268747470733a2f2f7061706572732e63680012636f6e74616374407061706572732e636800000b40706170657273446576000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1018912203e086b3aa5bd02bbd345acea759dceec1e03e25dc20c3d42fa2518ce315721407fa371": "0x00000000000000000000000000000000000c4b7573616d6f6f6e4e46540e4d616e75656c204f6c6d65646f0000166b7573616d6f6f6e6e667440676d61696c2e636f6d00000d404b7573616d6f6f6e4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1173e4bb4bde3d2f4681dada28e955e70d77fb8ccc3286d5028f0c415be18f6068cd97d921b5824": "0x000000000000000000000000000000000008414b524f20445605416b726f1968747470733a2f2f6c696e6b74722e65652f616b726f64760011616b726f647640676d61696c2e636f6d00000940416b726f5f4456000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f11f6c8614e661cdd26b6521fa6c7f27940601187600f400efb32375537a401099a582b9c65e0e76": "0x00000000000000000000000000000000000456757300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1352327dc3be8a0948223bb2e7bcc8a55be248add34b625c1c0826c58fe037fa5c8e4591440dc59": "0x0400000000020000000000000000000000000000000007456e7a6f726f00001540726f6d616e7631383a6d61747269782e6f726715656e7a6f726f2e64657640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f141bc71dafe807f7cd5f5ff9b7eefb11b8b32c1bb1e1fc63c08019d81124b3aa85f24ae8c779a31": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000e546865486f646c4661746865720f41726d616e646f2043617374726f00001861726d616e646f63617374727040676d61696c2e636f6d00000f40746833686f646c666174686572000e746865686f646c66617468657200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f15d5a7f73cec4735a5de862f77220d0aafd75335f986fbc18bb788aa8c4a5b61cc6b46f38a6dd58": "0x0000000000000000000000000000000000094d69636f6c656f6e0000000000000a404d4943304c45304e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1697a69799d08e44211b834beac4f35ff92e0dcbb0167f6ae7a0c43b186727d581d3f69f10fea34": "0x0404000000020000000000000000000000000000000021414d414c4c594e20e29ca8e29ca8f09f928ef09f928ef09f928ee29ca8e29ca800001440616d616c6c796e3a6d61747269782e6f72670e616d616c6c796e40706d2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1719675644622b35432349797f86c76049b09f36fe855c53d5bb87271a3186300feee6d2c040f3e": "0x000000000000000000000000000000000011576562336761696c206f66506865656200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f192451ba2e9b123969f7c9e5a153c9d9965ae28a973fdd9ebc270fe431e04396c711e12c6dc2356": "0x00000000000000000000000000000000000b4d59424553544c4946450e4a6f73696168204b6f747a75721568747470733a2f2f6d657461726f636b2e61707000184a6f736961686b6f747a75723140676d61696c2e636f6d00000f406a6f736961686b6f747a757231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1945f40d5dd3f64e2d9b07342518d0e97bc74b6c54b1773db3081792d43ca2b54bf89b80e899562": "0x00000000000000000000000000000000000d4e4654616d61676f746368690d4e4654616d61676f746368691868747470733a2f2f6e6674616d61676f746368692e696f010100000e406e6674616d61676f74636869000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1a63d104e9537d648851bbd377e2584fdfe42e8b048d1537b53bb3d64a1a8eacbfb3dae3032ef79": "0x000000000000000000000000000000000008444f545f4f4e4508646f74206f6e651468747470733a2f2f7777772e646f742e6f6e65000e746f75636840646f742e6f6e65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1aadb00106d1ec596417843ffb52469298959fef42e9153cc81531f708603e74562202f81dfcc0d": "0x00000000000000000000000000000000000a44616573756d6e6f7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1bcbe1d2866fe7bd01ee8b63206f50cc22749524193d58b84608aa3d895d839e42600fba1167261": "0x000000000000000000000000000000000012e0b98c4e657720436f6e74726f6c6c657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1d230b68b13fba664c4ce41b56c68a03cf22a7bb36fcd1a1b8678a37e3ac1dcbe8b354a526bc144": "0x00000000000000000000000000000000000f427566662041726d7320436c7562002168747470733a2f2f747769747465722e636f6d2f4275666641726d73436c756200176275666661726d73636c756240676d61696c2e636f6d00000e404275666641726d73436c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1ea586879f7ec76f5a68515207a31aaa74c335955fe0e59af6323355169fd925e6fe9c60cba58ba": "0x00000000000000000000000000000000000a4e65777420f09fa68e0000000000000e404d7973746963616c4e657774000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1eba20e6d2d881a24558de70c92fafb84da6fc766eab8323bd9329ab7f2d868417418fd32fdd737": "0x00000000000000000000000000000000000e536172697361204b6f6a696d610e536172697361204b6f6a696d61157777772e7361726973616b6f6a696d612e636f6d00167361726973612e6468303440676d61696c2e636f6d00000e405361726973614b6f6a696d61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1fc8f4f6212716380c6961c797a97f52859c85012b39dc1403ea0ef2cde3a48a3ba52a10570f77a": "0x000000000000000000000000000000000005566c616405566c6164000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f1fd5669b551e9dca43b2797bd4dd454d7fb0870a2a4edd62b39eea0801f6baaf09b05c8634b5a25": "0x04000000000200000000000000000000000000000000074c4547454e4400001a406c6567656e64373334313231363a6d61747269782e6f7267156b7572746f736973407961686c6f6d692e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f2148a94f5867abb148a35cad2b2fe9cf6ffe0baf5f4f2f4ef894263baefead0e797a1e3e6d0a07f": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f215e5ad123be565c25d2c8739671f166c3885215a4ce4d6c458d6881aa62a47bc31561b9c6bfe3a": "0x00000000000000000000000000000000000b4e6164696e655f282a2900000000000011404e6164696e654d6f6c6c656e686131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f22fdb49d209542deec7098fe8a74adfd10b30379b411db2b7cef5389c589c6b68e41ca87a28b45a": "0x0000000000000000000000000000000000086b72697875733100000018316b7269787573314070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f23d10c93f96a6ea7a2f3dc66d99575366f71c0de336ae877563eaa12c52abcc227bd8e990679443": "0x0000000000000000000000000000000000054c655469074c657261205400001056767431393836406d61696c2e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f23f862ecfa6f61f9cd77599356c6f5f72c36e612c088e526b92fe762a6a175b387df98ea737fb2f": "0x04000000000200000000000000000000000000000000144a6f726d756e67616e64204c616273f09f908d00000000000010404a6f726d756e67616e644c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f24d4d1adb36534d96f7daa1a00790f8b168d3db7f0175e5f8dfd3430dc7edb4c5b807bce2b9d93a": "0x0401000000020000000000000000000000000000000016e29caa20646f747374616b65722e70726f20e29caa001668747470733a2f2f646f747374616b65722e70726f1640646f747374616b65723a6d61747269782e6f726713696e666f40646f747374616b65722e70726f00000e40646f747374616b657270726f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f25ef82af77881fe240cc50e90684f175ebef583b904fbc0b9aef4b38aaafd53e6436ad3e70ba366": "0x040000000002000000000000000000000000000000000c477265656e20436c6f756400001840677265656e2d636c6f75643a6d61747269782e6f72671f677265656e2d636c6f75642d6b7573616d61406f75746c6f6f6b2e636f6d00000f40477265656e436c6f75644b534d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f268c9b97db7d42c36cd0bf4fb6d819171d9932d99299cc655a5debfb04d20aa5ae23649372e4f0f": "0x00000000000000000000000000000000000b43726970746f696f74610101010100000d404a6f736570526963617264000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f281211dddf4de4c9804585392c70a2327e2f8047f73e66dfefaaf9e9ec544d7694b053774e4d014": "0x0000000000000000000000000000000000144d7920736d616c6c20636f6c6c656374696f6e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f2852cbaf60c5e38269fa27098d88ecb1640185c91860fb62d92ae9a6ab7713c79485bae49862b39": "0x040000000002000000000000000000000000000000000b45584e4553532e434f4d0000134065786e6573733a6d61747269782e6f72671576616c696461746f724065786e6573732e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f2974ec4b5ddb395262da7eeb6f3e8342c04cbbf83f9cbc933d86aa980b53480a9e283668b73903f": "0x0000000000000000000000000000000000044c656f0d4b726973204d6f786e6573732168747470733a2f2f73696e67756c61722e6170702f636f6c6c656374696f6e7300196b7269732d6d6f786e65737340686f746d61696c2e636f6d00000c404c617a795f4c696f6e7a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f2b06e2ea680db3c12d9c0035dd422388e6d346f61df3d9f3667f8ab761c8c57120dd61917976e10": "0x04000000000100902f50090000000000000000000000000000000000000000000000000000000f4e757220736f20616d2072616e64000018406e7572736f616d72616e643a6d61747269782e6f7267166e7572736f616d72616e6440676d61696c2e636f6d00000d404e7572736f616d72616e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f2cd0e6538047668a88e885b627a179f8a843e0765c142ef41b0d6a9c7b0f178fb1c208a1631ab0f": "0x0000000000000000000000000000000000096465636f6d383838066465636f6d1868747470733a2f2f6465636f6d3838382e7370616365200010383838406465636f6d2e737061636500000a406465636f6d383838000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3199d5f1f3efb1568883556ebca8ab4e219f9b9b122deac5f8a041091b7272e68209638c290a757": "0x00000000000000000000000000000000000c56697274756f7a5f41727407417274796f6d00001662626b6472617274796f6d40676d61696c2e636f6d00000d4056697274756f7a5f417274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f31ecd1e7a1b8236862fdfefe655dc35f3ac0b586e274ea252d32e5ad1e189c0b750facc56ed5f2a": "0x04010000000200000000000000000000000000000000104c6f79616c2056616c696461746f7200001c406c6f79616c2e76616c696461746f723a6d61747269782e6f72671a6c6f79616c2e76616c696461746f7240676d61696c2e636f6d000010404c6f79616c56616c696461746f72000f6c6f79616c76616c696461746f7200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f32bbb6fec42f4b03e89cc7fecc4ad46cd7ba606522a8d1679863da498718cf9acdafbde8cfe4b78": "0x00000000000000000000000000000000000b4441524b464f5245535400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f35a7cac67fba21d5aafb1f14904ee2cef477907d825f744a980129c6ff4c0a8a0fdb6279b5ae42a": "0x0400000000020000000000000000000000000000000018f09faa9e612073206820f09fa799e2808de29982efb88f00001c40626c6f636b636861696e637572696f3a6d61747269782e6f72670b314039373130342e646500001140626c6f636b636861696e637572696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f37856c39e7d3aecf6729fb77338a94fd452c6455ced46c78844e967c3d3c7f45e176c38fafcd252": "0x040000000002000000000000000000000000000000000e56616c69646174696f6e44414f00001040786e693a6d61747269782e6f72671b756e6f7264657265645f73657440747574616e6f74612e636f6d00000540786e69000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f37d13738f231aef9448479aee4be9b14df6c206964e8c9a41d990876f3fd02e189c81c7b59bd718": "0x000000000000000000000000000000000011446561642043616e61727920436c7562000000196465616463616e617279636c756240676d61696c2e636f6d000010406465616463616e617279636c7562000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3912249e16d7dcd3c5db0048c1bec2061c55ac6337fd40b995f0c0632c65d2985e607c34564f84d": "0x000000000000000000000000000000000006616d7572690b4f6d61722048616d69641b68747470733a2f2f7777772e6f6d61722d68616d69642e636f6d00146f6d6172406f6d61722d68616d69642e636f6d00000e406472616d75726968616d6964000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3b9e4d61581e2eca44ec60e8eb57e646921f1be1696bb0070169f1b55e6d976ea780ad4ceeaf32f": "0x00000000000000000000000000000000000b436f6e74726f6c6c65720000001464686172723931383840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3bdf92c808f3f22c68d6466972eb0ea83776198b4d770f8ec90104edf41d423329d403f541b5c1b": "0x000000000000000000000000000000000013547269636b79204e4654206f726967696e7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3e3959f84b063bcd6c29a7c39cee45b0e045a94081bc188ef73be2be086d66aefd850fc7eeacc45": "0x040100000002000000000000000000000000000000000ff09f9a804f6e46696e616c6974790f4f6e46696e616c6974792e4c74641668747470733a2f2f6f6e66696e616c6974792e696f124069616e68653a6d61747269782e6f7267156b7573616d61406f6e66696e616c6974792e696f00000c404f6e46696e616c697479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3e86d44b0be98b4a485954cd0953248bfb4b47acf3124fe37bea4dd7436eb7286de6fec053b3437": "0x0000000000000000000000000000000000075a6169626f6e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3e912dce83414234c68f2680db04620157c7367e987bc1b502cc6e1512174de56e7839d05b16456": "0x0000000000000000000000000000000000114572726f6c204a6f686e736f6e204a7200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3f6fc5915e7ebb79c5ccc281c8aadc84dde78cd7904bd5abd05211edb1aff353d9b0ec1455d380e": "0x0000000000000000000000000000000000074865726d697400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3f9a9fea1c2bb71688f2dd2918739ffc90f280131b7d8bbfeaf9f0e2bacfe952a88bfa3bc168045": "0x040100000002000000000000000000000000000000001052414449554d424c4f434b2e434f4d001868747470733a2f2f72616469756d626c6f636b2e636f6d0015696e666f4072616469756d626c6f636b2e636f6d00000d4072616469756d626c6f636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f3fe45df61eadb158e5dd2b0d1bbcb01196506ec753353b2698fa64d77e039c66bc43c747b375d0e": "0x00000000000000000000000000000000000862696e616e636500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f419f736dbf31d4544c2fd9d2cc17606f93644a75086320a77c729a97553d33b8c602b7304d82d08": "0x00000000000000000000000000000000000778616d65797a01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f42b57bfe87de580d6aa438803d5e6ab28efa5ef6f3b3dd1fc1442497fbdafad37851a62c1788c2d": "0x00000000000000000000000000000000000d5265626563636120417274730000001e726562656363612e6b7573616d612e6172747340676d61696c2e636f6d00000e40726562656363615f61727473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4336ef56b1e116e966f06ede01dd4af9033cfce763ed647dad15ada85991dfa54ade147757b8346": "0x000000000000000000000000000000000005526f727900000015726f72796d6f7279393640676d61696c2e636f6d00000c40526f72795f4879706572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f43f187b68ff5147b29d3aa12cda294b6d5ea963d35f23e9afbc188aff49262c4903bb7b4dc04b1d": "0x00000000000000000000000000000000000f436c696d6174726f6e4143496e6313636c696d6174726f6e6163696e632e6574680000206a616d65732e6a68696c6c2e636c696d6174726f6e40676d61696c2e636f6d00001040436c696d6174726f6e6163696e63000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f43f3b59a11d04ec6c2f2e246faf3c84c8486e43f7fa54578fa011764f1d2183b174faa2ed89942c": "0x00000000000000000000000000000000000a6d6570686978746165000000146d657068697874616540676d61696c2e636f6d00000b406d6570686978746165000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f44c2f7410140cf19cbb16f064606fa2237ef9793e8c54e76e09934c0aa3616de195c3417ff47060": "0x040100000002000000000000000000000000000000000e4d584320466f756e6461746f6e154d584320466f756e646174696f6e2067476d62481468747470733a2f2f7777772e6d78632e6f7267000e68656c6c6f406d78632e6f726700000f404d5843666f756e646174696f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f45a1473eff966f38a1d68ff42661bb61ea1ba4d2818bd14bad9016823dd95ee0bd80d5cdc40a347": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f46797ab2e78531968922cb9e2094b7ae881da08890d1659e2c82d08878e45e7be83006aa6fefe35": "0x00000000000000000000000000000000000e5375624172742044657369676e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f46951568dd99491466e8b633811f506b9d27c30141d4f5f03f41545aa8a3acd20a65f92599eaf1e": "0x0000000000000000000000000000000000124e6f6e46756e6769626c655472616465720000000000000c406e5f665f747261646572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f49c731c93e855d8e442aaad715153a1515d843b05b774fd7a3b52cfc011cd718975b44ad239d831": "0x000000000000000000000000000000000010416e61656c6c65204c5444404b534d001c68747470733a2f2f616e61656c6c656c74642e636f6d70616e792f001961646d696e40616e61656c6c656c74642e636f6d70616e79000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4b9a6863cc46670889af0630394f4684620003c6fbdb2bde3b1493ee257851e2c894c0f9b1fc13c": "0x000000000000000000000000000000000003565a1356696b746f72696961205a656d74736f7661000013766963747a61727440676d61696c2e636f6d00000f4056696b746f726969615a617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4cb3aeb24cf84a9e2815c08a727372ac028bf267fa8631226ccad9b689bb5b787b274c0828e1c51": "0x00000000000000000000000000000000000d733066746d616368696e6520011b68747470733a2f2f73686974636f696e7072617869732e636f6d1840733066746d616368696e653a6d61747269782e6f726701000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4d588a2f12c5abea6f3f09fac7be035067d4b4e8e18a47ab28a7bf50e3dcb90679e8ed631582645": "0x00000000000000000000000000000000000e5b4b5553414d415d207465737400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4e09fff907e51dbba44ab1fc1acb0b1ff28165e08489416f665a4af1770ac45ab67642613d4a218": "0x04000000000200000000000000000000000000000000174d6f6e696e205374616b696e67207c204b7573616d61000017406d6172635f6d6f6e696e3a6d61747269782e6f7267186d6f6e696e2e7374616b696e67407961686f6f2e636f6d00000e404d6f6e696e5374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4ec2259201f165d10b51b925938bb414ec70b4a5b8179dde0028f4e00620e177839361f70bbd960": "0x000000000000000000000000000000000009506f6c6b61646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f4f074392c48cb8b90c8b22b263271d5e7a8baf7ad89a918fa15a5ea58c33b0e03fdebae9f60db45": "0x04000000000200000000000000000000000000000000195769657a7a656c204b7573616d612056616c696461746f72104164616d20576965727a6269636b690000127769657a7a656c40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5052ba88cc9b0139609cdb14cf0b415f012433cfe2714ae591a0c0bdb443eecf99be67a6251da31": "0x00000000000000000000000000000000000673657268690000001f70616c616d6172656e6b6f73657268696937373840676d61696c2e636f6d00000e405350616c616d6172656e6b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f52104c468be8e69409e451afd449239c0bf71d2064b64ccb6fa40b7d64b31e070e867c298397563": "0x00000000000000000000000000000000000f416c65784973426567696e6e65720000001b616c657869735f72616d6f733936406f75746c6f6f6b2e636f6d00001040416c65784973426567696e6e6572000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5260a005d5a4f8b1aeffe4adfad627470d78b75ceeff90aed88685b9ab436611cf8b8aff4316264": "0x04000000000200000000000000000000000000000000074141726f6e6e000000176f786561706f7865616e6b6140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f52b0b669e3be3189a649e148cdfacb89a0ed6ef6d1af70b4712cd09f0b079aee5fdebab7842584c": "0x00000000000000000000000000000000000c52756262657220466973680746656966616e00000000000d4061647269616e6573746131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f52dc65059840ede54d622206cdde1774f9ca2b05a09bb2679c97c6a2d7ad8a20d7fea2c7391d044": "0x00000000000000000000000000000000000c43727970746f5f70756d7000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f53a76b36f1f22087847a2bb5db0c9e65070fe05ce4e2a168a7a0e38c4e7238621c344445f1ba65f": "0x000000000000000000000000000000000005544f41410000000000000d40636861726c696562656e6a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f53d71829fabd2650c495817a6cd5cad36fa03114765a3e1189c1e8b11777d39f9c2ac1a18217505": "0x00000000000000000000000000000000000a416e67656c33356d6d10416e67656c20526f6472696775657a000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5488f1caf19f51ce69c23c5c6777d19d549efe56078bfd2f73f749f119c8ccf09023dfa6593347a": "0x0000000000000000000000000000000000074e7541725f7401010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f55e346ed30a7e9fda296bb99c7df724f33539a3110c456b9a082e121734470a4cbd40703e519442": "0x0000000000000000000000000000000000094d41432d4e465473000000126d61636e66747340676d61696c2e636f6d00000b405f6d61636e6674735f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5695ae6155ce7ab243612f0fc6c935d9ee0cbe21c453a83f58a9427054ccdc74966890ca57ca719": "0x0401000000020000000000000000000000000000000008416e74726f6d6500001440616e74726f6d653a6d61747269782e6f726714616e74726f6d65333740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f56a3670b6cb3944bcabe2b0f21456b5d75d8987f79197e4df729c9283edc8f1b2f5558950f88860": "0x0400000000020000000000000000000000000000000009736f72612d6f707300001a40736f72616d697473752d6f70733a6d61747269782e6f726714626f7440736f72616d697473752e636f2e6a70000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f56ab696ef80d1eec8f5635f081f1f774194a841f163cdc3ad27b3935bf1a928a9869627a0abe054": "0x0000000000000000000000000000000000124b72697374696e612044617679646f7661124b72697374696e612044617679646f766100001c64617679646f76612e6b72697374796e6140676d61696c2e636f6d00000b406b7269735f64617679000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f59d68b847bcb2beacab23f327e732756f5d76a43cd32830d5d8a9a489cd9c5c6a8554a3374da056": "0x040000000002000000000000000000000000000000001cf09fa6bef09fa4962049766f72794e6f646520f09fa496f09fa6be00001c4077686974655f736e6f77666c616b653a6d61747269782e6f72671769766f72792e626c616e63614070726f746f6e2e6d65000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5a9403264d182764011221fbb00463b80a86f5b7e3ad507717724ff91c47cba6521d7f34983f527": "0x00000000000000000000000000000000000d4b7573616d6157616c6c65740000001467726567323730303140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5b6095599969b9da657fdb5080af7783a0eb74870fa95b2e0e4dc78445f4b4dffeb3ab18856e30b": "0x00000000000000000000000000000000000d424f55424f554b524154494100000017626f75626f756b726174696140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5c03f3c88350579aeb0e7400e227d10778810032a5c677766796398d0dfcec5d7cf210458f22142": "0x040000000002000000000000000000000000000000000746617468657200001440706170616b736d3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5d0cc94e99850e8c2421666570ec7f9a5c94ef30c2c6443bd857faabcdeec6a96ef4280ef41f61c": "0x040100000001006c57c10b0100000000000000000000000000000000000000000000000000000c686173687761726c6f636b074a6f73687561001840686173687761726c6f636b3a6d61747269782e6f72671a6269747362656e6465724070726f746f6e6d61696c2e636f6d00000d40686173687761726c6f636b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5e19c61928389eae882a0e173cddff84f834ad020772bfafa4022d9c9a823f54982e9b4d3fec745": "0x00000000000000000000000000000000000f4956414e2052204d4154482023330000000000000b406d6174685f6976616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f5e44fd2e0ba9c81b88ac257042778fa648722b1500402f740f908e58d0bc8e19439a352e55dc613": "0x0000000000000000000000000000000000104d69737465725f436f6c65204b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f601fb05d6c070e4da8564ba0f7e717dd8d61025823ef756b474d6a3f3e8099da01ce16b53d85154": "0x00000000000000000000000000000000000747656f726765000000136d7574613631353040676d61696c2e636f6d00000d40475768616c65636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6035b451942851ca231fc973b2ec593bcb98a447e9c221a999cdfd05cf2dbdcaffea0bf42cb0f02": "0x00000000000000000000000000000000000c46696368204d6f72736c7906416e746f6e010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f60bbbed7d37752ebab59eee6a380bd486faf8abbb17790b47ab67cc2706ffeead8fc51f5949ae8b": "0x040000000002000000000000000000000000000000000f50726f6f66204f66204368616f730000194070726f6f666f666368616f733a6d61747269782e6f726721676f7665726e616e6365696e63656e746976697a657240676d61696c2e636f6d00000f40476f76506172745265774b534d000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f61803895bb4ef9200d6a5e519858100b8f989048a9d6a202d0c588ff72f76fc9a18a4adadcab168": "0x000000000000000000000000000000000006476f627a790000001a6d6f68616d6564686166697a39313940676d61696c2e636f6d000011404d6f68616d65643135323833343535000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f618fd21cfdd00cb0e8b58178acdc19d47b6b00140772db705f55e6d3a4881bfd3232b4de456103d": "0x040000000002000000000000000000000000000000000c536f666969615f56616c3200001740736f666969612e6b6f6e3a6d61747269782e6f7267136b736f6e696e393540676d61696c2e636f6d00000b40536f666969614b6f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f634b03876b8ef79806aaca020076fa26a81169d70fb62d932a440ab3c0ab77033285e572ad2b912": "0x00000000000000000000000000000000000b52454e454c494e3136380000001270636c696e3732407961686f6f2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6553f1969b75460800f8a9142fa2145a9dfd55f63917f1d56c61b019b92acc1e53669d281765a7d": "0x00000000000000000000000000000000000a59756d692041727473001b68747470733a2f2f6c696e6b74722e65652f59756d6941727473000000000d4059756d69417274734e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f66ebdaccf9fa53084b56b03893a12010b087eec53365d5b7d9b47b0b3bf17a012bfe096012f600f": "0x04000000000200000000000000000000000000000000074d6561646f77000000166e61746976612e7665746140676d61696c2e636f6d00000f40416e647265697461507261646f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f687f2305ea5dc3060ac960bd310b75e387525446daef1ceb98f322d3e5300ad8910568f6aef9d3f": "0x00000000000000000000000000000000000b7a6d6368656e2e6b736d011968747470733a2f2f6c696e6b74722e65652f7a6d6368656e01157a6d6368656e3133313440676d61696c2e636f6d000009407a6d6368656e33000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6b2883a4b0925a1f64c77c5a1bb3a45db136d8e36bd9fa3fcf0e060313b404650e59c97b7ac9030": "0x00000000000000000000000000000000000b416e676f2050616e676f0b416e676f2050616e676f000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6b5e0cd02d4b92f3a125886cdd1eddb5f8dc3fc266062e6066ea77566f7694efd93a97ba57a7e31": "0x0000000000000000000000000000000000056b72726e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6c04fa3dd4fac8ccaa7ea76d94fbb4715ca996b63214e8fa86bdd293fd5fc7b8fe9de231010e21b": "0x000000000000000000000000000000000010536f6c656d6e20537472616e67657210537472616e67657220536f6c656d6e00000000001040737472616e676572736f6c656d6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6d034c52a0fc194d6ac28ef62f212e4a5888fa5e72b1515a32233dfb118a9ea5de97558b1a53d65": "0x0000000000000000000000000000000000064b43435f3100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6d774e91f506eba46e2c2e77afa347eb36b101757c3d004b088a324405c097fa561a750249cc44e": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6e0d6bfbf124fd8c6d5a9d80d5559e34b6c16cea7f4da7d399aceeb54530bee71fcff718ee5a82c": "0x0000000000000000000000000000000000064561646c6500000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6e15252920b51ae5004bd06b509a6d463ef831486a0fa49b185bcb3f96e06020ae63615b284a81a": "0x040000000002000000000000000000000000000000000c526f647269676f3730303000001840726f647269676f373030303a6d61747269782e6f72671a726f647269676f373030302e6b736d40676d61696c2e636f6d00000e40526f647269676f5f374f4f4f0011526f647269676f37303030233533343200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6e75d18b8b8218f6a73a035c39a045fd93aa3e85b7b91fb4a77d8072149182f8d42362fea9bf85a": "0x0000000000000000000000000000000000124f647973736579204d756c74692d7369670b4f6479737365792042561568747470733a2f2f6f6479737365792e6f72672f0011696e666f406f6479737365792e6f7267000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f6fb66dae8fa6226a8d08e114a7bfeda36a14cb3db7b8085d867eb4e0f33eb3f2e0a50f821abd80f": "0x00000000000000000000000000000000000a506f6c6b616672616e00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f71158c0f51bb8fd5247e73b8ad3c36bb4e01c93a9bd6a6048afce1e2a45863ea5fe99778b530b61": "0x04000000000200000000000000000000000000000000094e5244204c6162730000000000000a404e52445f4c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f718691c7d2fecde924f9a8e5439d381aee00bd507a3d52321be607c5935bb0d6c9bfb2227875b5c": "0x0000000000000000000000000000000000094241545641554c54094241545641554c540000184261747661756c744070726f746f6e6d61696c2e636f6d00000b404261747661756c745f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7199ad6b299d282d2d6d338d9b6d82049dba9d8a4e20feb2515bd7aeeb997247a02e56e8d3b1469": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f71b1777c4c6a13546b4eca928ede3e8075d86e25581d46adf3eff915646eab110d13e2fbd947b5e": "0x0800000000020100000002000000000000000000000000000000000e7765623376616c696461746f72074e696b6974611c68747470733a2f2f7765623376616c696461746f722e696e666f2f1a407765623376616c696461746f723a6d61747269782e6f72671477656233346576657240676d61696c2e636f6d00000b40776562333465766572000a77656233346576657200", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f71c3bfdec4acbf06eb5904c5ae1d15ef5b700f4c30b87cfda092fe7e01b94f5ce7951b8b368a224": "0x04000000000100902f500900000000000000000000000000000000000000000000000000000005746e63680000001674696e636863727970746f40676d61696c2e636f6d00000b4064656d6954696e6368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f721344dcd79f9f76869fc679ec3b5cf08e4c2ea215ad2b3ab2fedf7263d019c4181e0f2e8e6071c": "0x0000000000000000000000000000000000114465657065726e6175742e73706163650c4a6f686e20426c616973651968747470733a2f2f6465657065726e6175742e737061636500166a6f686e406465657065726e6175742e737061636500000c406465657065726e617574000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7213bfc0e550eb660ba08bf2bacea0f40dcf6b9f8f253ca8267cb45f6db39acf5c71c5c1d1b3521": "0x0000000000000000000000000000000000056461336100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f72498dd00ff440c3c06757449eba15d09a779c6cbc249eb6fcd0dcf994ad9f3e4d6bf2b60ea8c74": "0x00000000000000000000000000000000001043696e636f2064652050686565626f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f726e9532024780186f20c19f0c0238685e4802c2f7880579b4426a1724d0ad0a6daa88bfcbca026": "0x00000000000000000000000000000000000452614611526174696f6e616c204173204675636b2168747470733a2f2f6c696e6b74722e65652f726174696f6e616c61736675636b0101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f72fe494f8b2c13b50bc2d20f1106991d73e7e17202dd22c951c13552caefa2fe973490017f0015c": "0x0000000000000000000000000000000000074b2053756c7a010101010000084073756c7a5f6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7395a35358c5c73b03a577ca487cc73addcdcbd6b006aee80991427d8cdf2b732e4cda58bb06a23": "0x0000000000000000000000000000000000094f736361726c74630f4c65756e672054737a204368756e00001b6f736361722e6368756e2e6c65756e6740676d61696c2e636f6d00000a406f6f636974656f6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f755c066638838c208ec81d6f3942d5955364977664f27b91f34f3b365ee0ef1ca87facc9bc1f900": "0x04000000000200000000000000000000000000000000056c616461000015406c6164612d6b6d763a6d61747269782e6f7267136c6164612d6b6d764079616e6465782e727500000b404c61646173756e6573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f75e019010e9d2891019993ccaf1f9dbd14e41793ebbc5dc0c3f301cb8323d75678deda1087d7e38": "0x000000000000000000000000000000000007594f4755525400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f762150cda5f8ed7ce6075c29ed1bf04552862e9068cd112761eca24d335514dbf43abd811512242": "0x0000000000000000000000000000000000184d6f6d656e74756d204e465420436f6c6c656374696f6e0c4d6f6d656e74756d58595a1668747470733a2f2f6d6f6d656e74756d2e78797a2f000000000d404d6f6d656e74756d58595a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f763d946684c55c7027342f61bb5ae7fd9a78ab16b23d56dc3bff26ce92fe6cb787cdd4c9abe7635": "0x0000000000000000000000000000000000064d6f7a7a6900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7722cb2c8ef11377e78e4019711d39804f121a2c2e719158dec8f848e329d23af4f4df886b0ef59": "0x0000000000000000000000000000000000104775657272696c6c61204b61726d61002168747470733a2f2f7777772e696e7374616772616d2e636f6d2f677565727269001554656b756368656f6e6740676d61696c2e636f6d00000b404775657272696c614b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7815b3b02445bee22e79717d0fefeab58a93b118b1da271ef308419ad31b7c88048b202a72a7f7c": "0x0000000000000000000000000000000000124c75646976696e652050726164696e6573124c75646976696e652050726164696e6573010101000011404c75646976696e6550726164696e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7b9882bb36b0080f043bee4b4c5a1387805a345d2ec765bbaf1368701292efa42c39592c8c74b4a": "0x00000000000000000000000000000000000c47656c6174614472696e6b00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7d620f3759f37d922a83d766632d6c6b371f5936014822d228c16699a1d2770c465f04abc05d71f": "0x00000000000000000000000000000000000d64696e6f6e757473696e686f01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f7dee93d06f89424c8b27ef9420148d8711a555ecaf50fdcf0705f1af8fe4cb525f43fbeb2393125": "0x000000000000000000000000000000000004e99d9601010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f803929b514c8374d44e8557e2484832376bb918ca7fb5743eb5befc52d4f2a3b9b54f21818f2d7c": "0x04010000000200000000000000000000000000000000064672656479001568747470733a2f2f64657266726564792e636f6d154064657266726564793a6d61747269782e6f72670000000b404465725f4672656479000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f820b2f799e04c2e4ea5deb79975c49738ccfc00e2d53dda38c7bda5b9794643c071b3be46eb1629": "0x00000000000000000000000000000000000953757065726d616e01010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f82d8b99311e7212a46c027c5b401f01d8d9bf548ab323785f6db26575c5fc9290434da5fef93960": "0x0400000000020000000000000000000000000000000011f09f918b203739616e766920f09f8d80000013403739616e76693a6d61747269782e6f7267133739616e6476696b40676d61696c2e636f6d000008403739616e7669000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f836b36502f1031656f85acf479b193128bb0482a4f01191b48b10c4a2a13458d97da7bbb383f77b": "0x00000000000000000000000000000000001d56616c696461747269756d20742e6d652f76616c696461747269756d1d56616c696461747269756d20742e6d652f76616c696461747269756d0000157661696461747269756d40676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f846335f6916b0d70e5f9a5620405b32b9cf67bf7124b4e772a34e87abeab4ccc4e14389f1ce305f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f846d171247e3f0f4aa63d199318cd993574507d7970c1cc69018124a96892f52a900debf38df908": "0x0000000000000000000000000000000000076b6173626f79184b617372612042617261646172616e20416e6172616b690000146b617369626f79363940676d61696c2e636f6d00000a406b617369626f7965000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f85213a2ee7ef9df68f838c7f70002288722303bd1482bf8a2f2973ff548d3517ed8ef3a8c6cac37": "0x0000000000000000000000000000000000076c6673613739000000166c66736137394070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f85b684a0310e669c4ce6a3336cbace999a6052c4dbc755fdb2d263490ec0fc2a8c3fe8e23376469": "0x00000000000000000000000000000000000e4b7573616d612057616c6c657400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f87b103429943affbc6f62a54d698249c4049a8ff3a7af9b5f28325adb33e1ef5d2ce402f954c65d": "0x0000000000000000000000000000000000204368616f7344414f206175746f6e6f6d6f757320766f74696e67207465737400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f87da1ee1c7abb802e0094a721c36e0ebceafaa1cc2fbd8d4e82f2bb1c85001ce8172ad6b5011d0b": "0x0000000000000000000000000000000000035056035056000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f88f79bc67c8710cb6bc64fe84080c7fbb6c6dea980960f0cfc716695b2821bf7a28a356bc19070e": "0x00000000000000000000000000000000000773757265736800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f891e0d61d95d2f9ecc96f0e735d4677e64728f5300b27c97c3413ba01e7a60dd29cb89123990a66": "0x040000000002000000000000000000000000000000000b44722e52616e766965720000001564722e72616e7669657240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f89ce40ac4f74c35cebfc6751f43de44d7aacff9d0e48240227560e071b4b2547edde36ae3c3ee59": "0x0000000000000000000000000000000000077469726f6c61077469726f6c61000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f8b08ec665a49b5a566edc7dbb221131cb2aea38025779d4f4638c769b16c1b0cfb060fc613f2d6b": "0x00000000000000000000000000000000000f546f736b612053617475726e6120034169000017746f736b6173617475726e6140676d61696c2e636f6d00000a405453617475726e61000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f8bcf5162393bea6c2f706cbfd0708a2fa387748388e4851012bb69b2e965d2dd933e452ddc36464": "0x00000000000000000000000000000000000f42494e414e43455f4b534d5f343800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f8ef4c38a66ac4223cf3f47f611c9dd952bd9007a85b0d84383f91e2f25edd0f13d6be20b5805110": "0x040000000002000000000000000000000000000000000a67747374616b696e67000000166761757468387a4067747374616b696e672e636f6d00000a40475374616b696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f8f2d058aa94f837b8356d7f4f32035fdf5b8188e4d1a5cb1639c580c48a29a1590bbcbc2df0597f": "0x040000000002000000000000000000000000000000000641424741520000124061626761723a6d61747269782e6f726716616267617262617273656740676d61696c2e636f6d00001040416476697a6f7254727573746564000b476172696b233537313500", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f8f844a5b45ed4e5461490934113768b8b0bdc60810250ab77fc9c0fe05f69a05d8262fdc7a39656": "0x00000000000000000000000000000000000b4672616d6553746f6e65001768747470733a2f2f6672616d6573746f6e652e6e65740000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9047b8f088890cbc687ff86c75c1a2506c4aa4cea67f68276b6348e3f497bb845b42a3aef585025": "0x000000000000000000000000000000000009464b31203139333100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f93edb11f07d9b7c4e721644ba20842c4c89f36b89af12e53a513a43841728eae5ac5efccaa01f32": "0x00000000000000000000000000000000000b53696d706c6573656e640101010100000c4073316d706c6573656e64000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9423de3a5fdd2d8c8c87c93d349b6e30b0b00906c966e623b5a48b4a12803434c45dfdfd171f951": "0x00000000000000000000000000000000000552697a6b1469647269737369206a616e6174692072697a6b01011772697a6b2e6964726973736940676d61696c2e636f6d00000d404964726973736952697a6b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f945bddd0ac8d6e44a3258cc6d8bc991479bc724a77d8d74491a5e8cb3ceba66cedcd180b3290e07": "0x00000000000000000000000000000000000d44616e676572204d6f75736500000017546966664c7563617330303740676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f94e92ce97ad9912aeffde5a4dc7117e4cdde2d3fb3d2afc7b2f710d5d66c55c5d1d7c5873598706": "0x040000000002000000000000000000000000000000000c4d6f6f6e4d697373696f6e0000001973616e67616c6c69676c656e6e6140676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f952ae0f2dbd6fee08a876a9d0c017b4a35ec9a60da69cdf10e25dcbcf6e32398e911c8471576f36": "0x0000000000000000000000000000000000104b7573616d612057616c6c6574203100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9540eba239b8a7078b5f7e8f099b66d62370d55e7423b65e5b813df52679626adec7b4b00de9565": "0x04010000000200000000000000000000000000000000075061726974791950617269747920546563686e6f6c6f67696573204c74642e1268747470733a2f2f7061726974792e696f001061646d696e407061726974792e696f00000c4050617269747954656368000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9588f41f8fb002552b993b5f03c0eb34858fd978eaba71182fd619307ab26a2fb31b3f34d098272": "0x040000000002000000000000000000000000000000000c6d7968616c657469736865000000126b6f76696440696e7465726e65742e7275000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f96da090b9f585b1e68da6ba34b144a0ca598bfe9796b4308e750f5f76972296528b97a3d97e0e67": "0x00000000000000000000000000000000000565646976000000146564697640676172626167652e6d61726b657400000840656469765f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9cdf9022f4cbf316e209998f669dba74194912c3e64d33dea4101e1e589b38abbdbbad88e93cc53": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9d69d01e9632c5372ee5c9dcec858fe96783766b2c1894e26b95b52318652b7672b2c496a579b75": "0x04010000000200000000000000000000000000000000114d756d6d696573205472656173757265001d68747470733a2f2f6d756d6d69657374726561737572652e636f6d2f001a6d756d6d696573747265617375726540676d61696c2e636f6d000011404d756d6d6965735472656173757265000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9e4321423bc80888ef7167c4d50be846c6a03591e13005fa68ef858d87321bb79428b121e105a11": "0x00000000000000000000000000000000000d53455247494e484f464f474f00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714f9ecb241324aeafbe63d1474c5ae8edc07f6b09e4efaa777640c6b1b1cfaab3cd797aecaa932010a": "0x00000000000000000000000000000000000730784d61723101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa0bfc4dac243ee0f42b7fead1bb8eec5d895fb3d3bd145e85f0b6d5c8bb3d7edb4a6fa9dda2c021": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa21d4617f82911d045dcf490090bbd75f4ab97f5984fc4792d122368c6a73cfb3d11873dd9e274d": "0x04000000000200000000000000000000000000000000064f7262697400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa3f4bf18db4aa46bac3d54468165a2b6b4cc010beaedcd71ee772dabc384bc9a54d6eca6e14a20b": "0x000000000000000000000000000000000020524d524b2047656e6573697320436f6c6c656374696f6e20466f726765727901010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa43aa10b719e7a44a1f6aa44b0456c45ffe2e1314c991430734a090f57910425f9a5e9b6573ce3e": "0x000000000000000000000000000000000004414c5800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa45a2d24a1b7d89a46615035c62da7a1906c838ac55e2ef1f38b679b9d5d6ab7c3633fd75280f43": "0x00000000000000000000000000000000000e42494e414e43455f4b534d5f370e42494e414e43455f4b534d5f37000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa48706896c81ac3544e034f612acb28ccbf0822adf1140335fa6e8bdccfac51a3bc7da22ebf7c58": "0x0000000000000000000000000000000000084461766579444301010101000011406461766579646f657363727970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa4f3e525e10f673faeffbbb88ab949b51abcacd45d7f9addf608a6e6ddc3d4b39147454e1a23a16": "0x040100000002000000000000000000000000000000001356414c494441544f5252554e4e455250524f000000177367696f7661636368696e6940676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa5550e0264faee9fa17408ad767e6d32032b8a73d670d87a8f2a339803d404d1430ceca36911865": "0x00000000000000000000000000000000000c676f6c64656e726174696f0000000000000d40396f6c64656e726174696f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa56ae54f7bf8c8ed62b129a1d30afe9a2fd69a871f50355d01f0a5e9b7fd160f3a0d4e74a0d0a35": "0x0000000000000000000000000000000000084d564420525654084d5644205256540000146d7664727674626f7840676d61696c2e636f6d000009406d76645f727674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa6a08c0d89c75d8801250e96cc2a1d70ef029adf57956e6a7100669076e8ccc14425142f4d7370a": "0x000000000000000000000000000000000008436f6c6f7375730000000000000e40616c7661726f64657265636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa894c90df0929a924454eab2e4e832c9d71afe1dd6345a7d889fab3430d8ad971888610af053317": "0x00000000000000000000000000000000000d506972617465205368656570001a68747470733a2f2f7069726174657368656570696e672e697400197069726174657368656570696e6740676d61696c2e636f6d000011407069726174655f7368656570696e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fa9ac24df5ce07f888ce8ce9cd622ac98233ffcca795bd69097012a6bf409054c1ec522850fb3523": "0x040000000002000000000000000000000000000000000c43727970746f436172746f000000000000104063727970746f636172746f78797a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714faa55b79d5b983962aad2d511e0a2ade151b1e3442675156b71aea1f049ce004311cf33c9d70c474": "0x040000000002000000000000000000000000000000000a53656261737469616e00001c4073656261737469616e63726970746f3a6d61747269782e6f72671b73656261737469616e63727970746f3840676d61696c2e636f6d0000114053656261737469616e43726970746f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714faa9d42c4d30ce42e6d147ba2586400cf6696e4d7f4491f51cfd88f9ff1b25aafba296851e6dbe5a": "0x0000000000000000000000000000000000134e657572616c204361742057617220494920134e657572616c2043617420576172204949200000186e657572616c6361747761723240676d61696c2e636f6d00000f404e657572616c43617457617232000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb0aed06762dab03eed2052b53fd2a9cffaa55f84d4abf8a6143956ad77cf0579a70bac39da5cc50": "0x0000000000000000000000000000000000074269484f444c001668747470733a2f2f6269686f646c2e636f6d2f232f0013737570706f7274406269686f646c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb0bfb045f7bf9b02c5a307190f900bfce402cda80d3e30768767064591707a00a4a3111d3fbbf21": "0x04000000000100902f5009000000000000000000000000000000000000000000000000000000064f7264756d0a4f7264756d204c54441c68747470733a2f2f6769746875622e636f6d2f4f7264756d4c544400156f7264756d4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb0c0bcedbed5db3f689caeaa9e3abd42396b7fdd5bfc75162325cfd5dd65a1eb247a64a1bfa123d": "0x000000000000000000000000000000000010446f7473616d6120416d617a6f6e7300000018646f7473616d616d617a6f6e7340676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb1e196ecaf7c6ef54ec6a7bfcee3ac00ab63b98e084f1a1c4d0e82ff63c31387aee91c9a721a81e": "0x04000000000200000000000000000000000000000000114e656a6c6570c5a1c3ad20766f6c6261000000157065746b6f6d65726b6f40676d61696c2e636f6d0000000017407065746b6f6d65726b6f3a6d61747269782e6f726700", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb20a4393f027fd3301da7198667c2c959b5f7d81068d819d90e8dfe3c4ead4a89d84d8691c07350": "0x000000000000000000000000000000000007594a534e50490f4b6f756a69205461646f6b6f726f17687474703a2f2f7777772e3131343531342e636f6d2f0101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb2b8dee530cc653344c0541f063ddc8dcf4709789b93099da7e145f794116906f511061ca6de158": "0x000000000000000000000000000000000011432d4c20426c6f636b636861696e20200a432d4c20696e632e2000000000000e40436c426c6f636b636861696e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb5b92a4cfa1db0b6c2856a7a778cecf99534917e33c2665c67734a7d666093b6b9c785a3428ec61": "0x00000000000000000000000000000000000f556e69517565204176615461727301010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb5bc1ff496d8054008d8404893c7b4b80f397605cc96e61fec3c89676c8c2794a2a7d281d678b1a": "0x0400000000020000000000000000000000000000000012f09f8f942048454c494b4f4e20f09f8f940000144068656c696b6f6e3a6d61747269782e6f726710696e666f4068656c696b6f6e2e696f00000d4068656c696b6f6e6c616273000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb81b24c2a962fd37a94eb167216d8c9dee6fc9b56b440f01cd6c3a982a52ee041148f324421e524": "0x00000000000000000000000000000000000b546f726f2056657264690000001b726176696b68616e726176693230323040676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb84ec0986da67466055556b55210cc9d0f33bbc68d7c31bb5e28e1a639e1d6599aeffd7e49b6749": "0x040000000002000000000000000000000000000000000b4c6174656e744865726f0000001a6c6174656e746865726f4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fb91afe505259de7eeb02ffe6617932e5f2dd74bc81031fd5bec0272c7b3db1c7c28f511cac7a669": "0x04000000000200000000000000000000000000000000134a47412d2d48794846642d2d2d7741416d5800000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fba64a5013aca5aeec056e28b5688b561339537ddcdf78522c50761995f97825b3cccabd1075cf2a": "0x0000000000000000000000000000000000084d696b6861696c084d696b6861696c010116656d70747931393836727540676d61696c2e636f6d000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbac4c060b088b92aeedb1738fb7133da240213ab0f0916eb7abaf4140693b7a3f54311732bdda33": "0x00000000000000000000000000000000000a477561726469616e7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbb58baf12373ea22a1fd6ec0eb5124ebd1a70b26d283cfd92c289a451099cf91d255b1d76492829": "0x0000000000000000000000000000000000054c6f76650d6d792073746f7279206f6620000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbb8612e16c166c53292b66610bfa155fa87e60a020cf1fbaa438270fee288cd37655c91b0e20d3f": "0x00000000000000000000000000000000000d6d65746165726f6372616674054f67616e157777772e6d65746165726f63726166742e636f6d00176d65746165726f637261667440676d61696c2e636f6d00000e406d65746165726f6372616674000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbbd751cf18b124e066c470486d44ccf316779b680487ebee03495f93504cae4ab095a8e84a14877": "0x00000000000000000000000000000000000a54656464792044414f0a54656464792044414f00000000000d40546564647944414f4e4654000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbc426fc6e0869cd6e440a8acabf4208776f36b78891e8374e587dddd3b9cd6b67c59bb5b5b21a22": "0x00000000000000000000000000000000000c5374616c69616e6f5f323200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbc638e525d98b707a8d3cae2a718a52464bbdee0cc9f4356e79eea7df10450852f53653fb1db029": "0x0000000000000000000000000000000000054e696c7300000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbc6c8362eaa2f7cc8f449273529d94798e1b40063ab062e12c6274d3ebae93b22c221cd090acb23": "0x040000000002000000000000000000000000000000000c536d696c655f7374616b6500001840736d696c655f7374616b653a6d61747269782e6f7267197a616c75736b69766173696c697940676d61696c2e636f6d000011404161726e6149726f6e733339303734000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbcfcd76d1d892611ed66ffc1202460d3e4ef69ba4f0108332bf2c1129e03e027a8d9d8f43f76561": "0x00000000000000000000000000000000001031506f73697469766576696265733100000017637572746973657472697070407961686f6f2e636f6d0000114031706f736974697665766962657332000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbe3fad5beebd421de43fe93757a22e2588359fe423a4b1a9158369e27c839e63d7f7e1b4f1eac3d": "0x040000000002000000000000000000000000000000000a30784a6f7461456c650000001230786a6f74616c40676d61696c2e636f6d00000b4030784a6f7461456c65000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbeac673cf6ad96d86d0ca1a8d914606cd02075f08d7761ebd332ad86366ad394b204b574e7eb531": "0x0000000000000000000000000000000000084368616f73313900000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fbffcfa5ca1c52b612ea0b1170fd52e15cead3cd728c55be445052ce3a9d0430c8f93d80e0f27a7a": "0x00000000000000000000000000000000000d706572696c69616e204b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc2c019dd594548ff8547fde2d99534f00b548363ea18c47f8e72003b1097417f4d337080a94890b": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc350fd2d1e9b3546e069c9fdc08c7b545f21e2fa2d4d95d0ab995dab99975acb4a717c0004b6d1d": "0x00000000000000000000000000000000000a486f6c6c792e4254430000000000000f40686f6c6c796a6565785f627463000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc4000681dcc4060901fb59036fcb6811c92f7f8c0b4cfe288393f849c31ebf18e34c48886486227": "0x00000000000000000000000000000000000f56616c657269796152656973657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc597e338ba1693cc06ba3aa6dd4ef5128ca5b3122b6d7eb5414c205056cf542e593e2d63adbaf2b": "0x00000000000000000000000000000000000e43727970746f20506172726f74010101010000104043727970746f506172726f745f5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc6a73dec7fa79b18c8305ff8478e6309325ebbfb81e8c1883d39e65d2ef84f88e4a428615c49277": "0x08000000000100902f50090000000000000000000000010000000200000000000000000000000000000000085032502e4f5247085032502e4f52471068747470733a2f2f7032702e6f7267000f6c657473676f407032702e6f726700000e4050325076616c696461746f72000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc6efad6664e87cc02d16cb5729728b5237dcf6335c1a49a844fc8f86e63f6dd27cb9c1803df911c": "0x0000000000000000000000000000000000094c616d615f4b534d00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc74e5b9fe588bd5bce565fbba1e8cc8cf794c368b755e0a57354b70d9a262b2a14b4c4363f6fc04": "0x00000000000000000000000000000000000b446f742057616c6c65740e5a68656e6973204162656e6f760000136b3233706978656c40676d61696c2e636f6d00000a406b3233706978656c000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc77c115641dccf2908fafa24788c23e2db2a4947d62813364fe3a4e6548a36b6cd7cfcaca30ca43": "0x0000000000000000000000000000000000134a524d522d424320436f6d70617269736f6e154a756c69616e20522e204d2e205269636874657221687474703a2f2f626c6f636b636861696e2d636f6d70617269736f6e2e636f6d13406a726d7239323a6d61747269782e6f7267216a756c69616e40626c6f636b636861696e2d636f6d70617269736f6e2e636f6d00000b405363616c6557656233000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fc7f2ed947ce60905842026fdfe358c9320e35012deeedc83c1e19d2b677eba10a1fad0d93c82b66": "0x0400000000020000000000000000000000000000000005414e474c00001840616e676c2d63727970746f3a6d61747269782e6f726700000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fca0f500e560ebb8aa2560b48e6acb448d5957b30400dacc88967f8ff0519c095a4628f7d001060c": "0x000000000000000000000000000000000017437270746f666f6c6c6f776572202d204b7573616d6100000018637270746f666f6c6c6f77657240676d61696c2e636f6d00000b40447572616e64696e73000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fcbacdb7dda02f70504baa1f30e0267703f471e94de948bd9f09caaf3c3a2f4c2dad3685a79ee000": "0x0401000000020000000000000000000000000000000006616e76656c0e416e64726569204f6368696576001240616e76656c3a6d61747269782e6f726717616e647265792e76656c646540676d61696c2e636f6d00000d40416e6472657956656c6465000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fcd27506d243061f2edf0fd8948ea642f135b314b1358c77ec6d0a4af83220b6ea18136e5ce36277": "0x04000000000200000000000000000000000000000000124368726973404f414b204e6574776f726b0000000f6368726973406f616b2e7465636800000d4063687269736c6932303436000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fce5be1f766dfb1672b5848541435240ecc09392bdea68c4fc6f7bc06ea7389a09e02a6b22052164": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd015b120265976186deb657c4754c485fad608accb98e195349f1d6f7b3e21fc0de1b49605f221a": "0x040000000002000000000000000000000000000000000641727347470000124061727367673a6d61747269782e6f72671562756c646f73696b706c40676d61696c2e636f6d00000a4062756c646f73696b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd033442619da284ec5da3e8919335b965130fb9109eb55f02fc78db8e592ddb8db101dce2b1235c": "0x00000000000000000000000000000000001157616c747a696e67204368696d657261000000000000114057616c747a696e674368696d657261000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd13d95520bea732966b58639403c4a3e5ad93300a158d65f9b6a8dd1d4e053f7058fc19d1f5ca2b": "0x04000000000200000000000000000000000000000000116269726473626972746866617468657200000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd265413bf0cff23c261b264bdd11a41bd20702fb3119fffc00f49d035d4efc219cdb217448ec353": "0x0000000000000000000000000000000000010220010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd3e18c07f5fba3b662df7fc799864be8c99d11723b4ebdb4837ab3287a4668b1bd6d83f904cfb7f": "0x0400000000020000000000000000000000000000000011576f6c6645646765204361706974616c0000001768656c6c6f40776f6c66656467652e6361706974616c00000a406d6f68616b616772000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd47ebcc2ca5e8d37e4f4ebe251bb6361e0ddcaecfbad3da3bf473b678c7684af7792a7cf83a226d": "0x00000000000000000000000000000000001250617472697a6961207c20414e414d495800000016646270617474792e64657640676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd49aaf383f13bb11ede7818a2f7f044a9dfa0755940d7f1468aee6f3df19695d4d74f77a8198a7a": "0x00000000000000000000000000000000000f4d64656e626f736368706f6c6b6100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd6097824962e44cc095ca14303d34ff5b0b2e5846e62c65bc4bd81244d41c97b82b4ea2a05e7d6b": "0x040100000002000000000000000000000000000000000c527562656e20546f7069610c527562656e20546f7069611b68747470733a2f2f7777772e727562656e746f7069612e636f6d0014696e666f40727562656e746f7069612e636f6d00000d40727562656e746f70696131000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd70211d1db8fd913a94d7f01d2e2a30b20bf318bbd88a3e8897769a26eacbbbb3383e3cbaab1321": "0x00000000000000000000000000000000000d706974636f696e2e61737472064d6172636f00001d6d6775696d61726165732e6461726f63686140676d61696c2e636f6d00000a40706974636f696e5f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd8ab13040828c7114896a045cb7bbcf45c0894fd388e23cc67d0697363530cae5cba9d5d28cc51e": "0x00000000000000000000000000000000000744616d69656e07446d7974726f00001964616d69656e2e746f726e2e373840676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fd8ca3f2d503cae5fa514f3f70cf1b8b3ff34cb7e783e3d8c38077409bb2dfc877b396a98703ae7e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fdb56e406bbd33003c1db08dfc6786bee3b0e1b4aaf51e80b6f2ec9badbe3da87d30ad7605a2bd16": "0x04000000000200000000000000000000000000000000104b7573616d6120476f204c756e617200001a4063727970746f676f6c756e61723a6d61747269782e6f7267196e6f74696669636174696f6e7340676f6c756e61722e696f00000f4043727970746f476f4c756e6172000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fdb8522cbdc728de58832b4a605c2e5200f88606aef263a82573ef1f8421ae19ac8f786661d77631": "0x040000000002000000000000000000000000000000001356696b746f726969615f44656e69736f766100001f4076696b746f726969612e64656e69736f76613a6d61747269782e6f72671368686f75722e647040676d61696c2e636f6d0000094048686f75724470000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fdbb17eb6b8c97966c335d86444f3189027cd53244265047e52a96b4621fdaeeb9bc128577898676": "0x0401000000020000000000000000000000000000000009414c4c4e4f4445530e416c6c6e6f64657320496e632e1968747470733a2f2f7777772e616c6c6e6f6465732e636f6d0015737570706f727440616c6c6e6f6465732e636f6d00000a40616c6c6e6f646573000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fddd722142c641e0666dc61de797e22de1ec2a15c79cc4d725fe3aeeed8f47ee6fc466644d1d3c21": "0x00000000000000000000000000000000000667667364610564667361000018677561696775616968616f303240676d61696c2e636f6d00000f40677561696775616968616f3032000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fde28b6d3debc5d194ffa8f3ea040d3a0b39415d39710fcbb26534f05aba21f800cce0d95e3ab72b": "0x000000000000000000000000000000000009435245574d45525a00000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fde7c0ce043a7c2de43473b2f1519b0970617b33670e00057d3379294c118fbac13505d5be3cd307": "0x000000000000000000000000000000000012524d524b205265776172642053746173680a524d524b205465616d1168747470733a2f2f726d726b2e617070000f68656c6c6f40726d726b2e61707000000940726d726b617070000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fdee11c887534b61c8c8ab85b285f3b6e7927b775058a6e359e7bdab7e514d4450eb10199b1e2f59": "0x000000000000000000000000000000000009706f6c6b61646f7400000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fdfdaed8db3ace0e7607dd168d84f61f878d7cd383e62e55e6e5cd1e34870ac8e6f1c294f6db5133": "0x0000000000000000000000000000000000054261626100000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe01bd1d10220f3e48caaec6c160b794721459c9d63038ea108a42f712993126256c6199f5358a15": "0x00000000000000000000000000000000000f62696e616e63655f6b736d5f33380f62696e616e63655f6b736d5f3338000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe0e61bb6b0e225d68170716ab7c6735dd0a1012045d9ea33891b5f6596cf97eb217d0962d86a518": "0x04010000000200000000000000000000000000000000076f6c616e6f640d44616e69656c204f6c616e6f1a68747470733a2f2f6769746875622e636f6d2f6f6c616e6f6418406f6c616e6f643a766972746f2e636f6d6d756e6974791264616e69656c40766972746f2e7465616d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe0feebd17524d7b067b047f02b57d4c77caf508cfa3944d8dbf8cbc0a829ee797ae5d6fbed6047f": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe13e8d69b79bd114ce421370cf0257d869618ec25c324ed4c6c7f65289297a3c134332c212e350b": "0x04010000000200000000000000000000000000000000174d617276696e207c205068616c61204e6574776f726b001668747470733a2f2f7068616c612e6e6574776f726b17406d617276696e746f6e673a6d61747269782e6f7267156d617276696e407068616c612e6e6574776f726b00000d406d617276696e5f746f6e67000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe162307295d89a332b6c05262048d5163640a9186784b80d74f6b6a8e1d72e31ed157a683c47103": "0x040000000002000000000000000000000000000000000e47726565656e204b7573616d6100001440677265656e30783a6d61747269782e6f726714677265656e3078406d61696c626f782e6f726700000c4047726565656e49744973000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe17f42c36004fd896505b10e2945a156440b36b640f87c7f88566ff332a9bd30caca8266a83126a": "0x00000000000000000000000000000000001e3520666f7220546865204b7573202853706f6e736f7220456e747279290000000000000f405468654b7573616d617269616e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe1c0833ec392131b0d633f222e86340e41e28d35e643dfb99d9bb411f46de3ade8d52601fc7d349": "0x0400000000020000000000000000000000000000000012426173617261625f56616c696461746f7200001a4079657668656e626173617261623a6d61747269782e6f72671a657667656e69792e6261736172616240676d61696c2e636f6d000011406768366d786a78384f437754776373000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe2795bc5fbd003faedfec0ea8f603e5915da43d878d9aeca5066170b32b4ea1e6d770603c38ef27": "0x0000000000000000000000000000000000066972796e610000001c70616c616d6172656e6b6f6972796e616940676d61696c2e636f6d000011404972796e6150616c616d6172656e31000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe3b1c73aae091b8a4c6cfc20e8d5395e20291d6339f9c9e7f8df2bd4a5484010ba21089fed5db3d": "0x0000000000000000000000000000000000104261737461726420467269656e6473002168747470733a2f2f6c696e6b74722e65652f42617374617264467269656e6473001c62617374617264667269656e64736e667440676d61696c2e636f6d0000104042617374617264467269656e6473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe4d46576752d75cce9903fecc2415a9ce35e5a39384b5005c1c1be3dbde661f3790fa6ef3d2d00d": "0x0000000000000000000000000000000000084772616e696141074c7975626f762168747470733a2f2f656469746f722e7769782e636f6d2f776562736974652f6200156772616e69616131313340676d61696c2e636f6d00000f404772616e6961414e6674617274000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe6c02a3d52a3ec7cc8b278ce627c23466aa5cb78b29ebddc340592d76013e1b36c5928a655b2c2d": "0x00000000000000000000000000000000000a4e657572616c41727405416c65780000167374735f6a6f6b657240686f746d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fe77fb272c40cb3db6b5592052813d13946ba4cbe6b2a28b44e6bd1e4c858e0c27beff6fbd288115": "0x00000000000000000000000000000000000e506f6e74656d204b7573616d610f506f6e74656d204e6574776f726b1768747470733a2f2f706f6e74656d2e6e6574776f726b000000000f40706f6e74656d6e6574776f726b000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714feb09bd923dd400cca437639da37528d8edc0bb6b31966fdc0263218f4bd60c6f2cc37e963090371": "0x04000000000200000000000000000000000000000000064d6172733200000018746f7468656d6172733230323240676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fec276262411f83c54f248466e58cb2d3f15705e84d9cb4b5bc4cf4305e227c91b9754b1f3d2350a": "0x040100000002000000000000000000000000000000000a436f736d6f74726f6e0000001d636f736d6f74726f6e76616c696461746f7240676d61696c2e636f6d00000c40436f736d6f74726f6e56000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fec4b60935b1627f3ecdb909643a31da23e3dec041ef8920632ec16fc5157297084eda7515badf68": "0x040000000002000000000000000000000000000000000f54617274616e205374616b696e6700001640616b68616e61746f6e3a6d61747269782e6f72671368656c6c6f40676f74617274616e2e636f6d00000b40616b68616e61746f6e000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fee0771ebef0f5076e208dee4a11c78082248fdff110afc5decb7af87c23a482042b462e463ece3e": "0x00000000000000000000000000000000000000000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fef0ad65a6e85d2fde8ba07168793b94e1f519c5a9485051c0cb161a10396fa38a5595887391da7f": "0x04010000000200000000000000000000000000000000054a61636b0e48752d4368656e672c204c65650016406a61636b37373132313a6d61747269782e6f7267146a61636b373731323140676d61696c2e636f6d00000b406a61636b3737313231000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fef1a8c1f1bd721354cbb4f2c8af1be474301d9c9dabc20015aa5779c5885e77010252388b2b7c52": "0x000000000000000000000000000000000000000000000000104049736b616e6465725f636973636f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714fefd9747bbaa6bd3dcfb89b5a15f3ed2e569b3ee58578a17ec547d42012d96c554b0154100793763": "0x0000000000000000000000000000000000134b7570706c657320636f6c6c656374696f6e0c477265656e204170706c65010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff27f362e41c7ee9487d7703ee644d9a9b59ad29aa7f27405851496306f69678965f1d18d1478740": "0x04000000000200000000000000000000000000000000086c75636b797665000014406c75636b7976653a6d61747269782e6f7267166c75636b7976656e6f646540676d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff295740e7cd48bec0fbef55637049c7352c1ef13f5db86359684ee1dfc32f76ce66c56776580b3a": "0x00000000000000000000000000000000000d524d524b204c6567656e64730000000000000d40726d726b6c6567656e6473000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff433a59c94c606d1c7c5bda689e0f7fff1f0012cd9c92d3ffdb3150b7585ca8e45d936a8c982674": "0x00000000000000000000000000000000000d46616c6361726975735f4b6f0756696b746f722168747470733a2f2f7777772e696e7374616772616d2e636f6d2f66616c636172164066616c6361726975733a6d61747269782e6f726714736172616e7461373240676d61696c2e636f6d00000e4046616c6361726975735f4b6f000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff58ab16118773668c1f986613ba74c810f3a640551d9a1d0831d4430eb9da2246019323f23ee244": "0x0000000000000000000000000000000000046a6163046a61630000196a61636f706f6d616e4070726f746f6e6d61696c2e636f6d000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff6779e6b83193fd281ba40c7b713abdb2ea8a124dec72cfd63d40bcc59b69550a0bf71c9a0d118f": "0x00000000000000000000000000000000000f476162652773204f6d6e6973696700000000000000000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ff85748c4b4f90b8548b99326157f4a2e39916a7ea20553d6964876bd6b583108f36e8941bcef951": "0x00000000000000000000000000000000000101010101000001000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ffb949961e1fd85deea39739cf422a6c6b2f350d2efb92428b71b408ef76b64165c32fedb7d32f16": "0x00000000000000000000000000000000000a4d616c6f6d62726573000000146d616c6f6d6272657340676d61696c2e636f6d00000f40545f4d616c6f6d627265735f54000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ffb95c1195a068daa023764a372deb88243537045ff9b3144219b315385c1d8e8de6761542410d61": "0x00000000000000000000000000000000000b617065586368696d707a001d68747470733a2f2f6c696e6b74722e65652f617065586368696d707a0015746f75636840617065786368696d707a2e636f6d00000c40617065586368696d707a000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ffc544aa04d3feb9a69484f2b10ec2f1dea19394423d576f91c6b5ab2315b389f4e108bcf0aa2840": "0x040000000002000000000000000000000000000000000a4661626920f09f90920000000000000d4066616269616e676f6d7066000000", + "0x2aeddc77fe58c98d50bd37f1b90840f9cd7f37317cd20b61e9bd46fab8704714ffee713c9a5ac32ea6a111bb9d56b51fd2648f68629b4e87f7b92915a16967f6d1a5777dfcbfc714": "0x040100000002000000000000000000000000000000000a487970657263756265001c68747470733a2f2f7777772e6879706572637562652e766964656f00166a6f657269406879706572637562652e766964656f000000000000" }, "childrenDefault": {} } } -} \ No newline at end of file +} diff --git a/cumulus/parachains/chain-specs/people-westend.json b/cumulus/parachains/chain-specs/people-westend.json index 93b8c064113f01c133ef301056ff79ade6dd032a..26e165b4839fcaa895bfdf0f7f4c1242b8513968 100644 --- a/cumulus/parachains/chain-specs/people-westend.json +++ b/cumulus/parachains/chain-specs/people-westend.json @@ -25,6 +25,8 @@ "/dns/people-westend.bootnode.amforc.com/tcp/30346/p2p/12D3KooWQrMQFAXxJJJCtVr8nViBR6EDsuT1RyqU3eoCMebRQxTf", "/dns/people-westend-bootnode.turboflakes.io/tcp/30650/p2p/12D3KooWQEhmZg3uMkuxVUx3jbsD84zEX4dUKtvHfmCoBWMhybKW", "/dns/people-westend-bootnode.turboflakes.io/tcp/30750/wss/p2p/12D3KooWQEhmZg3uMkuxVUx3jbsD84zEX4dUKtvHfmCoBWMhybKW", + "/dns/wppl16.rotko.net/tcp/33766/p2p/12D3KooWHwUXBUo2WRMUBwPLC2ttVbnEk1KvDyESYAeKcNoCn7WS", + "/dns/wppl16.rotko.net/tcp/35766/wss/p2p/12D3KooWHwUXBUo2WRMUBwPLC2ttVbnEk1KvDyESYAeKcNoCn7WS", "/dns/people-westend-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWBdCpCabhgBpLn67LWcXE2JJCCTMhuJHrfDNiTiCCr3KX", "/dns/people-westend-boot-ng.dwellir.com/tcp/30355/p2p/12D3KooWBdCpCabhgBpLn67LWcXE2JJCCTMhuJHrfDNiTiCCr3KX" ], diff --git a/cumulus/parachains/common/Cargo.toml b/cumulus/parachains/common/Cargo.toml index fa16205d0fd1adee1491cf3abb92a55829b16a44..2b943b6dca55989a891895b4abb3195970978b06 100644 --- a/cumulus/parachains/common/Cargo.toml +++ b/cumulus/parachains/common/Cargo.toml @@ -13,7 +13,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"], default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/cumulus/parachains/common/src/impls.rs b/cumulus/parachains/common/src/impls.rs index d70fdfeb7095a2dbd6f5fd9a53caeb1272476743..ed9c5c483fa74282306d20c20a6c6313bd940f5a 100644 --- a/cumulus/parachains/common/src/impls.rs +++ b/cumulus/parachains/common/src/impls.rs @@ -222,7 +222,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024); pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const MaxReserves: u32 = 50; @@ -240,7 +239,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockLength = BlockLength; type BlockWeights = (); type DbWeight = (); diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml index 20aedb50e6a18ef1112ab23b2a6d05780b6b443f..e4688a1c9f022dd9aafd821ee39bfc5906a7b2a0 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml @@ -25,6 +25,8 @@ pallet-staking = { path = "../../../../../../../substrate/frame/staking", defaul polkadot-primitives = { path = "../../../../../../../polkadot/primitives", default-features = false } westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/westend/constants", default-features = false } westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } +xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../../../../../../polkadot/xcm/xcm-fee-payment-runtime-api", default-features = false } # Cumulus parachains-common = { path = "../../../../../common" } diff --git a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml index 8c44cce7d922dff0a69a4273af7adb69819d2fce..b010d2a296382f2f2d5f8ffd889f4643a17098d0 100644 --- a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml @@ -10,7 +10,7 @@ description = "Common resources for integration testing with xcm-emulator" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } paste = "1.0.14" # Substrate diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index ddd6d2d049823f36ed193597ff438f39468a8a55..9abecbecc48a725448cfb17508351d5e76f848de 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } assert_matches = "1.5.0" # Substrate diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml index 00f4308324a96734afac879cafd1e51300407a26..e0f29cd801c346a064a4773efa5754b0e2f399f4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml @@ -11,23 +11,30 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } assert_matches = "1.5.0" # Substrate sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false } +sp-keyring = { path = "../../../../../../../substrate/primitives/keyring", default-features = false } +sp-core = { path = "../../../../../../../substrate/primitives/core", default-features = false } +frame-metadata-hash-extension = { path = "../../../../../../../substrate/frame/metadata-hash-extension" } frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false } +frame-system = { path = "../../../../../../../substrate/frame/system", default-features = false } pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false } pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false } pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false } pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false } +pallet-transaction-payment = { path = "../../../../../../../substrate/frame/transaction-payment", default-features = false } +pallet-asset-tx-payment = { path = "../../../../../../../substrate/frame/transaction-payment/asset-tx-payment", default-features = false } # Polkadot polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" } xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false } pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../../../../../../polkadot/xcm/xcm-fee-payment-runtime-api", default-features = false } westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } # Cumulus diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index bf013697b4c750c8a9f3da3732e97386ba1cae74..61eb70524fc9ae2a23e5061400c57ca719bae4e1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -21,3 +21,4 @@ mod set_xcm_versions; mod swap; mod teleport; mod treasury; +mod xcm_fee_estimation; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/xcm_fee_estimation.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/xcm_fee_estimation.rs new file mode 100644 index 0000000000000000000000000000000000000000..3e311ef95652ea2e3364d9f2964bacc95c050def --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/xcm_fee_estimation.rs @@ -0,0 +1,371 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests to ensure correct XCM fee estimation for cross-chain asset transfers. + +use crate::imports::*; + +use sp_keyring::AccountKeyring::Alice; +use sp_runtime::{generic, MultiSignature}; +use xcm_fee_payment_runtime_api::{ + dry_run::runtime_decl_for_xcm_dry_run_api::XcmDryRunApiV1, + fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, +}; + +/// We are able to dry-run and estimate the fees for a teleport between relay and system para. +/// Scenario: Alice on Westend relay chain wants to teleport WND to Asset Hub. +/// We want to know the fees using the `XcmDryRunApi` and `XcmPaymentApi`. +#[test] +fn teleport_relay_system_para_works() { + let destination: Location = Parachain(1000).into(); // Asset Hub. + let beneficiary_id = AssetHubWestendReceiver::get(); + let beneficiary: Location = AccountId32 { id: beneficiary_id.clone().into(), network: None } // Test doesn't allow specifying a network here. + .into(); // Beneficiary in Asset Hub. + let teleport_amount = 1_000_000_000_000; // One WND (12 decimals). + let assets: Assets = vec![(Here, teleport_amount).into()].into(); + + // We get them from the Westend closure. + let mut delivery_fees_amount = 0; + let mut remote_message = VersionedXcm::V4(Xcm(Vec::new())); + ::new_ext().execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + + let call = RuntimeCall::XcmPallet(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::V4(destination.clone())), + beneficiary: Box::new(VersionedLocation::V4(beneficiary)), + assets: Box::new(VersionedAssets::V4(assets)), + fee_asset_item: 0, + weight_limit: Unlimited, + }); + let sender = Alice; // Is the same as `WestendSender`. + let extrinsic = construct_extrinsic_westend(sender, call); + let result = Runtime::dry_run_extrinsic(extrinsic).unwrap(); + assert_eq!(result.forwarded_xcms.len(), 1); + let (destination_to_query, messages_to_query) = &result.forwarded_xcms[0]; + assert_eq!(messages_to_query.len(), 1); + remote_message = messages_to_query[0].clone(); + let delivery_fees = + Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone()) + .unwrap(); + delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees); + }); + + // This is set in the AssetHubWestend closure. + let mut remote_execution_fees = 0; + ::execute_with(|| { + type Runtime = ::Runtime; + + let weight = Runtime::query_xcm_weight(remote_message.clone()).unwrap(); + remote_execution_fees = + Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::V4(Parent.into())) + .unwrap(); + }); + + let test_args = TestContext { + sender: WestendSender::get(), // Alice. + receiver: AssetHubWestendReceiver::get(), // Bob in Asset Hub. + args: TestArgs::new_relay(destination, beneficiary_id, teleport_amount), + }; + let mut test = RelayToSystemParaTest::new(test_args); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + assert_eq!(sender_balance_before, 1_000_000_000_000_000_000); + assert_eq!(receiver_balance_before, 4_096_000_000_000); + + test.set_dispatchable::(transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + // We now know the exact fees. + assert_eq!( + sender_balance_after, + sender_balance_before - delivery_fees_amount - teleport_amount + ); + assert_eq!( + receiver_balance_after, + receiver_balance_before + teleport_amount - remote_execution_fees + ); +} + +/// We are able to dry-run and estimate the fees for a multi-hop XCM journey. +/// Scenario: Alice on PenpalA has some WND and wants to send them to PenpalB. +/// We want to know the fees using the `XcmDryRunApi` and `XcmPaymentApi`. +#[test] +fn multi_hop_works() { + let destination = PenpalA::sibling_location_of(PenpalB::para_id()); + let sender = PenpalASender::get(); + let amount_to_send = 1_000_000_000_000; // One WND (12 decimals). + let asset_owner = PenpalAssetOwner::get(); + let assets: Assets = (Parent, amount_to_send).into(); + let relay_native_asset_location = RelayLocation::get(); + let sender_as_seen_by_relay = Westend::child_location_of(PenpalA::para_id()); + let sov_of_sender_on_relay = Westend::sovereign_account_id_of(sender_as_seen_by_relay.clone()); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner.clone()), + relay_native_asset_location.clone(), + sender.clone(), + amount_to_send * 2, + ); + + // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve + Westend::fund_accounts(vec![(sov_of_sender_on_relay.clone().into(), amount_to_send * 2)]); + + // Init values for Parachain Destination + let beneficiary_id = PenpalBReceiver::get(); + let beneficiary: Location = AccountId32 { + id: beneficiary_id.clone().into(), + network: None, // Test doesn't allow specifying a network here. + } + .into(); + + // We get them from the PenpalA closure. + let mut delivery_fees_amount = 0; + let mut remote_message = VersionedXcm::V4(Xcm(Vec::new())); + ::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + + let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::V4(destination.clone())), + beneficiary: Box::new(VersionedLocation::V4(beneficiary)), + assets: Box::new(VersionedAssets::V4(assets.clone())), + fee_asset_item: 0, + weight_limit: Unlimited, + }); + let sender = Alice; // Same as `PenpalASender`. + let extrinsic = construct_extrinsic_penpal(sender, call); + let result = Runtime::dry_run_extrinsic(extrinsic).unwrap(); + assert_eq!(result.forwarded_xcms.len(), 1); + let (destination_to_query, messages_to_query) = &result.forwarded_xcms[0]; + assert_eq!(messages_to_query.len(), 1); + remote_message = messages_to_query[0].clone(); + let delivery_fees = + Runtime::query_delivery_fees(destination_to_query.clone(), remote_message.clone()) + .unwrap(); + delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees); + }); + + // This is set in the Westend closure. + let mut intermediate_execution_fees = 0; + let mut intermediate_delivery_fees_amount = 0; + let mut intermediate_remote_message = VersionedXcm::V4(Xcm::<()>(Vec::new())); + ::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + + // First we get the execution fees. + let weight = Runtime::query_xcm_weight(remote_message.clone()).unwrap(); + intermediate_execution_fees = + Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::V4(Here.into())).unwrap(); + + // We have to do this to turn `VersionedXcm<()>` into `VersionedXcm`. + let xcm_program = + VersionedXcm::V4(Xcm::::from(remote_message.clone().try_into().unwrap())); + + // Now we get the delivery fees to the final destination. + let result = + Runtime::dry_run_xcm(sender_as_seen_by_relay.clone().into(), xcm_program).unwrap(); + let (destination_to_query, messages_to_query) = &result.forwarded_xcms[0]; + // There's actually two messages here. + // One created when the message we sent from PenpalA arrived and was executed. + // The second one when we dry-run the xcm. + // We could've gotten the message from the queue without having to dry-run, but + // offchain applications would have to dry-run, so we do it here as well. + intermediate_remote_message = messages_to_query[0].clone(); + let delivery_fees = Runtime::query_delivery_fees( + destination_to_query.clone(), + intermediate_remote_message.clone(), + ) + .unwrap(); + intermediate_delivery_fees_amount = get_amount_from_versioned_assets(delivery_fees); + }); + + // Get the final execution fees in the destination. + let mut final_execution_fees = 0; + ::execute_with(|| { + type Runtime = ::Runtime; + + let weight = Runtime::query_xcm_weight(intermediate_remote_message.clone()).unwrap(); + final_execution_fees = + Runtime::query_weight_to_asset_fee(weight, VersionedAssetId::V4(Parent.into())) + .unwrap(); + }); + + // Dry-running is done. + PenpalA::reset_ext(); + Westend::reset_ext(); + PenpalB::reset_ext(); + + // Fund accounts again. + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location.clone(), + sender.clone(), + amount_to_send * 2, + ); + Westend::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); + + // Actually run the extrinsic. + let test_args = TestContext { + sender: PenpalASender::get(), // Alice. + receiver: PenpalBReceiver::get(), // Bob in PenpalB. + args: TestArgs::new_para( + destination, + beneficiary_id.clone(), + amount_to_send, + assets, + None, + 0, + ), + }; + let mut test = ParaToParaThroughRelayTest::new(test_args); + + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.clone(), &sender) + }); + let receiver_assets_before = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.clone(), &beneficiary_id) + }); + + test.set_dispatchable::(transfer_assets_para_to_para); + test.assert(); + + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.clone(), &sender) + }); + let receiver_assets_after = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &beneficiary_id) + }); + + // We know the exact fees on every hop. + assert_eq!( + sender_assets_after, + sender_assets_before - amount_to_send - delivery_fees_amount /* This is charged directly + * from the sender's + * account. */ + ); + assert_eq!( + receiver_assets_after, + receiver_assets_before + amount_to_send - + intermediate_execution_fees - + intermediate_delivery_fees_amount - + final_execution_fees + ); +} + +fn get_amount_from_versioned_assets(assets: VersionedAssets) -> u128 { + let latest_assets: Assets = assets.try_into().unwrap(); + let Fungible(amount) = latest_assets.inner()[0].fun else { + unreachable!("asset is fungible"); + }; + amount +} + +fn transfer_assets(test: RelayToSystemParaTest) -> DispatchResult { + ::XcmPallet::transfer_assets( + test.signed_origin, + bx!(test.args.dest.into()), + bx!(test.args.beneficiary.into()), + bx!(test.args.assets.into()), + test.args.fee_asset_item, + test.args.weight_limit, + ) +} + +fn transfer_assets_para_to_para(test: ParaToParaThroughRelayTest) -> DispatchResult { + ::PolkadotXcm::transfer_assets( + test.signed_origin, + bx!(test.args.dest.into()), + bx!(test.args.beneficiary.into()), + bx!(test.args.assets.into()), + test.args.fee_asset_item, + test.args.weight_limit, + ) +} + +// Constructs the SignedExtra component of an extrinsic for the Westend runtime. +fn construct_extrinsic_westend( + sender: sp_keyring::AccountKeyring, + call: westend_runtime::RuntimeCall, +) -> westend_runtime::UncheckedExtrinsic { + type Runtime = ::Runtime; + let account_id = ::AccountId::from(sender.public()); + let tip = 0; + let extra: westend_runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckMortality::::from(sp_runtime::generic::Era::immortal()), + frame_system::CheckNonce::::from( + frame_system::Pallet::::account(&account_id).nonce, + ), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), + ); + let raw_payload = westend_runtime::SignedPayload::new(call, extra).unwrap(); + let signature = raw_payload.using_encoded(|payload| sender.sign(payload)); + let (call, extra, _) = raw_payload.deconstruct(); + westend_runtime::UncheckedExtrinsic::new_signed( + call, + account_id.into(), + MultiSignature::Sr25519(signature), + extra, + ) +} + +// Constructs the SignedExtra component of an extrinsic for the Westend runtime. +fn construct_extrinsic_penpal( + sender: sp_keyring::AccountKeyring, + call: penpal_runtime::RuntimeCall, +) -> penpal_runtime::UncheckedExtrinsic { + type Runtime = ::Runtime; + let account_id = ::AccountId::from(sender.public()); + let tip = 0; + let extra: penpal_runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::immortal()), + frame_system::CheckNonce::::from( + frame_system::Pallet::::account(&account_id).nonce, + ), + frame_system::CheckWeight::::new(), + pallet_asset_tx_payment::ChargeAssetTxPayment::::from(tip, None), + ); + type SignedPayload = + generic::SignedPayload; + let raw_payload = SignedPayload::new(call, extra).unwrap(); + let signature = raw_payload.using_encoded(|payload| sender.sign(payload)); + let (call, extra, _) = raw_payload.deconstruct(); + penpal_runtime::UncheckedExtrinsic::new_signed( + call, + account_id.into(), + MultiSignature::Sr25519(signature), + extra, + ) +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index bbe54c367baf41d183dd60f976a7951d20d8a6f2..bed5af92f6e55b37f7f12518dbe1ed1b290dd5aa 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } hex-literal = "0.4.1" diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs index a1d871cdb618fdddfbbbc3e7812d0ec7f7ae7866..78788634e6ff45c10b5fbebc91da4843d8f595e3 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs @@ -61,10 +61,13 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable #[test] fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // Initially set only default version on all runtimes - AssetHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - AssetHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + + AssetHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubWestend::force_default_xcm_version(Some(older_xcm_version)); + AssetHubWestend::force_default_xcm_version(Some(older_xcm_version)); // prepare data let destination = asset_hub_westend_location(); @@ -87,42 +90,12 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ); // set destination version - AssetHubRococo::force_xcm_version(destination.clone(), xcm::v3::prelude::XCM_VERSION); - - // TODO: remove this block, when removing `xcm:v2` - { - // send XCM from AssetHubRococo - fails - AssetHubRococo is set to the default/safe `2` - // version, which does not have the `ExportMessage` instruction. If the default `2` is - // changed to `3`, then this assert can go away" - assert_err!( - send_asset_from_asset_hub_rococo(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - - // set exact version for BridgeHubWestend to `2` without `ExportMessage` instruction - AssetHubRococo::force_xcm_version( - ParentThen(Parachain(BridgeHubRococo::para_id().into()).into()).into(), - xcm::v2::prelude::XCM_VERSION, - ); - // send XCM from AssetHubRococo - fails - `ExportMessage` is not in `2` - assert_err!( - send_asset_from_asset_hub_rococo(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - } + AssetHubRococo::force_xcm_version(destination.clone(), newer_xcm_version); // set version with `ExportMessage` for BridgeHubRococo AssetHubRococo::force_xcm_version( ParentThen(Parachain(BridgeHubRococo::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubRococo - ok assert_ok!(send_asset_from_asset_hub_rococo( @@ -134,14 +107,11 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_bridge_hub_rococo_message_accepted(false); // set version for remote BridgeHub on BridgeHubRococo - BridgeHubRococo::force_xcm_version( - bridge_hub_westend_location(), - xcm::v3::prelude::XCM_VERSION, - ); + BridgeHubRococo::force_xcm_version(bridge_hub_westend_location(), newer_xcm_version); // set version for AssetHubWestend on BridgeHubWestend BridgeHubWestend::force_xcm_version( ParentThen(Parachain(AssetHubWestend::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubRococo - ok @@ -164,20 +134,4 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ] ); }); - - // TODO: remove this block, when removing `xcm:v2` - { - // set `2` version for remote BridgeHub on BridgeHubRococo, which does not have - // `UniversalOrigin` and `DescendOrigin` - BridgeHubRococo::force_xcm_version( - bridge_hub_westend_location(), - xcm::v2::prelude::XCM_VERSION, - ); - - // send XCM from AssetHubRococo - ok - assert_ok!(send_asset_from_asset_hub_rococo(destination, (native_token, amount))); - // message is not accepted on the local BridgeHub (`DestinationUnsupported`) because we - // cannot add `UniversalOrigin` and `DescendOrigin` - assert_bridge_hub_rococo_message_accepted(false); - } } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs index b01be5e8dc84b4edf35651d0388baa1462b54c9b..8539df97be9331ea1126a56a70a47ac3a597ce5b 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs @@ -61,10 +61,13 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable #[test] fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // Initially set only default version on all runtimes - AssetHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - AssetHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + + AssetHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubWestend::force_default_xcm_version(Some(older_xcm_version)); + AssetHubWestend::force_default_xcm_version(Some(older_xcm_version)); // prepare data let destination = asset_hub_rococo_location(); @@ -87,42 +90,12 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ); // set destination version - AssetHubWestend::force_xcm_version(destination.clone(), xcm::v3::prelude::XCM_VERSION); - - // TODO: remove this block, when removing `xcm:v2` - { - // send XCM from AssetHubRococo - fails - AssetHubRococo is set to the default/safe `2` - // version, which does not have the `ExportMessage` instruction. If the default `2` is - // changed to `3`, then this assert can go away" - assert_err!( - send_asset_from_asset_hub_westend(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - - // set exact version for BridgeHubWestend to `2` without `ExportMessage` instruction - AssetHubWestend::force_xcm_version( - ParentThen(Parachain(BridgeHubWestend::para_id().into()).into()).into(), - xcm::v2::prelude::XCM_VERSION, - ); - // send XCM from AssetHubWestend - fails - `ExportMessage` is not in `2` - assert_err!( - send_asset_from_asset_hub_westend(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - } + AssetHubWestend::force_xcm_version(destination.clone(), newer_xcm_version); // set version with `ExportMessage` for BridgeHubWestend AssetHubWestend::force_xcm_version( ParentThen(Parachain(BridgeHubWestend::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubWestend - ok assert_ok!(send_asset_from_asset_hub_westend( @@ -134,14 +107,11 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_bridge_hub_westend_message_accepted(false); // set version for remote BridgeHub on BridgeHubWestend - BridgeHubWestend::force_xcm_version( - bridge_hub_rococo_location(), - xcm::v3::prelude::XCM_VERSION, - ); + BridgeHubWestend::force_xcm_version(bridge_hub_rococo_location(), newer_xcm_version); // set version for AssetHubRococo on BridgeHubRococo BridgeHubRococo::force_xcm_version( ParentThen(Parachain(AssetHubRococo::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubWestend - ok @@ -164,20 +134,4 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ] ); }); - - // TODO: remove this block, when removing `xcm:v2` - { - // set `2` version for remote BridgeHub on BridgeHubRococo, which does not have - // `UniversalOrigin` and `DescendOrigin` - BridgeHubWestend::force_xcm_version( - bridge_hub_rococo_location(), - xcm::v2::prelude::XCM_VERSION, - ); - - // send XCM from AssetHubWestend - ok - assert_ok!(send_asset_from_asset_hub_westend(destination, (native_token, amount))); - // message is not accepted on the local BridgeHub (`DestinationUnsupported`) because we - // cannot add `UniversalOrigin` and `DescendOrigin` - assert_bridge_hub_westend_message_accepted(false); - } } diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml index d1dbef9fc4156c08b2c52f54a3759de763c959e0..297f68de6218317017a36c9535ad581aa86e2883 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml @@ -11,7 +11,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } assert_matches = "1.5.0" # Substrate diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml index 1570aa7662fcbbfe1b018251d2700ce2d653d165..29a939951e597a939de5ed9d244193ac8455e4d5 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml @@ -8,7 +8,7 @@ description = "People Rococo runtime integration tests with xcm-emulator" publish = false [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } # Substrate sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml index bc093dc0de6356d7cd98d20d12d63748ed248ff5..6eab6f52aa72172ecc19fa891109fc9df859ec3c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml @@ -8,7 +8,7 @@ description = "People Westend runtime integration tests with xcm-emulator" publish = false [dependencies] -codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } # Substrate sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false } diff --git a/cumulus/parachains/pallets/collective-content/Cargo.toml b/cumulus/parachains/pallets/collective-content/Cargo.toml index 207259bee52ceb68ba45b1237100cfe5367201f7..92e0a54631394154634900829c708431b2931b67 100644 --- a/cumulus/parachains/pallets/collective-content/Cargo.toml +++ b/cumulus/parachains/pallets/collective-content/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true } diff --git a/cumulus/parachains/pallets/collective-content/src/mock.rs b/cumulus/parachains/pallets/collective-content/src/mock.rs index 5cb0126425e59a67332d880cc8b925f50b1753c2..91f9c29933d91dd9be6f604c28da869317a5003d 100644 --- a/cumulus/parachains/pallets/collective-content/src/mock.rs +++ b/cumulus/parachains/pallets/collective-content/src/mock.rs @@ -18,9 +18,7 @@ pub use crate as pallet_collective_content; use crate::WeightInfo; use frame_support::{ - derive_impl, ord_parameter_types, parameter_types, - traits::{ConstU32, ConstU64}, - weights::Weight, + derive_impl, ord_parameter_types, parameter_types, traits::ConstU32, weights::Weight, }; use frame_system::EnsureSignedBy; use sp_runtime::{traits::IdentityLookup, BuildStorage}; @@ -70,7 +68,6 @@ impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/cumulus/parachains/pallets/parachain-info/Cargo.toml b/cumulus/parachains/pallets/parachain-info/Cargo.toml index 17981d238fd1880e81ce04ebbe5b2a045ba27e41..01ee12bf4e719a9fde63fa4adb43bc6ff4e5c3ea 100644 --- a/cumulus/parachains/pallets/parachain-info/Cargo.toml +++ b/cumulus/parachains/pallets/parachain-info/Cargo.toml @@ -10,7 +10,7 @@ description = "Pallet to store the parachain ID" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../../../substrate/frame/support", default-features = false } diff --git a/cumulus/parachains/pallets/ping/Cargo.toml b/cumulus/parachains/pallets/ping/Cargo.toml index 15169b08b9108998d850f6333e458d73580d1b2a..f51946e9ebd5d2c5fd471683a217fe2dbe8f2f61 100644 --- a/cumulus/parachains/pallets/ping/Cargo.toml +++ b/cumulus/parachains/pallets/ping/Cargo.toml @@ -10,7 +10,7 @@ description = "Ping Pallet for Cumulus XCM/UMP testing." workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-std = { path = "../../../../substrate/primitives/std", default-features = false } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 47574783810a024caf971adc087313d8336dde73..a880730ddacfdde9fcbda95fefb457af031b3da7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } hex-literal = { version = "0.4.1" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -18,6 +18,7 @@ scale-info = { version = "2.11.1", default-features = false, features = ["derive # Substrate frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-executive = { path = "../../../../../substrate/frame/executive", default-features = false } +frame-metadata-hash-extension = { path = "../../../../../substrate/frame/metadata-hash-extension", default-features = false } frame-support = { path = "../../../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../../../substrate/frame/system", default-features = false } frame-system-benchmarking = { path = "../../../../../substrate/frame/system/benchmarking", default-features = false, optional = true } @@ -37,7 +38,6 @@ pallet-nfts = { path = "../../../../../substrate/frame/nfts", default-features = pallet-nfts-runtime-api = { path = "../../../../../substrate/frame/nfts/runtime-api", default-features = false } pallet-proxy = { path = "../../../../../substrate/frame/proxy", default-features = false } pallet-session = { path = "../../../../../substrate/frame/session", default-features = false } -pallet-state-trie-migration = { path = "../../../../../substrate/frame/state-trie-migration", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false } pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } @@ -69,10 +69,11 @@ polkadot-runtime-common = { path = "../../../../../polkadot/runtime/common", def xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../../../../polkadot/xcm/xcm-fee-payment-runtime-api", default-features = false } # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } @@ -123,7 +124,6 @@ runtime-benchmarks = [ "pallet-nft-fractionalization/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", - "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", @@ -137,6 +137,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -161,7 +162,6 @@ try-runtime = [ "pallet-nfts/try-runtime", "pallet-proxy/try-runtime", "pallet-session/try-runtime", - "pallet-state-trie-migration/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", @@ -190,6 +190,7 @@ std = [ "cumulus-primitives-utility/std", "frame-benchmarking?/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", @@ -211,7 +212,6 @@ std = [ "pallet-nfts/std", "pallet-proxy/std", "pallet-session/std", - "pallet-state-trie-migration/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", @@ -246,10 +246,14 @@ std = [ "testnet-parachains-constants/std", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] +# Enable the metadata hash generation in the wasm builder. +metadata-hash = ["substrate-wasm-builder/metadata-hash"] + # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. -on-chain-release-build = ["sp-api/disable-logging"] +on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/build.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/build.rs index 239ccac19ec7778039fb1ee56f4e772b3ddd3711..99e510e22695da8dff3867e84125c68b113f6973 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/build.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/build.rs @@ -13,10 +13,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(feature = "std")] +#[cfg(all(not(feature = "metadata-hash"), feature = "std"))] fn main() { substrate_wasm_builder::WasmBuilder::build_using_defaults(); } +#[cfg(all(feature = "metadata-hash", feature = "std"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("ROC", 12) + .build(); +} + #[cfg(not(feature = "std"))] fn main() {} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 151734804632e462eb0db30faa9d0606960566ee..4705d12e60c8f8380912963c0b40e73ce7c43582 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -62,7 +62,7 @@ use frame_support::{ ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Equals, InstanceFilter, TransformOrigin, }, - weights::{ConstantMultiplier, Weight}, + weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, }; use frame_system::{ @@ -91,13 +91,19 @@ pub use sp_runtime::BuildStorage; // Polkadot imports use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; -// We exclude `Assets` since it's the name of a pallet #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ - Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, - NonFungible, Parent, ParentThen, Response, XCM_VERSION, + Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, + NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, +}; +use xcm::{ + latest::prelude::{AssetId, BodyId}, + IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm, +}; +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, }; -use xcm::latest::prelude::{AssetId, BodyId}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -112,10 +118,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 14, + transaction_version: 16, state_version: 1, }; @@ -664,7 +670,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -694,12 +700,21 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = xcm_config::XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -939,8 +954,6 @@ construct_runtime!( PoolAssets: pallet_assets:: = 55, AssetConversion: pallet_asset_conversion = 56, - StateTrieMigration: pallet_state_trie_migration = 70, - // TODO: the pallet instance should be removed once all pools have migrated // to the new account IDs. AssetConversionMigration: pallet_asset_conversion_ops = 200, @@ -966,6 +979,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = @@ -976,6 +990,7 @@ pub type Migrations = ( InitStorageVersions, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, pallet_collator_selection::migration::v2::MigrationToV2, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, @@ -1278,6 +1293,109 @@ impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { + let acceptable = vec![ + // native token + VersionedAssetId::from(AssetId(xcm_config::TokenLocation::get())) + ]; + + Ok(acceptable + .into_iter() + .filter_map(|asset| asset.into_version(xcm_version).ok()) + .collect()) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == xcm_config::TokenLocation::get() => { + // for native token + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_xcm_weight(message) + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_delivery_fees(destination, message) + } + } + + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm_executor::RecordXcm; + use xcm::prelude::*; + + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, program: VersionedXcm) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm::prelude::*; + + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let program: Xcm = program.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = program.using_encoded(sp_core::hashing::blake2_256); + let result = xcm_executor::XcmExecutor::::prepare_and_execute( + origin_location, + program, + &mut hash, + Weight::MAX, // Max limit available for execution. + Weight::zero(), + ); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } + impl cumulus_primitives_core::CollectCollationInfo for Runtime { fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { ParachainSystem::collect_collation_info(header) @@ -1417,7 +1535,7 @@ impl_runtime_apis! { } fn set_up_complex_asset_transfer( - ) -> Option<(xcm::v4::Assets, u32, Location, Box)> { + ) -> Option<(XcmAssets, u32, Location, Box)> { // Transfer to Relay some local AH asset (local-reserve-transfer) while paying // fees using teleported native token. // (We don't care that Relay doesn't accept incoming unknown AH local asset) @@ -1448,7 +1566,7 @@ impl_runtime_apis! { ); let transfer_asset: Asset = (asset_location, asset_amount).into(); - let assets: xcm::v4::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into(); let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; // verify transferred successfully @@ -1516,7 +1634,7 @@ impl_runtime_apis! { fn valid_destination() -> Result { Ok(TokenLocation::get()) } - fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets { + fn worst_case_holding(depositable_count: u32) -> XcmAssets { // A mix of fungible, non-fungible, and concrete assets. let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count; let holding_fungibles = holding_non_fungibles.saturating_sub(2); // -2 for two `iter::once` bellow @@ -1577,7 +1695,7 @@ impl_runtime_apis! { (0u64, Response::Version(Default::default())) } - fn worst_case_asset_exchange() -> Result<(xcm::v4::Assets, xcm::v4::Assets), BenchmarkError> { + fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> { Err(BenchmarkError::Skip) } @@ -1596,9 +1714,9 @@ impl_runtime_apis! { Ok(TokenLocation::get()) } - fn claimable_asset() -> Result<(Location, Location, xcm::v4::Assets), BenchmarkError> { + fn claimable_asset() -> Result<(Location, Location, XcmAssets), BenchmarkError> { let origin = TokenLocation::get(); - let assets: xcm::v4::Assets = (TokenLocation::get(), 1_000 * UNITS).into(); + let assets: XcmAssets = (TokenLocation::get(), 1_000 * UNITS).into(); let ticket = Location { parents: 0, interior: Here }; Ok((origin, ticket, assets)) } @@ -1676,49 +1794,6 @@ cumulus_pallet_parachain_system::register_validate_block! { BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } -parameter_types! { - // The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high) - pub const MigrationSignedDepositPerItem: Balance = CENTS; - pub const MigrationSignedDepositBase: Balance = 2_000 * CENTS; - pub const MigrationMaxKeyLen: u32 = 512; -} - -impl pallet_state_trie_migration::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type RuntimeHoldReason = RuntimeHoldReason; - type SignedDepositPerItem = MigrationSignedDepositPerItem; - type SignedDepositBase = MigrationSignedDepositBase; - // An origin that can control the whole pallet: should be Root, or a part of your council. - type ControlOrigin = frame_system::EnsureSignedBy; - // specific account for the migration, can trigger the signed migrations. - type SignedFilter = frame_system::EnsureSignedBy; - - // Replace this with weight based on your runtime. - type WeightInfo = pallet_state_trie_migration::weights::SubstrateWeight; - - type MaxKeyLen = MigrationMaxKeyLen; -} - -frame_support::ord_parameter_types! { - pub const MigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); - pub const RootMigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); -} - -#[test] -fn ensure_key_ss58() { - use frame_support::traits::SortedMembers; - use sp_core::crypto::Ss58Codec; - let acc = - AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); - //panic!("{:x?}", acc); - assert_eq!(acc, MigController::sorted_members()[0]); - let acc = - AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); - assert_eq!(acc, RootMigController::sorted_members()[0]); - //panic!("{:x?}", acc); -} - #[cfg(test)] mod tests { use super::*; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs index 299a801ebd5964829271d6575a60a123f156b7e3..35d7e1985c515879e210ab4ee6cd56c276fbbac2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_706_000 picoseconds. - Weight::from_parts(43_378_000, 0) + // Minimum execution time: 43_472_000 picoseconds. + Weight::from_parts(44_389_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 33_090_000 picoseconds. - Weight::from_parts(33_703_000, 0) + // Minimum execution time: 34_211_000 picoseconds. + Weight::from_parts(35_075_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 12_678_000 picoseconds. - Weight::from_parts(13_068_000, 0) + // Minimum execution time: 12_751_000 picoseconds. + Weight::from_parts(13_221_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 17_336_000 picoseconds. - Weight::from_parts(17_824_000, 0) + // Minimum execution time: 17_530_000 picoseconds. + Weight::from_parts(17_979_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 44_817_000 picoseconds. - Weight::from_parts(45_453_000, 0) + // Minimum execution time: 45_913_000 picoseconds. + Weight::from_parts(47_447_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_468_000 picoseconds. - Weight::from_parts(42_093_000, 0) + // Minimum execution time: 42_435_000 picoseconds. + Weight::from_parts(44_712_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 15_344_000 picoseconds. - Weight::from_parts(15_878_000, 0) + // Minimum execution time: 15_407_000 picoseconds. + Weight::from_parts(16_104_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 15_067_000 picoseconds. - Weight::from_parts(15_281_000, 0) + // Minimum execution time: 15_494_000 picoseconds. + Weight::from_parts(15_793_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 11_009 - .saturating_add(Weight::from_parts(13_050_024, 0).saturating_mul(u.into())) + // Standard Error: 11_778 + .saturating_add(Weight::from_parts(13_198_951, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_139_000 picoseconds. - Weight::from_parts(5_511_000, 0) + // Minimum execution time: 5_368_000 picoseconds. + Weight::from_parts(5_674_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 27_491_000 picoseconds. + Weight::from_parts(28_444_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_290_000 picoseconds. + Weight::from_parts(19_227_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index a73c1cc33ea0b958bf165fa54cd554548562f099..664d2b9c9dd593536404f02d895a414e6c232bfa 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -424,6 +424,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 554659415a0dc4d87dddb63ebcaf08ef356496eb..953f6a8b4009a5ab86cc7d1177dfbb993d291c8d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -10,14 +10,15 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -hex-literal = { version = "0.4.1", optional = true } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } +hex-literal = { version = "0.4.1" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-executive = { path = "../../../../../substrate/frame/executive", default-features = false } +frame-metadata-hash-extension = { path = "../../../../../substrate/frame/metadata-hash-extension", default-features = false } frame-support = { path = "../../../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../../../substrate/frame/system", default-features = false } frame-system-benchmarking = { path = "../../../../../substrate/frame/system/benchmarking", default-features = false, optional = true } @@ -36,6 +37,7 @@ pallet-nfts = { path = "../../../../../substrate/frame/nfts", default-features = pallet-nfts-runtime-api = { path = "../../../../../substrate/frame/nfts/runtime-api", default-features = false } pallet-proxy = { path = "../../../../../substrate/frame/proxy", default-features = false } pallet-session = { path = "../../../../../substrate/frame/session", default-features = false } +pallet-state-trie-migration = { path = "../../../../../substrate/frame/state-trie-migration", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false } pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } @@ -66,11 +68,12 @@ westend-runtime-constants = { path = "../../../../../polkadot/runtime/westend/co xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../../../../polkadot/xcm/xcm-fee-payment-runtime-api", default-features = false } # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } @@ -92,7 +95,6 @@ bp-bridge-hub-rococo = { path = "../../../../../bridges/chains/chain-bridge-hub- bp-bridge-hub-westend = { path = "../../../../../bridges/chains/chain-bridge-hub-westend", default-features = false } [dev-dependencies] -hex-literal = "0.4.1" asset-test-utils = { path = "../test-utils" } [build-dependencies] @@ -111,7 +113,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "hex-literal", "pallet-asset-conversion-ops/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", @@ -122,6 +123,7 @@ runtime-benchmarks = [ "pallet-nft-fractionalization/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", + "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", @@ -134,6 +136,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -158,6 +161,7 @@ try-runtime = [ "pallet-nfts/try-runtime", "pallet-proxy/try-runtime", "pallet-session/try-runtime", + "pallet-state-trie-migration/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", @@ -186,6 +190,7 @@ std = [ "cumulus-primitives-utility/std", "frame-benchmarking?/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", @@ -207,6 +212,7 @@ std = [ "pallet-nfts/std", "pallet-proxy/std", "pallet-session/std", + "pallet-state-trie-migration/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", @@ -239,10 +245,14 @@ std = [ "westend-runtime-constants/std", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] +# Enable the metadata hash generation in the wasm builder. +metadata-hash = ["substrate-wasm-builder/metadata-hash"] + # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. -on-chain-release-build = ["sp-api/disable-logging"] +on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/build.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/build.rs index 239ccac19ec7778039fb1ee56f4e772b3ddd3711..cf9664aeb2f3e4ae8cfd74c24c833ba7021a3432 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/build.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/build.rs @@ -13,10 +13,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(feature = "std")] +#[cfg(all(not(feature = "metadata-hash"), feature = "std"))] fn main() { substrate_wasm_builder::WasmBuilder::build_using_defaults(); } +#[cfg(all(feature = "metadata-hash", feature = "std"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("WND", 12) + .build(); +} + #[cfg(not(feature = "std"))] fn main() {} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 64127c80b6d5796c7ee2d9f1708b5c3baa63d036..a82094d6f8a65b9b5fc1382d055bd3dc2fcb2bcb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -45,7 +45,7 @@ use frame_support::{ AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, InstanceFilter, TransformOrigin, }, - weights::{ConstantMultiplier, Weight}, + weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, }; use frame_system::{ @@ -74,9 +74,10 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use testnet_parachains_constants::westend::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ - ForeignAssetsConvertedConcreteId, PoolAssetsConvertedConcreteId, - TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, WestendLocation, - WestendLocationV3, XcmOriginToTransactDispatchOrigin, + ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, + PoolAssetsConvertedConcreteId, TrustBackedAssetsConvertedConcreteId, + TrustBackedAssetsPalletLocationV3, WestendLocation, WestendLocationV3, + XcmOriginToTransactDispatchOrigin, }; #[cfg(any(feature = "std", test))] @@ -84,16 +85,25 @@ pub use sp_runtime::BuildStorage; use assets_common::{foreign_creators::ForeignCreators, matching::FromSiblingParachain}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; +use xcm::{ + prelude::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}, + IntoVersion, +}; + // We exclude `Assets` since it's the name of a pallet use xcm::latest::prelude::AssetId; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ - Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, - NonFungible, Parent, ParentThen, Response, XCM_VERSION, + Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, + NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, +}; + +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, }; -use crate::xcm_config::ForeignCreatorsSovereignAccountOf; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; impl_opaque_keys! { @@ -110,11 +120,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westmint"), impl_name: create_runtime_str!("westmint"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 14, - state_version: 0, + transaction_version: 16, + state_version: 1, }; /// The version information used to identify this runtime when compiled natively. @@ -659,7 +669,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -687,13 +697,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -928,6 +947,8 @@ construct_runtime!( PoolAssets: pallet_assets:: = 55, AssetConversion: pallet_asset_conversion = 56, + StateTrieMigration: pallet_state_trie_migration = 70, + // TODO: the pallet instance should be removed once all pools have migrated // to the new account IDs. AssetConversionMigration: pallet_asset_conversion_ops = 200, @@ -953,6 +974,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = @@ -972,6 +994,7 @@ pub type Migrations = ( DeleteUndecodableStorage, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); @@ -1306,6 +1329,109 @@ impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { + let acceptable = vec![ + // native token + VersionedAssetId::from(AssetId(xcm_config::WestendLocation::get())) + ]; + + Ok(acceptable + .into_iter() + .filter_map(|asset| asset.into_version(xcm_version).ok()) + .collect()) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == xcm_config::WestendLocation::get() => { + // for native token + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_xcm_weight(message) + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_delivery_fees(destination, message) + } + } + + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm_executor::RecordXcm; + use xcm::prelude::*; + + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, program: VersionedXcm) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm::prelude::*; + + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let program: Xcm = program.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = program.using_encoded(sp_core::hashing::blake2_256); + let result = xcm_executor::XcmExecutor::::prepare_and_execute( + origin_location, + program, + &mut hash, + Weight::MAX, // Max limit available for execution. + Weight::zero(), + ); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi for Runtime { @@ -1503,7 +1629,7 @@ impl_runtime_apis! { } fn set_up_complex_asset_transfer( - ) -> Option<(xcm::v4::Assets, u32, Location, Box)> { + ) -> Option<(XcmAssets, u32, Location, Box)> { // Transfer to Relay some local AH asset (local-reserve-transfer) while paying // fees using teleported native token. // (We don't care that Relay doesn't accept incoming unknown AH local asset) @@ -1534,7 +1660,7 @@ impl_runtime_apis! { ); let transfer_asset: Asset = (asset_location, asset_amount).into(); - let assets: xcm::v4::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into(); let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; // verify transferred successfully @@ -1607,7 +1733,7 @@ impl_runtime_apis! { fn valid_destination() -> Result { Ok(WestendLocation::get()) } - fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets { + fn worst_case_holding(depositable_count: u32) -> XcmAssets { // A mix of fungible, non-fungible, and concrete assets. let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count; let holding_fungibles = holding_non_fungibles - 2; // -2 for two `iter::once` bellow @@ -1668,7 +1794,7 @@ impl_runtime_apis! { (0u64, Response::Version(Default::default())) } - fn worst_case_asset_exchange() -> Result<(xcm::v4::Assets, xcm::v4::Assets), BenchmarkError> { + fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> { Err(BenchmarkError::Skip) } @@ -1687,9 +1813,9 @@ impl_runtime_apis! { Ok(WestendLocation::get()) } - fn claimable_asset() -> Result<(Location, Location, xcm::v4::Assets), BenchmarkError> { + fn claimable_asset() -> Result<(Location, Location, XcmAssets), BenchmarkError> { let origin = WestendLocation::get(); - let assets: xcm::v4::Assets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into(); + let assets: XcmAssets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into(); let ticket = Location { parents: 0, interior: Here }; Ok((origin, ticket, assets)) } @@ -1766,3 +1892,44 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +parameter_types! { + // The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high) + pub const MigrationSignedDepositPerItem: Balance = CENTS; + pub const MigrationSignedDepositBase: Balance = 2_000 * CENTS; + pub const MigrationMaxKeyLen: u32 = 512; +} + +impl pallet_state_trie_migration::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + type SignedDepositPerItem = MigrationSignedDepositPerItem; + type SignedDepositBase = MigrationSignedDepositBase; + // An origin that can control the whole pallet: should be Root, or a part of your council. + type ControlOrigin = frame_system::EnsureSignedBy; + // specific account for the migration, can trigger the signed migrations. + type SignedFilter = frame_system::EnsureSignedBy; + + // Replace this with weight based on your runtime. + type WeightInfo = pallet_state_trie_migration::weights::SubstrateWeight; + + type MaxKeyLen = MigrationMaxKeyLen; +} + +frame_support::ord_parameter_types! { + pub const MigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); + pub const RootMigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); +} + +#[test] +fn ensure_key_ss58() { + use frame_support::traits::SortedMembers; + use sp_core::crypto::Ss58Codec; + let acc = + AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); + assert_eq!(acc, MigController::sorted_members()[0]); + let acc = + AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); + assert_eq!(acc, RootMigController::sorted_members()[0]); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_balances.rs index 68aceca14c1589825e588e4a5491529120da01f5..bb8ae8e5f97e2792df79496a761c173bec6e0d95 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_122_000 picoseconds. - Weight::from_parts(43_640_000, 0) + // Minimum execution time: 45_289_000 picoseconds. + Weight::from_parts(46_764_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 33_636_000 picoseconds. - Weight::from_parts(34_571_000, 0) + // Minimum execution time: 35_052_000 picoseconds. + Weight::from_parts(36_494_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 12_101_000 picoseconds. - Weight::from_parts(12_511_000, 0) + // Minimum execution time: 12_361_000 picoseconds. + Weight::from_parts(12_668_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 17_077_000 picoseconds. - Weight::from_parts(17_362_000, 0) + // Minimum execution time: 17_253_000 picoseconds. + Weight::from_parts(17_733_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 44_352_000 picoseconds. - Weight::from_parts(45_045_000, 0) + // Minimum execution time: 45_674_000 picoseconds. + Weight::from_parts(47_981_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_836_000 picoseconds. - Weight::from_parts(43_201_000, 0) + // Minimum execution time: 45_021_000 picoseconds. + Weight::from_parts(46_292_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 14_413_000 picoseconds. - Weight::from_parts(14_743_000, 0) + // Minimum execution time: 15_071_000 picoseconds. + Weight::from_parts(15_406_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_542_000 picoseconds. - Weight::from_parts(14_731_000, 0) + // Minimum execution time: 14_779_000 picoseconds. + Weight::from_parts(15_129_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 11_213 - .saturating_add(Weight::from_parts(13_160_721, 0).saturating_mul(u.into())) + // Standard Error: 10_629 + .saturating_add(Weight::from_parts(13_558_995, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_208_000 picoseconds. - Weight::from_parts(5_619_000, 0) + // Minimum execution time: 5_274_000 picoseconds. + Weight::from_parts(5_727_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 28_088_000 picoseconds. + Weight::from_parts(28_980_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 19_002_000 picoseconds. + Weight::from_parts(19_480_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index d610bfd768cdf43c7efce3ee368b6490fcf054b1..35a42627ad71004642b278bba1ff1a564929061f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -440,6 +440,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/assets/common/Cargo.toml b/cumulus/parachains/runtimes/assets/common/Cargo.toml index 12dfd9da1fffbc6d1be0edc40ab6de3ebcc78e20..4664e0cb9a7f817ed419936dfa9e5d0ac52f599e 100644 --- a/cumulus/parachains/runtimes/assets/common/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/common/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } log = { workspace = true } impl-trait-for-tuples = "0.2.2" diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 883c93c97b4de6774e86ee83b84d246dc1427f7f..af5b4a64680724abcbf0d659ba8a7b2b45cd0e80 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } # Substrate frame-support = { path = "../../../../../substrate/frame/support", default-features = false } @@ -24,7 +24,7 @@ sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-fea sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } # Cumulus -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } parachains-common = { path = "../../../common", default-features = false } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 574406ab305f33d4266dca1a3229b92a80ab9e8c..af243998d43a87a0231daa570953a6037458113d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -13,7 +13,7 @@ workspace = true substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } hex-literal = { version = "0.4.1" } @@ -69,9 +69,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = [ - "parameterized-consensus-hook", -] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = [ diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 7c2aa49088610c7a3c842a2142fc4bcac528efef..0c72b000c2a0b4a0a8b59f613463e2b5213bb1a4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -148,8 +148,9 @@ pub type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, pallet_multisig::migrations::v1::MigrateToV1, InitStorageVersions, - cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, // unreleased + cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, snowbridge_pallet_system::migration::v0::InitializeOnUpgrade< Runtime, ConstU32, @@ -209,10 +210,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-rococo"), impl_name: create_runtime_str!("bridge-hub-rococo"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 4, + transaction_version: 5, state_version: 1, }; @@ -389,7 +390,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -417,13 +418,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_balances.rs index 861ccfc51fd8e9f7bf8a1367d4ab4ddf459891a0..d67ae4dee92a8a9eec7ebefeda52fda7c08b6fab 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_696_000 picoseconds. - Weight::from_parts(42_201_000, 0) + // Minimum execution time: 41_898_000 picoseconds. + Weight::from_parts(42_690_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 32_855_000 picoseconds. - Weight::from_parts(33_554_000, 0) + // Minimum execution time: 32_745_000 picoseconds. + Weight::from_parts(33_686_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_977_000 picoseconds. - Weight::from_parts(13_473_000, 0) + // Minimum execution time: 13_352_000 picoseconds. + Weight::from_parts(13_808_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_617_000 picoseconds. - Weight::from_parts(18_234_000, 0) + // Minimum execution time: 18_248_000 picoseconds. + Weight::from_parts(18_763_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 43_174_000 picoseconds. - Weight::from_parts(43_685_000, 0) + // Minimum execution time: 43_626_000 picoseconds. + Weight::from_parts(45_333_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_125_000 picoseconds. - Weight::from_parts(41_636_000, 0) + // Minimum execution time: 41_702_000 picoseconds. + Weight::from_parts(43_366_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_749_000 picoseconds. - Weight::from_parts(16_163_000, 0) + // Minimum execution time: 15_944_000 picoseconds. + Weight::from_parts(16_512_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_238_000 picoseconds. - Weight::from_parts(14_469_000, 0) + // Minimum execution time: 14_351_000 picoseconds. + Weight::from_parts(14_568_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 11_818 - .saturating_add(Weight::from_parts(12_621_051, 0).saturating_mul(u.into())) + // Standard Error: 11_289 + .saturating_add(Weight::from_parts(13_163_759, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 4_904_000 picoseconds. - Weight::from_parts(5_459_000, 0) + // Minimum execution time: 5_174_000 picoseconds. + Weight::from_parts(5_490_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 26_681_000 picoseconds. + Weight::from_parts(27_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_105_000 picoseconds. + Weight::from_parts(19_246_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs index 8c2435599f59780be56dcaa5060addee4c5c1d15..11e1439a1f6df2423421faf85ce6dd75c37e045b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-itmxxexx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-vicqj8em-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,32 +48,52 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bridge_grandpa`. pub struct WeightInfo(PhantomData); impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:0) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::PalletOperatingMode` (r:1 w:0) /// Proof: `BridgeWestendGrandpa::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:1 w:1) /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) - /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:0) - /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::FreeHeadersRemaining` (r:1 w:0) + /// Proof: `BridgeWestendGrandpa::FreeHeadersRemaining` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::ImportedHashes` (r:1 w:1) /// Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 w:2) /// Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// The range of component `p` is `[1, 838]`. + /// The range of component `p` is `[1, 168]`. /// The range of component `v` is `[50, 100]`. - fn submit_finality_proof(p: u32, v: u32, ) -> Weight { + fn submit_finality_proof(p: u32, _v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `335 + p * (60 ±0)` + // Measured: `438 + p * (60 ±0)` // Estimated: `51735` - // Minimum execution time: 310_124_000 picoseconds. - Weight::from_parts(18_294_977, 0) + // Minimum execution time: 300_829_000 picoseconds. + Weight::from_parts(321_573_000, 0) .saturating_add(Weight::from_parts(0, 51735)) - // Standard Error: 5_665 - .saturating_add(Weight::from_parts(55_380_719, 0).saturating_mul(p.into())) - // Standard Error: 94_494 - .saturating_add(Weight::from_parts(2_765_959, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Standard Error: 25_917 + .saturating_add(Weight::from_parts(48_613_160, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashes` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 w:2) + /// Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 101_007_000 picoseconds. + Weight::from_parts(129_904_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(6)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index bd1445bee22c3246bf07ba068a8ba0a0490d0770..a0d2e91dffd2e9240ad9364e18ef52a7b3cab3b1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -239,6 +239,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml index a7241cc6d10c45a292c3e0ffc0a8044e9b2fb706..4a58528498d847322982008624575cadc17c3c7d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml @@ -13,7 +13,7 @@ workspace = true substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -65,7 +65,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 640eaf881a571115357572ce39b5bd2daaad9db4..90190da82dd16eb641ff70e1cdde709df581cbce 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -129,6 +129,7 @@ pub type Migrations = ( InitStorageVersions, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); @@ -183,10 +184,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-westend"), impl_name: create_runtime_str!("bridge-hub-westend"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 4, + transaction_version: 5, state_version: 1, }; @@ -352,7 +353,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -379,13 +380,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_balances.rs index 3afef6564bdb8fec4e435948cf8cadb928bbf773..34ce487216f24f0a93ecec89610f298c4c9eae35 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_912_000 picoseconds. - Weight::from_parts(43_690_000, 0) + // Minimum execution time: 42_637_000 picoseconds. + Weight::from_parts(44_357_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 33_823_000 picoseconds. - Weight::from_parts(34_415_000, 0) + // Minimum execution time: 33_463_000 picoseconds. + Weight::from_parts(34_484_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 13_226_000 picoseconds. - Weight::from_parts(13_557_000, 0) + // Minimum execution time: 13_115_000 picoseconds. + Weight::from_parts(13_749_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 18_055_000 picoseconds. - Weight::from_parts(18_407_000, 0) + // Minimum execution time: 17_825_000 picoseconds. + Weight::from_parts(18_471_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 44_442_000 picoseconds. - Weight::from_parts(45_101_000, 0) + // Minimum execution time: 43_669_000 picoseconds. + Weight::from_parts(45_781_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_485_000 picoseconds. - Weight::from_parts(43_157_000, 0) + // Minimum execution time: 41_572_000 picoseconds. + Weight::from_parts(43_812_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_002_000 picoseconds. - Weight::from_parts(16_425_000, 0) + // Minimum execution time: 15_538_000 picoseconds. + Weight::from_parts(16_227_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_526_000 picoseconds. - Weight::from_parts(14_825_000, 0) + // Minimum execution time: 13_979_000 picoseconds. + Weight::from_parts(14_195_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 10_967 - .saturating_add(Weight::from_parts(13_376_293, 0).saturating_mul(u.into())) + // Standard Error: 11_039 + .saturating_add(Weight::from_parts(13_102_916, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_151_000 picoseconds. - Weight::from_parts(5_419_000, 0) + // Minimum execution time: 4_959_000 picoseconds. + Weight::from_parts(5_377_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 26_604_000 picoseconds. + Weight::from_parts(27_641_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_106_000 picoseconds. + Weight::from_parts(18_637_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs index e87ed668dfc7acb1a92a7535d92392a272370277..e98be6ba39be74c3532290ea4a7b483640466c10 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-itmxxexx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-vicqj8em-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,32 +48,54 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bridge_grandpa`. pub struct WeightInfo(PhantomData); impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:0) + /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::PalletOperatingMode` (r:1 w:0) /// Proof: `BridgeRococoGrandpa::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::BestFinalized` (r:1 w:1) /// Proof: `BridgeRococoGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) - /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:0) - /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::FreeHeadersRemaining` (r:1 w:0) + /// Proof: `BridgeRococoGrandpa::FreeHeadersRemaining` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::ImportedHashesPointer` (r:1 w:1) /// Proof: `BridgeRococoGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::ImportedHashes` (r:1 w:1) /// Proof: `BridgeRococoGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::ImportedHeaders` (r:0 w:2) /// Proof: `BridgeRococoGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// The range of component `p` is `[1, 838]`. + /// The range of component `p` is `[1, 168]`. /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `231 + p * (60 ±0)` + // Measured: `268 + p * (60 ±0)` // Estimated: `51735` - // Minimum execution time: 303_549_000 picoseconds. - Weight::from_parts(306_232_000, 0) + // Minimum execution time: 291_721_000 picoseconds. + Weight::from_parts(37_495_589, 0) .saturating_add(Weight::from_parts(0, 51735)) - // Standard Error: 4_641 - .saturating_add(Weight::from_parts(55_196_301, 0).saturating_mul(p.into())) - // Standard Error: 35_813 - .saturating_add(Weight::from_parts(70_584, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Standard Error: 22_170 + .saturating_add(Weight::from_parts(45_403_072, 0).saturating_mul(p.into())) + // Standard Error: 73_977 + .saturating_add(Weight::from_parts(2_130_216, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } + /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHashes` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeRococoGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHeaders` (r:0 w:2) + /// Proof: `BridgeRococoGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `282` + // Estimated: `51735` + // Minimum execution time: 77_426_000 picoseconds. + Weight::from_parts(90_926_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(6)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index f147cd9653fe7e3eee03bf08a07cf6d3c1d94999..c2ca8e47f2a61cf6d66613daa205caddafe192b0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -206,6 +206,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml index 2f5f783ce48fb19e1087e24e712fc4dc52b607da..aece34613e6a6c4dfe100e84b0317a96ad7ee97c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml @@ -7,7 +7,7 @@ description = "Bridge hub common utilities" license = "Apache-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../../../../substrate/frame/support", default-features = false } sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index 5f2a6e050d83c3db662f8ff4896d32dc8a28fde3..80f0114cc4cadb6cd7871454eead80a0988d5e7e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } impl-trait-for-tuples = "0.2" log = { workspace = true } @@ -29,7 +29,7 @@ pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default- # Cumulus asset-test-utils = { path = "../../assets/test-utils" } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } parachains-common = { path = "../../../common", default-features = false } parachains-runtimes-test-utils = { path = "../../test-utils", default-features = false } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml index 22821170a54c9ef0faf6fb3756b6d62234bf654a..58985d71a5037a38a1accccd23f33ae87848b9db 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml @@ -10,7 +10,7 @@ description = "Westend Collectives Parachain Runtime" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } hex-literal = { version = "0.4.1" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -34,6 +34,7 @@ pallet-preimage = { path = "../../../../../substrate/frame/preimage", default-fe pallet-proxy = { path = "../../../../../substrate/frame/proxy", default-features = false } pallet-scheduler = { path = "../../../../../substrate/frame/scheduler", default-features = false } pallet-session = { path = "../../../../../substrate/frame/session", default-features = false } +pallet-state-trie-migration = { path = "../../../../../substrate/frame/state-trie-migration", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false } pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } @@ -70,7 +71,7 @@ westend-runtime-constants = { path = "../../../../../polkadot/runtime/westend/co # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } @@ -118,6 +119,7 @@ runtime-benchmarks = [ "pallet-referenda/runtime-benchmarks", "pallet-salary/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", + "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", @@ -156,6 +158,7 @@ try-runtime = [ "pallet-salary/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", + "pallet-state-trie-migration/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-treasury/try-runtime", @@ -202,6 +205,7 @@ std = [ "pallet-salary/std", "pallet-scheduler/std", "pallet-session/std", + "pallet-state-trie-migration/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/mod.rs index 0c9f428c1396bede97a67002d0554d98d62dbc39..ceef6de6b7435e453e9622a3d318669e1a3a9307 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/mod.rs @@ -220,6 +220,7 @@ impl pallet_core_fellowship::Config for Runtime { type ApproveOrigin = PromoteOrigin; type PromoteOrigin = PromoteOrigin; type EvidenceSize = ConstU32<65536>; + type MaxRank = ConstU32<9>; } pub type AmbassadorSalaryInstance = pallet_salary::Instance2; diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs index 94765287637b57d47c588d9a4359666d1b54f509..6a4a182079671f297d18bc40de0bc557911735cd 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs @@ -210,6 +210,7 @@ impl pallet_core_fellowship::Config for Runtime { EnsureCanPromoteTo, >; type EvidenceSize = ConstU32<65536>; + type MaxRank = ConstU32<9>; } pub type FellowshipSalaryInstance = pallet_salary::Instance1; diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 7274e9acdcd6cc89eb48c820dd9cab8228cf6113..29ba88df10454acd94dfdea47e12758cfe21bd70 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -44,8 +44,9 @@ pub mod xcm_config; pub mod fellowship; pub use ambassador::pallet_ambassador_origins; +use ambassador::AmbassadorCoreInstance; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; -use fellowship::{pallet_fellowship_origins, Fellows}; +use fellowship::{pallet_fellowship_origins, Fellows, FellowshipCoreInstance}; use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp}; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -117,11 +118,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("collectives-westend"), impl_name: create_runtime_str!("collectives-westend"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 5, - state_version: 0, + transaction_version: 6, + state_version: 1, }; /// The version information used to identify this runtime when compiled natively. @@ -420,7 +421,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -448,13 +449,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EitherOfDiverse, Fellows>; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -693,6 +703,8 @@ construct_runtime!( AmbassadorCore: pallet_core_fellowship:: = 73, AmbassadorSalary: pallet_salary:: = 74, AmbassadorContent: pallet_collective_content:: = 75, + + StateTrieMigration: pallet_state_trie_migration = 80, } ); @@ -725,8 +737,13 @@ type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, + // unreleased + pallet_core_fellowship::migration::MigrateV0ToV1, + // unreleased + pallet_core_fellowship::migration::MigrateV0ToV1, ); /// Executive: handles dispatch to the various modules. @@ -1080,3 +1097,44 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +parameter_types! { + // The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high) + pub const MigrationSignedDepositPerItem: Balance = CENTS; + pub const MigrationSignedDepositBase: Balance = 2_000 * CENTS; + pub const MigrationMaxKeyLen: u32 = 512; +} + +impl pallet_state_trie_migration::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + type SignedDepositPerItem = MigrationSignedDepositPerItem; + type SignedDepositBase = MigrationSignedDepositBase; + // An origin that can control the whole pallet: should be Root, or a part of your council. + type ControlOrigin = frame_system::EnsureSignedBy; + // specific account for the migration, can trigger the signed migrations. + type SignedFilter = frame_system::EnsureSignedBy; + + // Replace this with weight based on your runtime. + type WeightInfo = pallet_state_trie_migration::weights::SubstrateWeight; + + type MaxKeyLen = MigrationMaxKeyLen; +} + +frame_support::ord_parameter_types! { + pub const MigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); + pub const RootMigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52")); +} + +#[test] +fn ensure_key_ss58() { + use frame_support::traits::SortedMembers; + use sp_core::crypto::Ss58Codec; + let acc = + AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); + assert_eq!(acc, MigController::sorted_members()[0]); + let acc = + AccountId::from_ss58check("5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD").unwrap(); + assert_eq!(acc, RootMigController::sorted_members()[0]); +} diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_balances.rs index 602e7ca50c136c3c862bbf2f43fa452b9518116e..b100b0f2b1a83f6c939e25c88493814a80d29bd4 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 45_085_000 picoseconds. - Weight::from_parts(45_772_000, 0) + // Minimum execution time: 46_316_000 picoseconds. + Weight::from_parts(46_965_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 35_447_000 picoseconds. - Weight::from_parts(36_143_000, 0) + // Minimum execution time: 36_337_000 picoseconds. + Weight::from_parts(36_803_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 12_314_000 picoseconds. - Weight::from_parts(12_679_000, 0) + // Minimum execution time: 12_331_000 picoseconds. + Weight::from_parts(12_774_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 17_455_000 picoseconds. - Weight::from_parts(17_902_000, 0) + // Minimum execution time: 17_532_000 picoseconds. + Weight::from_parts(17_948_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 46_785_000 picoseconds. - Weight::from_parts(47_436_000, 0) + // Minimum execution time: 47_251_000 picoseconds. + Weight::from_parts(48_164_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_948_000 picoseconds. - Weight::from_parts(44_680_000, 0) + // Minimum execution time: 45_319_000 picoseconds. + Weight::from_parts(46_094_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 15_267_000 picoseconds. - Weight::from_parts(15_499_000, 0) + // Minimum execution time: 15_263_000 picoseconds. + Weight::from_parts(15_632_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_817_000 picoseconds. - Weight::from_parts(15_287_000, 0) + // Minimum execution time: 15_106_000 picoseconds. + Weight::from_parts(15_353_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 11_738 - .saturating_add(Weight::from_parts(13_511_800, 0).saturating_mul(u.into())) + // Standard Error: 11_570 + .saturating_add(Weight::from_parts(13_765_985, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_382_000 picoseconds. - Weight::from_parts(5_768_000, 0) + // Minimum execution time: 5_277_000 picoseconds. + Weight::from_parts(5_560_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 28_810_000 picoseconds. + Weight::from_parts(29_155_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_957_000 picoseconds. + Weight::from_parts(19_292_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index 84697c3e36341218ad959f575262c0903f5ae96d..c68f230a16dc3d35b861df5aa7667d61d4cf53cf 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -220,6 +220,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml index 74c5b5f8115958d0894af621e6c7307e3f67b9b7..c9dd279e9c080e7ff2c1d570391fdbeb56f09d69 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1", optional = true } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -67,7 +67,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 988195d88d876c49941463e8103f08d6c8f3ab10..1222e11e9a6888850db8739b60194bece3d7ca42 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -106,6 +106,7 @@ pub type Migrations = ( pallet_contracts::Migration, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); @@ -136,10 +137,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("contracts-rococo"), impl_name: create_runtime_str!("contracts-rococo"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 6, + transaction_version: 7, state_version: 1, }; @@ -318,7 +319,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index ac15ac5b0f0f524c560f50dcd5ea7a73e2051ae3..ef5ded1731d0d9f3ff60e1e8cb71cd1fe18ca81b 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -202,6 +202,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. @@ -283,7 +284,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { cumulus_primitives_core::ParaId, parachains_common::message_queue::ParaIdToSibling, >; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EitherOfDiverse< EnsureRoot, EnsureXcm>, @@ -293,6 +298,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml index ee9f5e87ec876d73d80eb088806f5b36f12079db..ad85aab1f8acf5a42ffc08f1c8e973c95909df76 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml @@ -13,7 +13,7 @@ workspace = true substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hex-literal = "0.4.1" log = { workspace = true } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } @@ -65,7 +65,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 895890da7dd60dae5c5a5fd257184fa734a68808..f43bb1c1e41b86391aee8fab8299095188dfc8b6 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -110,6 +110,7 @@ pub type UncheckedExtrinsic = pub type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, pallet_broker::migration::MigrateV0ToV1, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, @@ -136,10 +137,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-rococo"), impl_name: create_runtime_str!("coretime-rococo"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 0, + transaction_version: 1, state_version: 1, }; @@ -301,7 +302,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -341,13 +342,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_balances.rs index aac7e10936615fddf39f9c306121dd9eda826ec6..a021d11478480bb941fbd79b85ec85eef25d3a66 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_balances.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-01-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-8idpd4bs-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_557_000 picoseconds. - Weight::from_parts(42_618_000, 0) + // Minimum execution time: 43_792_000 picoseconds. + Weight::from_parts(44_475_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 33_046_000 picoseconds. - Weight::from_parts(33_550_000, 0) + // Minimum execution time: 34_144_000 picoseconds. + Weight::from_parts(34_887_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 11_804_000 picoseconds. - Weight::from_parts(12_007_000, 0) + // Minimum execution time: 11_864_000 picoseconds. + Weight::from_parts(12_253_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 16_261_000 picoseconds. - Weight::from_parts(16_655_000, 0) + // Minimum execution time: 16_448_000 picoseconds. + Weight::from_parts(17_008_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 42_967_000 picoseconds. - Weight::from_parts(43_870_000, 0) + // Minimum execution time: 44_353_000 picoseconds. + Weight::from_parts(45_131_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 41_022_000 picoseconds. - Weight::from_parts(41_475_000, 0) + // Minimum execution time: 42_899_000 picoseconds. + Weight::from_parts(43_749_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 14_339_000 picoseconds. - Weight::from_parts(14_641_000, 0) + // Minimum execution time: 14_308_000 picoseconds. + Weight::from_parts(15_020_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_241_000 picoseconds. - Weight::from_parts(14_463_000, 0) + // Minimum execution time: 14_369_000 picoseconds. + Weight::from_parts(14_525_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 12_290 - .saturating_add(Weight::from_parts(12_903_900, 0).saturating_mul(u.into())) + // Standard Error: 11_260 + .saturating_add(Weight::from_parts(13_056_576, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -154,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_116_000 picoseconds. - Weight::from_parts(5_345_000, 0) + // Minimum execution time: 5_198_000 picoseconds. + Weight::from_parts(5_430_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 27_335_000 picoseconds. + Weight::from_parts(28_146_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_390_000 picoseconds. + Weight::from_parts(18_893_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs index c5d315467c1ed8b2aabf7ac18abe10931a02951b..7fb492173dad9b88be6d32ab063c10e532155f53 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 35_051_000 picoseconds. - Weight::from_parts(35_200_000, 0) + // Minimum execution time: 19_121_000 picoseconds. + Weight::from_parts(19_582_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,21 +84,41 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 56_235_000 picoseconds. - Weight::from_parts(58_178_000, 0) + // Minimum execution time: 61_722_000 picoseconds. + Weight::from_parts(63_616_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve_transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `377` + // Estimated: `3842` + // Minimum execution time: 97_823_000 picoseconds. + Weight::from_parts(102_022_000, 0) + .saturating_add(Weight::from_parts(0, 3842)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -110,14 +130,12 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn execute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) + // Minimum execution time: 8_397_000 picoseconds. + Weight::from_parts(8_773_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -126,8 +144,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_226_000 picoseconds. - Weight::from_parts(6_403_000, 0) + // Minimum execution time: 5_806_000 picoseconds. + Weight::from_parts(6_106_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +155,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_020_000 picoseconds. - Weight::from_parts(2_100_000, 0) + // Minimum execution time: 1_802_000 picoseconds. + Weight::from_parts(1_939_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +180,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 24_387_000 picoseconds. - Weight::from_parts(24_814_000, 0) + // Minimum execution time: 24_300_000 picoseconds. + Weight::from_parts(25_359_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +204,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 27_039_000 picoseconds. - Weight::from_parts(27_693_000, 0) + // Minimum execution time: 27_579_000 picoseconds. + Weight::from_parts(28_414_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_920_000 picoseconds. - Weight::from_parts(2_082_000, 0) + // Minimum execution time: 1_762_000 picoseconds. + Weight::from_parts(1_884_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +227,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 17_141_000 picoseconds. - Weight::from_parts(17_500_000, 0) + // Minimum execution time: 16_512_000 picoseconds. + Weight::from_parts(16_818_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 17_074_000 picoseconds. - Weight::from_parts(17_431_000, 0) + // Minimum execution time: 16_368_000 picoseconds. + Weight::from_parts(16_887_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 19_139_000 picoseconds. - Weight::from_parts(19_474_000, 0) + // Minimum execution time: 17_661_000 picoseconds. + Weight::from_parts(17_963_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +272,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 24_346_000 picoseconds. - Weight::from_parts(25_318_000, 0) + // Minimum execution time: 24_498_000 picoseconds. + Weight::from_parts(25_339_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 11_777_000 picoseconds. - Weight::from_parts(12_051_000, 0) + // Minimum execution time: 10_675_000 picoseconds. + Weight::from_parts(11_106_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +295,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 17_538_000 picoseconds. - Weight::from_parts(17_832_000, 0) + // Minimum execution time: 16_520_000 picoseconds. + Weight::from_parts(16_915_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +317,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `13507` - // Minimum execution time: 33_623_000 picoseconds. - Weight::from_parts(34_186_000, 0) + // Minimum execution time: 32_851_000 picoseconds. + Weight::from_parts(33_772_000, 0) .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +331,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_363_000 picoseconds. - Weight::from_parts(3_511_000, 0) + // Minimum execution time: 3_373_000 picoseconds. + Weight::from_parts(3_534_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 23_969_000 picoseconds. - Weight::from_parts(24_347_000, 0) + // Minimum execution time: 26_027_000 picoseconds. + Weight::from_parts(26_467_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_071_000 picoseconds. - Weight::from_parts(35_031_000, 0) + // Minimum execution time: 35_692_000 picoseconds. + Weight::from_parts(36_136_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs index ec71a87b5a753a879a8157f094693140316ca792..7ff1cce2e072339dccd52c0809aafd59337db7b4 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs @@ -16,29 +16,27 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::fungible` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("coretime-rococo-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --template=./cumulus/templates/xcm-bench-template.hbs -// --chain=coretime-rococo-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm_benchmarks::fungible -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_benchmarks::fungible +// --chain=coretime-rococo-dev // --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +// --template=./cumulus/templates/xcm-bench-template.hbs +// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -56,8 +54,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `101` // Estimated: `3593` - // Minimum execution time: 19_199_000 picoseconds. - Weight::from_parts(19_784_000, 3593) + // Minimum execution time: 26_642_000 picoseconds. + Weight::from_parts(27_583_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -67,8 +65,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `101` // Estimated: `6196` - // Minimum execution time: 42_601_000 picoseconds. - Weight::from_parts(43_296_000, 6196) + // Minimum execution time: 35_124_000 picoseconds. + Weight::from_parts(36_510_000, 6196) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -90,8 +88,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `207` // Estimated: `6196` - // Minimum execution time: 62_463_000 picoseconds. - Weight::from_parts(64_142_000, 6196) + // Minimum execution time: 55_950_000 picoseconds. + Weight::from_parts(57_207_000, 6196) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -120,8 +118,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 31_417_000 picoseconds. - Weight::from_parts(32_153_000, 3571) + // Minimum execution time: 23_747_000 picoseconds. + Weight::from_parts(24_424_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -129,8 +127,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_235_000 picoseconds. - Weight::from_parts(3_331_000, 0) + // Minimum execution time: 1_853_000 picoseconds. + Weight::from_parts(1_998_000, 0) } // Storage: `System::Account` (r:1 w:1) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) @@ -138,13 +136,11 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 17_701_000 picoseconds. - Weight::from_parts(18_219_000, 3593) + // Minimum execution time: 19_164_000 picoseconds. + Weight::from_parts(19_643_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - // Storage: `System::Account` (r:1 w:1) - // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) @@ -153,6 +149,8 @@ impl WeightInfo { // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:1 w:1) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) @@ -161,8 +159,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3593` - // Minimum execution time: 41_748_000 picoseconds. - Weight::from_parts(42_401_000, 3593) + // Minimum execution time: 48_708_000 picoseconds. + Weight::from_parts(49_610_000, 3593) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -182,8 +180,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 27_455_000 picoseconds. - Weight::from_parts(27_976_000, 3571) + // Minimum execution time: 20_586_000 picoseconds. + Weight::from_parts(21_147_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 719e7543e8886a803f773126eafbc77f34749ddb..16412eb49a5267d3f3f38cdd285e8f3b248a5f99 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -16,29 +16,27 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::generic` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("coretime-rococo-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --template=./cumulus/templates/xcm-bench-template.hbs -// --chain=coretime-rococo-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm_benchmarks::generic -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_benchmarks::generic +// --chain=coretime-rococo-dev // --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +// --template=./cumulus/templates/xcm-bench-template.hbs +// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -66,8 +64,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 35_477_000 picoseconds. - Weight::from_parts(36_129_000, 3571) + // Minimum execution time: 23_760_000 picoseconds. + Weight::from_parts(24_411_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -75,8 +73,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_243_000 picoseconds. - Weight::from_parts(2_329_000, 0) + // Minimum execution time: 522_000 picoseconds. + Weight::from_parts(546_000, 0) } // Storage: `PolkadotXcm::Queries` (r:1 w:0) // Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -84,58 +82,58 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `3497` - // Minimum execution time: 8_112_000 picoseconds. - Weight::from_parts(8_275_000, 3497) + // Minimum execution time: 5_830_000 picoseconds. + Weight::from_parts(6_069_000, 3497) .saturating_add(T::DbWeight::get().reads(1)) } pub fn transact() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_960_000 picoseconds. - Weight::from_parts(9_253_000, 0) + // Minimum execution time: 5_508_000 picoseconds. + Weight::from_parts(5_801_000, 0) } pub fn refund_surplus() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_332_000 picoseconds. - Weight::from_parts(2_438_000, 0) + // Minimum execution time: 1_130_000 picoseconds. + Weight::from_parts(1_239_000, 0) } pub fn set_error_handler() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_054_000 picoseconds. - Weight::from_parts(2_119_000, 0) + // Minimum execution time: 541_000 picoseconds. + Weight::from_parts(567_000, 0) } pub fn set_appendix() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_061_000 picoseconds. - Weight::from_parts(2_133_000, 0) + // Minimum execution time: 560_000 picoseconds. + Weight::from_parts(591_000, 0) } pub fn clear_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_054_000 picoseconds. - Weight::from_parts(2_128_000, 0) + // Minimum execution time: 505_000 picoseconds. + Weight::from_parts(547_000, 0) } pub fn descend_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_791_000 picoseconds. - Weight::from_parts(2_903_000, 0) + // Minimum execution time: 538_000 picoseconds. + Weight::from_parts(565_000, 0) } pub fn clear_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_088_000 picoseconds. - Weight::from_parts(2_153_000, 0) + // Minimum execution time: 514_000 picoseconds. + Weight::from_parts(541_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -153,8 +151,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 27_721_000 picoseconds. - Weight::from_parts(28_602_000, 3571) + // Minimum execution time: 20_920_000 picoseconds. + Weight::from_parts(21_437_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -164,8 +162,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 11_468_000 picoseconds. - Weight::from_parts(11_866_000, 3555) + // Minimum execution time: 8_549_000 picoseconds. + Weight::from_parts(8_821_000, 3555) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -173,8 +171,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_125_000 picoseconds. - Weight::from_parts(2_167_000, 0) + // Minimum execution time: 525_000 picoseconds. + Weight::from_parts(544_000, 0) } // Storage: `PolkadotXcm::VersionNotifyTargets` (r:1 w:1) // Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -192,8 +190,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 22_422_000 picoseconds. - Weight::from_parts(22_924_000, 3539) + // Minimum execution time: 19_645_000 picoseconds. + Weight::from_parts(20_104_000, 3539) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -203,44 +201,44 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_880_000 picoseconds. - Weight::from_parts(4_050_000, 0) + // Minimum execution time: 2_232_000 picoseconds. + Weight::from_parts(2_334_000, 0) .saturating_add(T::DbWeight::get().writes(1)) } pub fn burn_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_432_000 picoseconds. - Weight::from_parts(3_536_000, 0) + // Minimum execution time: 883_000 picoseconds. + Weight::from_parts(945_000, 0) } pub fn expect_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_213_000 picoseconds. - Weight::from_parts(2_286_000, 0) + // Minimum execution time: 600_000 picoseconds. + Weight::from_parts(645_000, 0) } pub fn expect_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_155_000 picoseconds. - Weight::from_parts(2_239_000, 0) + // Minimum execution time: 527_000 picoseconds. + Weight::from_parts(552_000, 0) } pub fn expect_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_093_000 picoseconds. - Weight::from_parts(2_139_000, 0) + // Minimum execution time: 527_000 picoseconds. + Weight::from_parts(550_000, 0) } pub fn expect_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_345_000 picoseconds. - Weight::from_parts(2_378_000, 0) + // Minimum execution time: 657_000 picoseconds. + Weight::from_parts(703_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -258,8 +256,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 31_543_000 picoseconds. - Weight::from_parts(32_075_000, 3571) + // Minimum execution time: 24_999_000 picoseconds. + Weight::from_parts(25_671_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -267,8 +265,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_416_000 picoseconds. - Weight::from_parts(4_613_000, 0) + // Minimum execution time: 3_159_000 picoseconds. + Weight::from_parts(3_296_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -286,8 +284,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 28_050_000 picoseconds. - Weight::from_parts(28_755_000, 3571) + // Minimum execution time: 21_052_000 picoseconds. + Weight::from_parts(22_153_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -295,35 +293,35 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_073_000 picoseconds. - Weight::from_parts(2_181_000, 0) + // Minimum execution time: 547_000 picoseconds. + Weight::from_parts(584_000, 0) } pub fn set_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_049_000 picoseconds. - Weight::from_parts(2_137_000, 0) + // Minimum execution time: 506_000 picoseconds. + Weight::from_parts(551_000, 0) } pub fn clear_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_082_000 picoseconds. - Weight::from_parts(2_144_000, 0) + // Minimum execution time: 508_000 picoseconds. + Weight::from_parts(527_000, 0) } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_043_000 picoseconds. - Weight::from_parts(2_151_000, 0) + // Minimum execution time: 527_000 picoseconds. + Weight::from_parts(558_000, 0) } pub fn unpaid_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_197_000 picoseconds. - Weight::from_parts(2_293_000, 0) + // Minimum execution time: 514_000 picoseconds. + Weight::from_parts(553_000, 0) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs index 9095b5b1caaa6f7655ec1f2a0ab6302b20367679..c16b40b8675fbce2878bca4ba1106b89bbd9e9b1 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs @@ -224,6 +224,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml index 60cc7e2f765477052332b4c422facb8b19e1f5a4..4611228da299e0b2a084388e5f005e403eb8141a 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml @@ -13,7 +13,7 @@ workspace = true substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hex-literal = "0.4.1" log = { workspace = true } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } @@ -64,7 +64,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 9d080087d5dbe07d8cb75e76dc203f6fd06b20da..ff2456dc1772ac68109ed49357c099cc5dd502a3 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -136,10 +136,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-westend"), impl_name: create_runtime_str!("coretime-westend"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 0, + transaction_version: 1, state_version: 1, }; @@ -302,7 +302,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -342,13 +342,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_balances.rs index c4770a7c94381cfca9404a6577c703164f215918..7024c58d97f961199784890142dbde3558e16ab4 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_balances.rs @@ -17,25 +17,23 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=coretime-westend-dev -// --wasm-execution=compiled -// --pallet=pallet_balances -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=coretime-westend-dev // --header=./cumulus/file_header.txt // --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ @@ -56,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_773_000 picoseconds. - Weight::from_parts(43_292_000, 0) + // Minimum execution time: 44_250_000 picoseconds. + Weight::from_parts(45_303_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -68,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_023_000 picoseconds. - Weight::from_parts(34_513_000, 0) + // Minimum execution time: 34_451_000 picoseconds. + Weight::from_parts(35_413_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -80,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 11_685_000 picoseconds. - Weight::from_parts(12_103_000, 0) + // Minimum execution time: 11_886_000 picoseconds. + Weight::from_parts(12_158_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -92,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 16_233_000 picoseconds. - Weight::from_parts(16_706_000, 0) + // Minimum execution time: 16_457_000 picoseconds. + Weight::from_parts(16_940_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -104,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 43_909_000 picoseconds. - Weight::from_parts(44_683_000, 0) + // Minimum execution time: 45_416_000 picoseconds. + Weight::from_parts(46_173_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -116,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_081_000 picoseconds. - Weight::from_parts(42_553_000, 0) + // Minimum execution time: 43_502_000 picoseconds. + Weight::from_parts(44_060_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -128,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 14_413_000 picoseconds. - Weight::from_parts(14_827_000, 0) + // Minimum execution time: 14_790_000 picoseconds. + Weight::from_parts(15_451_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -141,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_189_000 picoseconds. - Weight::from_parts(14_587_000, 0) + // Minimum execution time: 14_582_000 picoseconds. + Weight::from_parts(14_797_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 10_909 - .saturating_add(Weight::from_parts(13_040_864, 0).saturating_mul(u.into())) + // Standard Error: 12_074 + .saturating_add(Weight::from_parts(13_220_968, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -156,9 +154,25 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_218_000 picoseconds. - Weight::from_parts(5_562_000, 0) + // Minimum execution time: 4_939_000 picoseconds. + Weight::from_parts(5_403_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 27_479_000 picoseconds. + Weight::from_parts(28_384_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_174_000 picoseconds. + Weight::from_parts(18_737_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs index 0082db3099d029c976779af8600bcaf4410e8a2f..fa588e982f0965218fa9cca7f93a20f9f70b37c5 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 18_410_000 picoseconds. - Weight::from_parts(18_657_000, 0) + // Minimum execution time: 18_707_000 picoseconds. + Weight::from_parts(19_391_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,21 +84,41 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 56_616_000 picoseconds. - Weight::from_parts(57_751_000, 0) + // Minimum execution time: 61_874_000 picoseconds. + Weight::from_parts(63_862_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve_transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `377` + // Estimated: `3842` + // Minimum execution time: 98_657_000 picoseconds. + Weight::from_parts(101_260_000, 0) + .saturating_add(Weight::from_parts(0, 3842)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -110,14 +130,12 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn execute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) + // Minimum execution time: 8_455_000 picoseconds. + Weight::from_parts(8_842_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -126,8 +144,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_014_000 picoseconds. - Weight::from_parts(6_412_000, 0) + // Minimum execution time: 5_850_000 picoseconds. + Weight::from_parts(6_044_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +155,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_844_000 picoseconds. - Weight::from_parts(1_957_000, 0) + // Minimum execution time: 1_754_000 picoseconds. + Weight::from_parts(1_832_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +180,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 24_067_000 picoseconds. - Weight::from_parts(24_553_000, 0) + // Minimum execution time: 24_886_000 picoseconds. + Weight::from_parts(25_403_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +204,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 27_023_000 picoseconds. - Weight::from_parts(27_620_000, 0) + // Minimum execution time: 28_114_000 picoseconds. + Weight::from_parts(28_414_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_866_000 picoseconds. - Weight::from_parts(1_984_000, 0) + // Minimum execution time: 1_713_000 picoseconds. + Weight::from_parts(1_810_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +227,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 16_425_000 picoseconds. - Weight::from_parts(16_680_000, 0) + // Minimum execution time: 15_910_000 picoseconds. + Weight::from_parts(16_256_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 16_171_000 picoseconds. - Weight::from_parts(16_564_000, 0) + // Minimum execution time: 15_801_000 picoseconds. + Weight::from_parts(16_298_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 17_785_000 picoseconds. - Weight::from_parts(18_123_000, 0) + // Minimum execution time: 17_976_000 picoseconds. + Weight::from_parts(18_390_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +272,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 23_903_000 picoseconds. - Weight::from_parts(24_769_000, 0) + // Minimum execution time: 24_723_000 picoseconds. + Weight::from_parts(25_531_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 10_617_000 picoseconds. - Weight::from_parts(10_843_000, 0) + // Minimum execution time: 10_954_000 picoseconds. + Weight::from_parts(11_199_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +295,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 16_656_000 picoseconds. - Weight::from_parts(17_106_000, 0) + // Minimum execution time: 16_561_000 picoseconds. + Weight::from_parts(16_908_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +317,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `13507` - // Minimum execution time: 31_721_000 picoseconds. - Weight::from_parts(32_547_000, 0) + // Minimum execution time: 33_279_000 picoseconds. + Weight::from_parts(33_869_000, 0) .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +331,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_439_000 picoseconds. - Weight::from_parts(3_619_000, 0) + // Minimum execution time: 3_405_000 picoseconds. + Weight::from_parts(3_489_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 24_657_000 picoseconds. - Weight::from_parts(24_971_000, 0) + // Minimum execution time: 24_387_000 picoseconds. + Weight::from_parts(25_143_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_028_000 picoseconds. - Weight::from_parts(34_697_000, 0) + // Minimum execution time: 35_229_000 picoseconds. + Weight::from_parts(36_035_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs index 6f5a52de98c39fb7ff5de96c41652be063f56a74..8e1461c4a99e2e95dea078280844a157ab4084de 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::fungible` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("coretime-westend-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --template=./cumulus/templates/xcm-bench-template.hbs -// --chain=coretime-westend-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm_benchmarks::fungible -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_benchmarks::fungible +// --chain=coretime-westend-dev // --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +// --template=./cumulus/templates/xcm-bench-template.hbs +// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -56,8 +54,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `101` // Estimated: `3593` - // Minimum execution time: 19_401_000 picoseconds. - Weight::from_parts(19_768_000, 3593) + // Minimum execution time: 26_842_000 picoseconds. + Weight::from_parts(27_606_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -67,8 +65,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `101` // Estimated: `6196` - // Minimum execution time: 42_452_000 picoseconds. - Weight::from_parts(43_126_000, 6196) + // Minimum execution time: 35_076_000 picoseconds. + Weight::from_parts(36_109_000, 6196) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -90,8 +88,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `207` // Estimated: `6196` - // Minimum execution time: 58_090_000 picoseconds. - Weight::from_parts(59_502_000, 6196) + // Minimum execution time: 56_951_000 picoseconds. + Weight::from_parts(58_286_000, 6196) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -120,8 +118,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 23_569_000 picoseconds. - Weight::from_parts(24_598_000, 3571) + // Minimum execution time: 23_796_000 picoseconds. + Weight::from_parts(24_692_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -129,8 +127,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_546_000 picoseconds. - Weight::from_parts(2_674_000, 0) + // Minimum execution time: 1_990_000 picoseconds. + Weight::from_parts(2_142_000, 0) } // Storage: `System::Account` (r:1 w:1) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) @@ -138,11 +136,13 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 16_889_000 picoseconds. - Weight::from_parts(17_350_000, 3593) + // Minimum execution time: 19_572_000 picoseconds. + Weight::from_parts(20_017_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + // Storage: `ParachainInfo::ParachainId` (r:1 w:0) + // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) @@ -151,8 +151,6 @@ impl WeightInfo { // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `System::Account` (r:1 w:1) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - // Storage: `ParachainInfo::ParachainId` (r:1 w:0) - // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) @@ -161,8 +159,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3593` - // Minimum execution time: 43_964_000 picoseconds. - Weight::from_parts(45_293_000, 3593) + // Minimum execution time: 49_336_000 picoseconds. + Weight::from_parts(50_507_000, 3593) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -182,8 +180,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 20_704_000 picoseconds. - Weight::from_parts(21_266_000, 3571) + // Minimum execution time: 21_230_000 picoseconds. + Weight::from_parts(21_870_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 74254814bcafc7f67dd20d8fa5dcd8da4337f782..9657fa55c1f2fdd4cf6ffdc4888e13e22a262155 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::generic` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("coretime-westend-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --template=./cumulus/templates/xcm-bench-template.hbs -// --chain=coretime-westend-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm_benchmarks::generic -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_benchmarks::generic +// --chain=coretime-westend-dev // --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +// --template=./cumulus/templates/xcm-bench-template.hbs +// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -66,8 +64,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 22_424_000 picoseconds. - Weight::from_parts(23_208_000, 3571) + // Minimum execution time: 23_688_000 picoseconds. + Weight::from_parts(24_845_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -75,8 +73,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_194_000 picoseconds. - Weight::from_parts(1_306_000, 0) + // Minimum execution time: 569_000 picoseconds. + Weight::from_parts(619_000, 0) } // Storage: `PolkadotXcm::Queries` (r:1 w:0) // Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -84,58 +82,58 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `3497` - // Minimum execution time: 6_359_000 picoseconds. - Weight::from_parts(6_585_000, 3497) + // Minimum execution time: 5_851_000 picoseconds. + Weight::from_parts(6_061_000, 3497) .saturating_add(T::DbWeight::get().reads(1)) } pub fn transact() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_297_000 picoseconds. - Weight::from_parts(6_661_000, 0) + // Minimum execution time: 5_770_000 picoseconds. + Weight::from_parts(5_916_000, 0) } pub fn refund_surplus() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_778_000 picoseconds. - Weight::from_parts(1_923_000, 0) + // Minimum execution time: 1_155_000 picoseconds. + Weight::from_parts(1_270_000, 0) } pub fn set_error_handler() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_212_000 picoseconds. - Weight::from_parts(1_314_000, 0) + // Minimum execution time: 558_000 picoseconds. + Weight::from_parts(628_000, 0) } pub fn set_appendix() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_165_000 picoseconds. - Weight::from_parts(1_247_000, 0) + // Minimum execution time: 603_000 picoseconds. + Weight::from_parts(630_000, 0) } pub fn clear_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_173_000 picoseconds. - Weight::from_parts(1_275_000, 0) + // Minimum execution time: 533_000 picoseconds. + Weight::from_parts(563_000, 0) } pub fn descend_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_247_000 picoseconds. - Weight::from_parts(1_332_000, 0) + // Minimum execution time: 597_000 picoseconds. + Weight::from_parts(644_000, 0) } pub fn clear_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_170_000 picoseconds. - Weight::from_parts(1_237_000, 0) + // Minimum execution time: 536_000 picoseconds. + Weight::from_parts(588_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -153,8 +151,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 19_872_000 picoseconds. - Weight::from_parts(20_453_000, 3571) + // Minimum execution time: 21_146_000 picoseconds. + Weight::from_parts(21_771_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -164,8 +162,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 9_105_000 picoseconds. - Weight::from_parts(9_365_000, 3555) + // Minimum execution time: 8_446_000 picoseconds. + Weight::from_parts(8_660_000, 3555) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -173,8 +171,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_228_000 picoseconds. - Weight::from_parts(1_293_000, 0) + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(594_000, 0) } // Storage: `PolkadotXcm::VersionNotifyTargets` (r:1 w:1) // Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -192,8 +190,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 19_535_000 picoseconds. - Weight::from_parts(20_139_000, 3539) + // Minimum execution time: 19_953_000 picoseconds. + Weight::from_parts(20_608_000, 3539) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -203,44 +201,44 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_158_000 picoseconds. - Weight::from_parts(3_275_000, 0) + // Minimum execution time: 2_290_000 picoseconds. + Weight::from_parts(2_370_000, 0) .saturating_add(T::DbWeight::get().writes(1)) } pub fn burn_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_539_000 picoseconds. - Weight::from_parts(1_607_000, 0) + // Minimum execution time: 943_000 picoseconds. + Weight::from_parts(987_000, 0) } pub fn expect_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_317_000 picoseconds. - Weight::from_parts(1_427_000, 0) + // Minimum execution time: 635_000 picoseconds. + Weight::from_parts(699_000, 0) } pub fn expect_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_176_000 picoseconds. - Weight::from_parts(1_250_000, 0) + // Minimum execution time: 553_000 picoseconds. + Weight::from_parts(609_000, 0) } pub fn expect_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_202_000 picoseconds. - Weight::from_parts(1_279_000, 0) + // Minimum execution time: 547_000 picoseconds. + Weight::from_parts(581_000, 0) } pub fn expect_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_411_000 picoseconds. - Weight::from_parts(1_463_000, 0) + // Minimum execution time: 700_000 picoseconds. + Weight::from_parts(757_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -258,8 +256,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 22_991_000 picoseconds. - Weight::from_parts(23_820_000, 3571) + // Minimum execution time: 24_953_000 picoseconds. + Weight::from_parts(25_516_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -267,8 +265,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_534_000 picoseconds. - Weight::from_parts(3_708_000, 0) + // Minimum execution time: 2_746_000 picoseconds. + Weight::from_parts(2_944_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -286,8 +284,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 20_025_000 picoseconds. - Weight::from_parts(20_463_000, 3571) + // Minimum execution time: 21_325_000 picoseconds. + Weight::from_parts(21_942_000, 3571) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -295,35 +293,35 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_213_000 picoseconds. - Weight::from_parts(1_290_000, 0) + // Minimum execution time: 600_000 picoseconds. + Weight::from_parts(631_000, 0) } pub fn set_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_207_000 picoseconds. - Weight::from_parts(1_265_000, 0) + // Minimum execution time: 534_000 picoseconds. + Weight::from_parts(566_000, 0) } pub fn clear_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_195_000 picoseconds. - Weight::from_parts(1_231_000, 0) + // Minimum execution time: 540_000 picoseconds. + Weight::from_parts(565_000, 0) } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_182_000 picoseconds. - Weight::from_parts(1_265_000, 0) + // Minimum execution time: 542_000 picoseconds. + Weight::from_parts(581_000, 0) } pub fn unpaid_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_165_000 picoseconds. - Weight::from_parts(1_252_000, 0) + // Minimum execution time: 568_000 picoseconds. + Weight::from_parts(597_000, 0) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs index defc57e2d7f552a86421359b25d64a2bacbd3572..b12765870bfdbbc7eb495a52e9ec4e931dc442da 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs @@ -232,6 +232,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml index 808bed38732758e546a6a513c4f19cf2b1d50fbc..92a5bbbd1376088909f315371dff6be13ffa69af 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml @@ -10,7 +10,7 @@ description = "Glutton parachain runtime." workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate @@ -47,7 +47,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-primitives-aura = { path = "../../../../primitives/aura", default-features = false } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 996f7655c0319a9dd40ce724beab5bf544893c08..4092fb78594d205d8ad9ddf7d8268c4fa4db27db 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -100,7 +100,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("glutton-westend"), impl_name: create_runtime_str!("glutton-westend"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -208,8 +208,9 @@ impl pallet_message_queue::Config for Runtime { >; type Size = u32; type QueueChangeHandler = (); - type QueuePausedQuery = (); // No XCMP queue pallet deployed. - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + // No XCMP queue pallet deployed. + type QueuePausedQuery = (); + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs index 9d438a41f8fe75037a4c9781653d5f65eee77f9c..d1fb50c1ab095cb07eb3f849c5e5d8be42fd1fc6 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs @@ -91,6 +91,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml index 7183be5fc82cc594c6ad2f3738dbfd5b67738a2c..a29d6db58fef2a97aedf6d2b95591ab39720260b 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } enumflags2 = { version = "0.7.7" } hex-literal = { version = "0.4.1" } log = { workspace = true } @@ -62,7 +62,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 4a57bad01c8c9c4a77caa4d701ada4e149317607..5cd8aa357c37ee26e0779b76b25f9d184a6d9742 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -128,10 +128,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-rococo"), impl_name: create_runtime_str!("people-rococo"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 0, + transaction_version: 1, state_version: 1, }; @@ -281,7 +281,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -308,13 +308,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_balances.rs index 126d816afcdb551e31adc38aaeb54ad3af5b228c..4990e8c12d5aa2f3f3be9ac6fb2181f5f6e80f7a 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_balances.rs @@ -1,40 +1,41 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-kusama-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-kusama-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_balances -// --extrinsic=* // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-kusama/src/weights/pallet_balances.rs +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=people-rococo-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,112 +48,131 @@ use core::marker::PhantomData; /// Weight functions for `pallet_balances`. pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_allow_death() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 63_775_000 picoseconds. - Weight::from_parts(64_181_000, 0) + // Minimum execution time: 42_847_000 picoseconds. + Weight::from_parts(44_471_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 47_986_000 picoseconds. - Weight::from_parts(48_308_000, 0) + // Minimum execution time: 33_076_000 picoseconds. + Weight::from_parts(35_052_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_set_balance_creating() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 18_083_000 picoseconds. - Weight::from_parts(18_380_000, 0) + // Minimum execution time: 13_422_000 picoseconds. + Weight::from_parts(13_682_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_set_balance_killing() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 26_341_000 picoseconds. - Weight::from_parts(26_703_000, 0) + // Minimum execution time: 18_360_000 picoseconds. + Weight::from_parts(18_721_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 66_227_000 picoseconds. - Weight::from_parts(67_321_000, 0) + // Minimum execution time: 44_647_000 picoseconds. + Weight::from_parts(46_142_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_all() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 59_472_000 picoseconds. - Weight::from_parts(60_842_000, 0) + // Minimum execution time: 41_807_000 picoseconds. + Weight::from_parts(44_490_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_unreserve() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 21_497_000 picoseconds. - Weight::from_parts(21_684_000, 0) + // Minimum execution time: 16_032_000 picoseconds. + Weight::from_parts(16_694_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `System::Account` (r:999 w:999) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `u` is `[1, 1000]`. + fn upgrade_accounts(u: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + u * (136 ±0)` + // Estimated: `990 + u * (2603 ±0)` + // Minimum execution time: 14_593_000 picoseconds. + Weight::from_parts(14_767_000, 0) + .saturating_add(Weight::from_parts(0, 990)) + // Standard Error: 11_218 + .saturating_add(Weight::from_parts(13_432_648, 0).saturating_mul(u.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) + .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) + } /// Storage: `Balances::InactiveIssuance` (r:1 w:0) /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn force_adjust_total_issuance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_132_000 picoseconds. - Weight::from_parts(5_467_000, 0) + // Minimum execution time: 5_044_000 picoseconds. + Weight::from_parts(5_368_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } - fn upgrade_accounts(u: u32, ) -> Weight { + fn burn_allow_death() -> Weight { // Proof Size summary in bytes: - // Measured: `0 + u * (136 ±0)` - // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 20_385_000 picoseconds. - Weight::from_parts(20_587_000, 0) - .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 10_001 - .saturating_add(Weight::from_parts(16_801_557, 0).saturating_mul(u.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 26_868_000 picoseconds. + Weight::from_parts(27_921_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 17_988_000 picoseconds. + Weight::from_parts(18_962_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs index 101d9a180e5feaa36d65afcd01276b86768f4ab0..cca964fb2441bbe8bd40d909eb90766907918df2 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs @@ -230,6 +230,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml index 576c3b1aa4e3eaafafafd0af353580fef7a3c20c..b72675900fdca0756f3dcf1c73014c9137360e47 100644 --- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } enumflags2 = { version = "0.7.7" } hex-literal = { version = "0.4.1" } log = { workspace = true } @@ -62,7 +62,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 22e8fd57d3ca735fa0e8490e94adf06bf2f91108..af6b5be44695c5fc5ba1a7e95ca53839fc57da2e 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -128,10 +128,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-westend"), impl_name: create_runtime_str!("people-westend"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 0, + transaction_version: 1, state_version: 1, }; @@ -281,7 +281,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -308,13 +308,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_balances.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_balances.rs index 1a3df158a0d0742d6d721c66f9e6545608e0c88f..2649c1557a2f848826175e4b0ec1c30207f4fbb9 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_balances.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_balances.rs @@ -1,40 +1,41 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-polkadot-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-polkadot-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_balances -// --extrinsic=* // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-polkadot/src/weights/pallet_balances.rs +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=people-westend-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,112 +48,131 @@ use core::marker::PhantomData; /// Weight functions for `pallet_balances`. pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_allow_death() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 59_580_000 picoseconds. - Weight::from_parts(60_317_000, 0) + // Minimum execution time: 42_705_000 picoseconds. + Weight::from_parts(43_367_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 45_490_000 picoseconds. - Weight::from_parts(45_910_000, 0) + // Minimum execution time: 33_334_000 picoseconds. + Weight::from_parts(34_183_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_set_balance_creating() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_353_000 picoseconds. - Weight::from_parts(17_676_000, 0) + // Minimum execution time: 13_036_000 picoseconds. + Weight::from_parts(13_392_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_set_balance_killing() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 25_017_000 picoseconds. - Weight::from_parts(25_542_000, 0) + // Minimum execution time: 17_734_000 picoseconds. + Weight::from_parts(18_504_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 61_161_000 picoseconds. - Weight::from_parts(61_665_000, 0) + // Minimum execution time: 44_343_000 picoseconds. + Weight::from_parts(44_783_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_all() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 55_422_000 picoseconds. - Weight::from_parts(55_880_000, 0) + // Minimum execution time: 41_562_000 picoseconds. + Weight::from_parts(42_397_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_unreserve() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 20_477_000 picoseconds. - Weight::from_parts(20_871_000, 0) + // Minimum execution time: 15_547_000 picoseconds. + Weight::from_parts(16_072_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `System::Account` (r:999 w:999) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `u` is `[1, 1000]`. + fn upgrade_accounts(u: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + u * (136 ±0)` + // Estimated: `990 + u * (2603 ±0)` + // Minimum execution time: 13_969_000 picoseconds. + Weight::from_parts(14_302_000, 0) + .saturating_add(Weight::from_parts(0, 990)) + // Standard Error: 12_004 + .saturating_add(Weight::from_parts(12_993_439, 0).saturating_mul(u.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) + .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) + } /// Storage: `Balances::InactiveIssuance` (r:1 w:0) /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn force_adjust_total_issuance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 5_132_000 picoseconds. - Weight::from_parts(5_467_000, 0) + // Minimum execution time: 4_854_000 picoseconds. + Weight::from_parts(5_148_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } - fn upgrade_accounts(u: u32, ) -> Weight { + fn burn_allow_death() -> Weight { // Proof Size summary in bytes: - // Measured: `0 + u * (136 ±0)` - // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 19_501_000 picoseconds. - Weight::from_parts(19_726_000, 0) - .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 9_495 - .saturating_add(Weight::from_parts(15_658_957, 0).saturating_mul(u.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 26_532_000 picoseconds. + Weight::from_parts(27_418_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_148_000 picoseconds. + Weight::from_parts(18_809_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs index 0a903f915056313c5650f030a3c0266eff1612e1..3926ddcf21efe09933e85552b3fc31f368d69e9b 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs @@ -238,6 +238,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/starters/seedling/Cargo.toml b/cumulus/parachains/runtimes/starters/seedling/Cargo.toml index eb702c9f2cdf30844fbf4ea17534566c038c4880..910944f54a5ff3433f11fab1d33aa0e88abc35b2 100644 --- a/cumulus/parachains/runtimes/starters/seedling/Cargo.toml +++ b/cumulus/parachains/runtimes/starters/seedling/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate @@ -36,7 +36,7 @@ sp-version = { path = "../../../../../substrate/primitives/version", default-fea # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-solo-to-para = { path = "../../../../pallets/solo-to-para", default-features = false } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-timestamp = { path = "../../../../primitives/timestamp", default-features = false } diff --git a/cumulus/parachains/runtimes/starters/shell/Cargo.toml b/cumulus/parachains/runtimes/starters/shell/Cargo.toml index f66d04fec1fdd72eb30f183bb713e88d4fee00e7..7a7fad537ac302a9e71889c949a04aacc79df3f3 100644 --- a/cumulus/parachains/runtimes/starters/shell/Cargo.toml +++ b/cumulus/parachains/runtimes/starters/shell/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate @@ -41,7 +41,7 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } parachain-info = { package = "staging-parachain-info", path = "../../../pallets/parachain-info", default-features = false } diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index a3d1629bbe5eb928f3f78998ed721968f140536d..7422b580cc3e08c1df8af5e9dce23d79d0c4e1a8 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -229,7 +229,7 @@ impl pallet_message_queue::Config for Runtime { // These need to be configured to the XCMP pallet - if it is deployed. type QueueChangeHandler = (); type QueuePausedQuery = (); - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs index 7f9de0f64b35676f4684b15590a243e4550885d2..741b3bcd752f5511b09add16865a5f311e3626cc 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs @@ -91,6 +91,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/test-utils/Cargo.toml b/cumulus/parachains/runtimes/test-utils/Cargo.toml index eda88beb7dabb41bd4075ec5ab6bf8ec2f42d3c8..c081bac4babe87413c40869917715d03c0c71a86 100644 --- a/cumulus/parachains/runtimes/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/test-utils/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } # Substrate frame-support = { path = "../../../../substrate/frame/support", default-features = false } @@ -26,7 +26,7 @@ sp-tracing = { path = "../../../../substrate/primitives/tracing" } sp-core = { path = "../../../../substrate/primitives/core", default-features = false } # Cumulus -cumulus-pallet-parachain-system = { path = "../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../pallets/xcmp-queue", default-features = false } pallet-collator-selection = { path = "../../../pallets/collator-selection", default-features = false } parachain-info = { package = "staging-parachain-info", path = "../../pallets/parachain-info", default-features = false } diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml index 028aa002a91e508c858c7ba71c981d9c9cf8dc60..3262233053e7e130c230adbc0aef857572756b1d 100644 --- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } hex-literal = { version = "0.4.1", optional = true } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -64,11 +64,12 @@ polkadot-runtime-common = { path = "../../../../../polkadot/runtime/common", def xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../../../../polkadot/xcm/xcm-fee-payment-runtime-api", default-features = false } # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } @@ -134,6 +135,7 @@ std = [ "substrate-wasm-builder", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] @@ -164,6 +166,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 89885d77378ba2c1df13116b5f2d41f547002b30..8afe56cddefab30e21cc5e4f58abfa6b973d7a0a 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -32,6 +32,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod weights; pub mod xcm_config; +use codec::Encode; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::{ @@ -44,7 +45,7 @@ use frame_support::{ AsEnsureOriginWithArg, ConstBool, ConstU32, ConstU64, ConstU8, Everything, TransformOrigin, }, weights::{ - constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, FeePolynomial, + constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, FeePolynomial, WeightToFee as _, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, PalletId, @@ -80,7 +81,14 @@ pub use sp_runtime::BuildStorage; use parachains_common::{AccountId, Signature}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; -use xcm::latest::prelude::{AssetId as AssetLocationId, BodyId}; +use xcm::{ + latest::prelude::{AssetId as AssetLocationId, BodyId}, + IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm, +}; +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; /// Balance of an account. pub type Balance = u128; @@ -533,7 +541,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -561,7 +569,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = (); @@ -835,6 +847,109 @@ impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { + let acceptable = vec![ + // native token + VersionedAssetId::from(AssetLocationId(xcm_config::RelayLocation::get())) + ]; + + Ok(acceptable + .into_iter() + .filter_map(|asset| asset.into_version(xcm_version).ok()) + .collect()) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == xcm_config::RelayLocation::get() => { + // for native token + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_xcm_weight(message) + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + PolkadotXcm::query_delivery_fees(destination, message) + } + } + + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm_executor::RecordXcm; + use xcm::prelude::*; + + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, program: VersionedXcm) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm::prelude::*; + + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let program: Xcm = program.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = program.using_encoded(sp_core::hashing::blake2_256); + let result = xcm_executor::XcmExecutor::::prepare_and_execute( + origin_location, + program, + &mut hash, + Weight::MAX, // Max limit. + Weight::zero(), + ); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 711041f6d6e28ccfc53d83ee2b903f06ae65de36..08a2da260c57e67b17eecf55f3845049e371b996 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -362,6 +362,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml index df3aaa92c79e78e5dfb9043db69778db051b3053..cf734345a976f027ae31f2f38735b9b7aac59f7d 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate @@ -50,7 +50,7 @@ polkadot-runtime-common = { path = "../../../../../polkadot/runtime/common", def # Cumulus cumulus-pallet-aura-ext = { path = "../../../../pallets/aura-ext", default-features = false } pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false } cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } cumulus-ping = { path = "../../../pallets/ping", default-features = false } diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 11da6adb81905a79718213b3663c3ffb25bfe8cb..fd4716ab972e8e8f6d3d1a3ca6aca74df7263fa7 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -107,7 +107,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("test-parachain"), impl_name: create_runtime_str!("test-parachain"), authoring_version: 1, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 6, @@ -317,7 +317,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = (); @@ -490,6 +490,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. @@ -541,7 +542,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = (); // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight; diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 55cea88adf16767e30a26c11f5970657e78c5e12..90c1442448182e1c4ba4b14de90a95a8e56dfce2 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -17,7 +17,7 @@ path = "src/main.rs" [dependencies] async-trait = "0.1.79" clap = { version = "4.5.3", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.28" hex-literal = "0.4.1" log = { workspace = true, default-features = true } @@ -117,7 +117,7 @@ substrate-build-script-utils = { path = "../../substrate/utils/build-script-util [dev-dependencies] assert_cmd = "2.0" -nix = { version = "0.26.1", features = ["signal"] } +nix = { version = "0.28.0", features = ["signal"] } tempfile = "3.8.0" wait-timeout = "0.2" tokio = { version = "1.32.0", features = ["macros", "parking_lot", "time"] } diff --git a/cumulus/polkadot-parachain/src/chain_spec/mod.rs b/cumulus/polkadot-parachain/src/chain_spec/mod.rs index bbda334e4c66e0d9f8fcb7434bc4f218d81dc6e5..19047b073b057a06f19e86faf935ecb4fc3c96b5 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/mod.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/mod.rs @@ -37,11 +37,12 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Generic extensions for Parachain ChainSpecs. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] -#[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. + #[serde(alias = "relayChain", alias = "RelayChain")] pub relay_chain: String, /// The id of the Parachain. + #[serde(alias = "paraId", alias = "ParaId")] pub para_id: u32, } @@ -53,7 +54,7 @@ impl Extensions { } /// Generic chain spec for all polkadot-parachain runtimes -pub type GenericChainSpec = sc_service::GenericChainSpec<(), Extensions>; +pub type GenericChainSpec = sc_service::GenericChainSpec; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { @@ -78,3 +79,22 @@ where pub fn get_collator_keys_from_seed(seed: &str) -> ::Public { get_from_seed::(seed) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_decode_extension_camel_and_snake_case() { + let camel_case = r#"{"relayChain":"relay","paraId":1}"#; + let snake_case = r#"{"relay_chain":"relay","para_id":1}"#; + let pascal_case = r#"{"RelayChain":"relay","ParaId":1}"#; + + let camel_case_extension: Extensions = serde_json::from_str(camel_case).unwrap(); + let snake_case_extension: Extensions = serde_json::from_str(snake_case).unwrap(); + let pascal_case_extension: Extensions = serde_json::from_str(pascal_case).unwrap(); + + assert_eq!(camel_case_extension, snake_case_extension); + assert_eq!(snake_case_extension, pascal_case_extension); + } +} diff --git a/cumulus/polkadot-parachain/src/chain_spec/people.rs b/cumulus/polkadot-parachain/src/chain_spec/people.rs index 1408ef0aff67adf4942b8dcd8d4198c8cd60910b..db8756e68819b3f7abaeeea9e8b684f75beda5dc 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/people.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/people.rs @@ -60,8 +60,9 @@ impl PeopleRuntimeType { pub fn load_config(&self) -> Result, String> { match self { - PeopleRuntimeType::Kusama => - todo!("Update chain-spec: ../../chain-specs/people-kusama.json - https://github.com/paritytech/polkadot-sdk/pull/3961#issuecomment-2037438431"), + PeopleRuntimeType::Kusama => Ok(Box::new(GenericChainSpec::from_json_bytes( + &include_bytes!("../../chain-specs/people-kusama.json")[..], + )?)), PeopleRuntimeType::Polkadot => todo!("Generate chain-spec: ../../chain-specs/people-polkadot.json"), PeopleRuntimeType::Rococo => Ok(Box::new(GenericChainSpec::from_json_bytes( diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 041187de488f33c2c0fe65e4464d165a46c0333e..653ea3281f0f769df9a3c88629e139244b187863 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -1017,7 +1017,7 @@ mod tests { cfg_file_path } - pub type DummyChainSpec = sc_service::GenericChainSpec<(), E>; + pub type DummyChainSpec = sc_service::GenericChainSpec; pub fn create_default_with_extensions( id: &str, diff --git a/cumulus/primitives/aura/Cargo.toml b/cumulus/primitives/aura/Cargo.toml index 21c06ef22d9a13bf8361156ea5e1af1216aa3e28..ef96f334d63753c73de669ddcd98b6868a88389b 100644 --- a/cumulus/primitives/aura/Cargo.toml +++ b/cumulus/primitives/aura/Cargo.toml @@ -10,7 +10,7 @@ description = "Core primitives for Aura in Cumulus" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } # Substrate sp-api = { path = "../../../substrate/primitives/api", default-features = false } diff --git a/cumulus/primitives/core/Cargo.toml b/cumulus/primitives/core/Cargo.toml index 62c3f6751917ad4aaaaec6509c852a5cfd75d7f8..595aa5f72bf2453edea23e372865de95e9e46699 100644 --- a/cumulus/primitives/core/Cargo.toml +++ b/cumulus/primitives/core/Cargo.toml @@ -10,7 +10,7 @@ description = "Cumulus related core primitive types and traits" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate diff --git a/cumulus/primitives/core/src/lib.rs b/cumulus/primitives/core/src/lib.rs index 7f7353685657e7bf6bfb2c05faba32315bbbb706..29216d513465160eb94db76faedb6e7fd992b461 100644 --- a/cumulus/primitives/core/src/lib.rs +++ b/cumulus/primitives/core/src/lib.rs @@ -64,6 +64,8 @@ pub enum MessageSendError { TooBig, /// Some other error. Other, + /// There are too many channels open at once. + TooManyChannels, } impl From for &'static str { @@ -74,6 +76,7 @@ impl From for &'static str { NoChannel => "NoChannel", TooBig => "TooBig", Other => "Other", + TooManyChannels => "TooManyChannels", } } } @@ -135,6 +138,11 @@ pub trait GetChannelInfo { fn get_channel_info(id: ParaId) -> Option; } +/// List all open outgoing channels. +pub trait ListChannelInfos { + fn outgoing_channels() -> Vec; +} + /// Something that should be called when sending an upward message. pub trait UpwardMessageSender { /// Send the given UMP message; return the expected number of blocks before the message will diff --git a/cumulus/primitives/parachain-inherent/Cargo.toml b/cumulus/primitives/parachain-inherent/Cargo.toml index 4da561661b6b312d8d89a9f0f5ae5b7359e79a82..0156eb02e2b4aaa9ee02e4e237f305c20792569d 100644 --- a/cumulus/primitives/parachain-inherent/Cargo.toml +++ b/cumulus/primitives/parachain-inherent/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate diff --git a/cumulus/primitives/storage-weight-reclaim/Cargo.toml b/cumulus/primitives/storage-weight-reclaim/Cargo.toml index 6dbf7904bf796e81415b967637d9770356142603..bdfb83ad72a96930c1dae2d2c054a2c19c5cfcb2 100644 --- a/cumulus/primitives/storage-weight-reclaim/Cargo.toml +++ b/cumulus/primitives/storage-weight-reclaim/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/cumulus/primitives/timestamp/Cargo.toml b/cumulus/primitives/timestamp/Cargo.toml index 59f327b2642a292db56708f5770ebb35b1b82d1d..7a6f4787ba3121cf0c9c7eec3b9f3794c870037d 100644 --- a/cumulus/primitives/timestamp/Cargo.toml +++ b/cumulus/primitives/timestamp/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } futures = "0.3.28" # Substrate diff --git a/cumulus/primitives/utility/Cargo.toml b/cumulus/primitives/utility/Cargo.toml index 1e2c300b9ba257d2c8fb998689ae45847099dd63..85e3ac2f7606c9e12aa4d38f0c44c3fe1818b107 100644 --- a/cumulus/primitives/utility/Cargo.toml +++ b/cumulus/primitives/utility/Cargo.toml @@ -10,7 +10,7 @@ description = "Helper datatypes for Cumulus" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } # Substrate diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs index 54f40bd01097c99ab82520c7fe83d13c96c698b2..64784eb36f846f7b325aaaa5ed72966e3d59a1b8 100644 --- a/cumulus/primitives/utility/src/lib.rs +++ b/cumulus/primitives/utility/src/lib.rs @@ -34,8 +34,8 @@ use sp_runtime::{ SaturatedConversion, }; use sp_std::{marker::PhantomData, prelude::*}; -use xcm::{latest::prelude::*, WrapVersion}; -use xcm_builder::TakeRevenue; +use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm, WrapVersion}; +use xcm_builder::{InspectMessageQueues, TakeRevenue}; use xcm_executor::{ traits::{MatchesFungibles, TransactAsset, WeightTrader}, AssetsInHolding, @@ -93,6 +93,14 @@ where } } +impl InspectMessageQueues + for ParentAsUmp +{ + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + T::get_messages() + } +} + /// Contains information to handle refund/payment for xcm-execution #[derive(Clone, Eq, PartialEq, Debug)] struct AssetTraderRefunder { diff --git a/cumulus/test/client/Cargo.toml b/cumulus/test/client/Cargo.toml index 254361e85420de982a984f76d76b96a5c7d3b4a4..120983eb9390e9007c13b08c763f13446011f98e 100644 --- a/cumulus/test/client/Cargo.toml +++ b/cumulus/test/client/Cargo.toml @@ -9,7 +9,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } # Substrate sc-service = { path = "../../../substrate/client/service" } diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs index 6ccea43fb7cb6c1040d6972c5126e05f71d9bf3f..f26413e441e72b7fca558043f0507de91db4746f 100644 --- a/cumulus/test/client/src/lib.rs +++ b/cumulus/test/client/src/lib.rs @@ -45,33 +45,18 @@ pub use substrate_test_client::*; pub type ParachainBlockData = cumulus_primitives_core::ParachainBlockData; -mod local_executor { - /// Native executor instance. - pub struct LocalExecutor; - - impl sc_executor::NativeExecutionDispatch for LocalExecutor { - type ExtendHostFunctions = - cumulus_primitives_proof_size_hostfunction::storage_proof_size::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - cumulus_test_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - cumulus_test_runtime::native_version() - } - } -} - -/// Native executor used for tests. -pub use local_executor::LocalExecutor; - /// Test client database backend. pub type Backend = substrate_test_client::Backend; /// Test client executor. -pub type Executor = - client::LocalCallExecutor>; +pub type Executor = client::LocalCallExecutor< + Block, + Backend, + WasmExecutor<( + sp_io::SubstrateHostFunctions, + cumulus_primitives_proof_size_hostfunction::storage_proof_size::HostFunctions, + )>, +>; /// Test client builder for Cumulus pub type TestClientBuilder = @@ -101,7 +86,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters { } } -/// A `test-runtime` extensions to `TestClientBuilder`. +/// A `test-runtime` extensions to [`TestClientBuilder`]. pub trait TestClientBuilderExt: Sized { /// Build the test client. fn build(self) -> Client { diff --git a/cumulus/test/relay-sproof-builder/Cargo.toml b/cumulus/test/relay-sproof-builder/Cargo.toml index ff5c4bd66b9742383bcd170f0012695d7f0c72d2..d775c61f7801e98b4c8e8436eb95c1ec86854d77 100644 --- a/cumulus/test/relay-sproof-builder/Cargo.toml +++ b/cumulus/test/relay-sproof-builder/Cargo.toml @@ -10,7 +10,7 @@ description = "Mocked relay state proof builder for testing Cumulus." workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } # Substrate sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } diff --git a/cumulus/test/runtime/Cargo.toml b/cumulus/test/runtime/Cargo.toml index aebc1033db8d8290a358e7800662c73dcd1c37a4..32257db3460f8a0720c6f5338d1bcbe8d4a04126 100644 --- a/cumulus/test/runtime/Cargo.toml +++ b/cumulus/test/runtime/Cargo.toml @@ -9,7 +9,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate @@ -41,9 +41,7 @@ sp-transaction-pool = { path = "../../../substrate/primitives/transaction-pool", sp-version = { path = "../../../substrate/primitives/version", default-features = false } # Cumulus -cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false, features = [ - "parameterized-consensus-hook", -] } +cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false } cumulus-primitives-aura = { path = "../../primitives/aura", default-features = false } pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false } cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false } diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index 3444fd6192d23ada728c9498a60acbec0537fe53..32cc45c7936481081fd9718d2fc979d88040fa73 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -15,7 +15,7 @@ path = "src/main.rs" [dependencies] async-trait = "0.1.79" clap = { version = "4.5.3", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.6.12" } criterion = { version = "0.5.1", features = ["async_tokio"] } jsonrpsee = { version = "0.22", features = ["server"] } rand = "0.8.5" @@ -85,7 +85,7 @@ cumulus-test-runtime = { path = "../runtime" } cumulus-relay-chain-minimal-node = { path = "../../client/relay-chain-minimal-node" } cumulus-client-pov-recovery = { path = "../../client/pov-recovery" } cumulus-test-relay-sproof-builder = { path = "../relay-sproof-builder" } -cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false } cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim" } pallet-timestamp = { path = "../../../substrate/frame/timestamp" } diff --git a/cumulus/test/service/src/chain_spec.rs b/cumulus/test/service/src/chain_spec.rs index 7b44bdf2fee09bf7f758c033fb9314499ff6e329..842251d428a2ffff3c7ef3d08deccb1d47e2db7b 100644 --- a/cumulus/test/service/src/chain_spec.rs +++ b/cumulus/test/service/src/chain_spec.rs @@ -17,7 +17,7 @@ #![allow(missing_docs)] use cumulus_primitives_core::ParaId; -use cumulus_test_runtime::{AccountId, RuntimeGenesisConfig, Signature}; +use cumulus_test_runtime::{AccountId, Signature}; use parachains_common::AuraId; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; @@ -26,7 +26,7 @@ use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index a9dea1d94df8f466305e5e20077ea5d1fe0572e3..ded61ae90fd95a4eebd0e004167851b42b263236 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -155,7 +155,7 @@ impl RecoveryHandle for FailingRecoveryHandle { message: AvailabilityRecoveryMessage, origin: &'static str, ) { - let AvailabilityRecoveryMessage::RecoverAvailableData(ref receipt, _, _, _) = message; + let AvailabilityRecoveryMessage::RecoverAvailableData(ref receipt, _, _, _, _) = message; let candidate_hash = receipt.hash(); // For every 3rd block we immediately signal unavailability to trigger @@ -163,7 +163,8 @@ impl RecoveryHandle for FailingRecoveryHandle { if self.counter % 3 == 0 && self.failed_hashes.insert(candidate_hash) { tracing::info!(target: LOG_TARGET, ?candidate_hash, "Failing pov recovery."); - let AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, back_sender) = message; + let AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, back_sender) = + message; back_sender .send(Err(RecoveryError::Unavailable)) .expect("Return channel should work here."); @@ -873,6 +874,8 @@ pub fn node_config( rpc_message_buffer_capacity: Default::default(), rpc_batch_config: RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/cumulus/xcm/xcm-emulator/Cargo.toml b/cumulus/xcm/xcm-emulator/Cargo.toml index 6b45770a8e3df47cb083dba5a8a0eeed1759e338..0ed77bf5b7073bc9e3041388206203ce7c1829a2 100644 --- a/cumulus/xcm/xcm-emulator/Cargo.toml +++ b/cumulus/xcm/xcm-emulator/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.6.12" } paste = "1.0.14" log = { workspace = true } lazy_static = "1.4.0" diff --git a/cumulus/xcm/xcm-emulator/src/lib.rs b/cumulus/xcm/xcm-emulator/src/lib.rs index babb318a99500932dd8a2e42a2b443944751d286..a50f33951d056d56ab281934cc7987018d91f7c6 100644 --- a/cumulus/xcm/xcm-emulator/src/lib.rs +++ b/cumulus/xcm/xcm-emulator/src/lib.rs @@ -34,7 +34,9 @@ pub use frame_support::{ }, weights::{Weight, WeightMeter}, }; -pub use frame_system::{Config as SystemConfig, Pallet as SystemPallet}; +pub use frame_system::{ + pallet_prelude::BlockNumberFor, Config as SystemConfig, Pallet as SystemPallet, +}; pub use pallet_balances::AccountData; pub use pallet_message_queue; pub use sp_arithmetic::traits::Bounded; @@ -54,7 +56,7 @@ pub use cumulus_primitives_core::{ pub use cumulus_primitives_parachain_inherent::ParachainInherentData; pub use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; pub use pallet_message_queue::{Config as MessageQueueConfig, Pallet as MessageQueuePallet}; -pub use parachains_common::{AccountId, Balance, BlockNumber}; +pub use parachains_common::{AccountId, Balance}; pub use polkadot_primitives; pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId}; @@ -657,7 +659,7 @@ macro_rules! decl_test_parachains { .clone() ); ::System::initialize(&block_number, &parent_head_data.hash(), &Default::default()); - <::ParachainSystem as Hooks<$crate::BlockNumber>>::on_initialize(block_number); + <::ParachainSystem as Hooks<$crate::BlockNumberFor>>::on_initialize(block_number); let _ = ::ParachainSystem::set_validation_data( ::RuntimeOrigin::none(), diff --git a/docs/RELEASE.md b/docs/RELEASE.md index e73be2779a99426203e209da846f938c0f73cceb..653e6a2a3e929e052cdd839884ed30c5b5327201 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -45,7 +45,7 @@ variable. ## Westend & Rococo -For the these networks, in addition to incrementing the `Cargo.toml` version we also increment the `spec_version` and +For these networks, in addition to incrementing the `Cargo.toml` version we also increment the `spec_version` and sometimes the `transaction_version`. The spec version is also following the node version. Its schema is: `M_mmm_ppp` and for example `1_002_000` is the node release `1.2.0`. This versioning has no further meaning, and is only done to map from an on chain `spec_version` easily to the release in this repository. diff --git a/docs/images/Polkadot_Logo_Horizontal_Pink_Black.png b/docs/images/Polkadot_Logo_Horizontal_Pink_Black.png new file mode 100644 index 0000000000000000000000000000000000000000..8909dc96a62a93f2bd8b9204e3f1a6885dffae52 Binary files /dev/null and b/docs/images/Polkadot_Logo_Horizontal_Pink_Black.png differ diff --git a/docs/images/Polkadot_Logo_Horizontal_Pink_White.png b/docs/images/Polkadot_Logo_Horizontal_Pink_White.png new file mode 100644 index 0000000000000000000000000000000000000000..ea814ea28d5c813613c087f0a2fe0e3e1f8f4b52 Binary files /dev/null and b/docs/images/Polkadot_Logo_Horizontal_Pink_White.png differ diff --git a/docs/mermaid/IA.mmd b/docs/mermaid/IA.mmd index 4eb50bcf96a8932de3fa90748fcfeb3ca7f02a5f..fe9a96bcafc0053c18332ca5901a93142811977f 100644 --- a/docs/mermaid/IA.mmd +++ b/docs/mermaid/IA.mmd @@ -1,5 +1,6 @@ flowchart parity[paritytech.github.io] --> devhub[polkadot_sdk_docs] + polkadot[polkadot.network] --> devhub[polkadot_sdk_docs] devhub --> polkadot_sdk devhub --> reference_docs @@ -10,5 +11,3 @@ flowchart polkadot_sdk --> cumulus polkadot_sdk --> polkadot polkadot_sdk --> xcm - - diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 426c5d9de4a022093c5e3c792722021601817c69..a8c873be556c2fd06ff6a3d3c096b3a8301f16d8 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -15,7 +15,7 @@ workspace = true [dependencies] # Needed for all FRAME-based code -parity-scale-codec = { version = "3.0.0", default-features = false } +parity-scale-codec = { version = "3.6.12", default-features = false } scale-info = { version = "2.6.0", default-features = false } frame = { package = "polkadot-sdk-frame", path = "../../substrate/frame", features = [ "experimental", @@ -30,6 +30,7 @@ simple-mermaid = "0.1.1" docify = "0.2.8" # Polkadot SDK deps, typically all should only be in scope such that we can link to their doc item. +polkadot-sdk = { path = "../../umbrella", features = ["runtime"] } node-cli = { package = "staging-node-cli", path = "../../substrate/bin/node/cli" } kitchensink-runtime = { path = "../../substrate/bin/node/runtime" } chain-spec-builder = { package = "staging-chain-spec-builder", path = "../../substrate/bin/utils/chain-spec-builder" } @@ -38,6 +39,7 @@ frame-system = { path = "../../substrate/frame/system", default-features = false frame-support = { path = "../../substrate/frame/support", default-features = false } frame-executive = { path = "../../substrate/frame/executive", default-features = false } pallet-example-single-block-migrations = { path = "../../substrate/frame/examples/single-block-migrations" } +frame-metadata-hash-extension = { path = "../../substrate/frame/metadata-hash-extension" } # Substrate Client sc-network = { path = "../../substrate/client/network" } @@ -51,18 +53,21 @@ sc-consensus-grandpa = { path = "../../substrate/client/consensus/grandpa" } sc-consensus-beefy = { path = "../../substrate/client/consensus/beefy" } sc-consensus-manual-seal = { path = "../../substrate/client/consensus/manual-seal" } sc-consensus-pow = { path = "../../substrate/client/consensus/pow" } +sc-executor = { path = "../../substrate/client/executor" } +sc-service = { path = "../../substrate/client/service" } substrate-wasm-builder = { path = "../../substrate/utils/wasm-builder" } # Cumulus cumulus-pallet-aura-ext = { path = "../../cumulus/pallets/aura-ext" } -cumulus-pallet-parachain-system = { path = "../../cumulus/pallets/parachain-system", features = [ - "parameterized-consensus-hook", -] } +cumulus-pallet-parachain-system = { path = "../../cumulus/pallets/parachain-system" } parachain-info = { package = "staging-parachain-info", path = "../../cumulus/parachains/pallets/parachain-info" } -pallet-aura = { path = "../../substrate/frame/aura", default-features = false } +cumulus-primitives-proof-size-hostfunction = { path = "../../cumulus/primitives/proof-size-hostfunction" } +cumulus-client-service = { path = "../../cumulus/client/service" } +cumulus-primitives-storage-weight-reclaim = { path = "../../cumulus/primitives/storage-weight-reclaim" } # Pallets and FRAME internals +pallet-aura = { path = "../../substrate/frame/aura" } pallet-timestamp = { path = "../../substrate/frame/timestamp" } pallet-balances = { path = "../../substrate/frame/balances" } pallet-assets = { path = "../../substrate/frame/assets" } @@ -96,3 +101,4 @@ sp-version = { path = "../../substrate/primitives/version" } # XCM xcm = { package = "staging-xcm", path = "../../polkadot/xcm" } +xcm-docs = { path = "../../polkadot/xcm/docs" } diff --git a/docs/sdk/src/guides/enable_metadata_hash.rs b/docs/sdk/src/guides/enable_metadata_hash.rs new file mode 100644 index 0000000000000000000000000000000000000000..b9cbae8533538d685f39d1cde979758dcc59955b --- /dev/null +++ b/docs/sdk/src/guides/enable_metadata_hash.rs @@ -0,0 +1,88 @@ +//! # Enable metadata hash verification +//! +//! This guide will teach you how to enable the metadata hash verification in your runtime. +//! +//! ## What is metadata hash verification? +//! +//! Each FRAME based runtime exposes metadata about itself. This metadata is used by consumers of +//! the runtime to interpret the state, to construct transactions etc. Part of this metadata are the +//! type information. These type information can be used to e.g. decode storage entries or to decode +//! a transaction. So, the metadata is quite useful for wallets to interact with a FRAME based +//! chain. Online wallets can fetch the metadata directly from any node of the chain they are +//! connected to, but offline wallets can not do this. So, for the offline wallet to have access to +//! the metadata it needs to be transferred and stored on the device. The problem is that the +//! metadata has a size of several hundreds of kilobytes, which takes quite a while to transfer to +//! these offline wallets and the internal storage of these devices is also not big enough to store +//! the metadata for one or more networks. The next problem is that the offline wallet/user can not +//! trust the metadata to be correct. It is very important for the metadata to be correct or +//! otherwise an attacker could change them in a way that the offline wallet decodes a transaction +//! in a different way than what it will be decoded to on chain. So, the user may signs an incorrect +//! transaction leading to unexpecting behavior. +//! +//! The metadata hash verification circumvents the issues of the huge metadata and the need to trust +//! some metadata blob to be correct. To generate a hash for the metadata, the metadata is chunked, +//! these chunks are put into a merkle tree and then the root of this merkle tree is the "metadata +//! hash". For a more technical explanation on how it works, see +//! [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html). At compile +//! time the metadata hash is generated and "backed" into the runtime. This makes it extremely cheap +//! for the runtime to verify on chain that the metadata hash is correct. By having the runtime +//! verify the hash on chain, the user also doesn't need to trust the offchain metadata. If the +//! metadata hash doesn't match the on chain metadata hash the transaction will be rejected. The +//! metadata hash itself is added to the data of the transaction that is signed, this means the +//! actual hash does not appear in the transaction. On chain the same procedure is repeated with the +//! metadata hash that is known by the runtime and if the metadata hash doesn't match the signature +//! verification will fail. As the metadata hash is actually the root of a merkle tree, the offline +//! wallet can get proofs of individual types to decode a transaction. This means that the offline +//! wallet does not require the entire metadata to be present on the device. +//! +//! ## Integrating metadata hash verification into your runtime +//! +//! The integration of the metadata hash verification is split into two parts, first the actual +//! integration into the runtime and secondly the enabling of the metadata hash generation at +//! compile time. +//! +//! ### Runtime integration +//! +//! From the runtime side only the +//! [`CheckMetadataHash`](frame_metadata_hash_extension::CheckMetadataHash) needs to be added to the +//! list of signed extension: +#![doc = docify::embed!("../../templates/parachain/runtime/src/lib.rs", template_signed_extra)] +//! +//! > **Note:** +//! > +//! > Adding the signed extension changes the encoding of the transaction and adds one extra byte +//! > per transaction! +//! +//! This signed extension will make sure to decode the requested `mode` and will add the metadata +//! hash to the signed data depending on the requested `mode`. The `mode` gives the user/wallet +//! control over deciding if the metadata hash should be verified or not. The metadata hash itself +//! is drawn from the `RUNTIME_METADATA_HASH` environment variable. If the environment variable is +//! not set, any transaction that requires the metadata hash is rejected with the error +//! `CannotLookup`. This is a security measurement to prevent including invalid transactions. +//! +//!

+//! +//! The extension does not work with the native runtime, because the +//! `RUNTIME_METADATA_HASH` environment variable is not set when building the +//! `frame-metadata-hash-extension` crate. +//! +//!
+//! +//! ### Enable metadata hash generation +//! +//! The metadata hash generation needs to be enabled when building the wasm binary. The +//! `substrate-wasm-builder` supports this out of the box: +#![doc = docify::embed!("../../templates/parachain/runtime/build.rs", template_enable_metadata_hash)] +//! +//! > **Note:** +//! > +//! > The `metadata-hash` feature needs to be enabled for the `substrate-wasm-builder` to enable the +//! > code for being able to generate the metadata hash. It is also recommended to put the metadata +//! > hash generation behind a feature in the runtime as shown above. The reason behind is that it +//! > adds a lot of code which increases the compile time and the generation itself also increases +//! > the compile time. Thus, it is recommended to enable the feature only when the metadata hash is +//! > required (e.g. for an on-chain build). +//! +//! The two parameters to `enable_metadata_hash` are the token symbol and the number of decimals of +//! the primary token of the chain. These information are included for the wallets to show token +//! related operations in a more user friendly way. diff --git a/docs/sdk/src/guides/enable_pov_reclaim.rs b/docs/sdk/src/guides/enable_pov_reclaim.rs new file mode 100644 index 0000000000000000000000000000000000000000..3c0c5fba2158691b51abdcceed5db5130e58c9b4 --- /dev/null +++ b/docs/sdk/src/guides/enable_pov_reclaim.rs @@ -0,0 +1,84 @@ +//! This guide will teach you how to enable storage weight reclaiming for a parachain. The +//! explanations in this guide assume a project structure similar to the one detailed in +//! the [substrate documentation](crate::polkadot_sdk::substrate#anatomy-of-a-binary-crate). Full +//! technical details are available in the original [pull request](https://github.com/paritytech/polkadot-sdk/pull/3002). +//! +//! # What is PoV reclaim? +//! When a parachain submits a block to a relay chain like Polkadot or Kusama, it sends the block +//! itself and a storage proof. Together they form the Proof-of-Validity (PoV). The PoV allows the +//! relay chain to validate the parachain block by re-executing it. Relay chain +//! validators distribute this PoV among themselves over the network. This distribution is costly +//! and limits the size of the storage proof. The storage weight dimension of FRAME weights reflects +//! this cost and limits the size of the storage proof. However, the storage weight determined +//! during [benchmarking](crate::reference_docs::frame_benchmarking_weight) represents the worst +//! case. In reality, runtime operations often consume less space in the storage proof. PoV reclaim +//! offers a mechanism to reclaim the difference between the benchmarked worst-case and the real +//! proof-size consumption. +//! +//! +//! # How to enable PoV reclaim +//! ## 1. Add the host function to your node +//! +//! To reclaim excess storage weight, a parachain runtime needs the +//! ability to fetch the size of the storage proof from the node. The reclaim +//! mechanism uses the +//! [`storage_proof_size`](cumulus_primitives_proof_size_hostfunction::storage_proof_size) +//! host function for this purpose. For convenience, cumulus provides +//! [`ParachainHostFunctions`](cumulus_client_service::ParachainHostFunctions), a set of +//! host functions typically used by cumulus-based parachains. In the binary crate of your +//! parachain, find the instantiation of the [`WasmExecutor`](sc_executor::WasmExecutor) and set the +//! correct generic type. +//! +//! This example from the parachain-template shows a type definition that includes the correct +//! host functions. +#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", wasm_executor)] +//! +//! > **Note:** +//! > +//! > If you see error `runtime requires function imports which are not present on the host: +//! > 'env:ext_storage_proof_size_storage_proof_size_version_1'`, it is likely +//! > that this step in the guide was not set up correctly. +//! +//! ## 2. Enable storage proof recording during import +//! +//! The reclaim mechanism reads the size of the currently recorded storage proof multiple times +//! during block authoring and block import. Proof recording during authoring is already enabled on +//! parachains. You must also ensure that storage proof recording is enabled during block import. +//! Find where your node builds the fundamental substrate components by calling +//! [`new_full_parts`](sc_service::new_full_parts). Replace this +//! with [`new_full_parts_record_import`](sc_service::new_full_parts_record_import) and +//! pass `true` as the last parameter to enable import recording. +#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", component_instantiation)] +//! +//! > **Note:** +//! > +//! > If you see error `Storage root must match that calculated.` during block import, it is likely +//! > that this step in the guide was not +//! > set up correctly. +//! +//! ## 3. Add the SignedExtension to your runtime +//! +//! In your runtime, you will find a list of SignedExtensions. +//! To enable the reclaiming, +//! add [`StorageWeightReclaim`](cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim) +//! to that list. For maximum efficiency, make sure that `StorageWeightReclaim` is last in the list. +//! The extension will check the size of the storage proof before and after an extrinsic execution. +//! It reclaims the difference between the calculated size and the benchmarked size. +#![doc = docify::embed!("../../templates/parachain/runtime/src/lib.rs", template_signed_extra)] +//! +//! ## Optional: Verify that reclaim works +//! +//! Start your node with the log target `runtime::storage_reclaim` set to `trace` to enable full +//! logging for `StorageWeightReclaim`. The following log is an example from a local testnet. To +//! trigger the log, execute any extrinsic on the network. +//! +//! ```ignore +//! ... +//! 2024-04-22 17:31:48.014 TRACE runtime::storage_reclaim: [ferdie] Reclaiming storage weight. benchmarked: 3593, consumed: 265 unspent: 0 +//! ... +//! ``` +//! +//! In the above example we see a benchmarked size of 3593 bytes, while the extrinsic only consumed +//! 265 bytes of proof size. This results in 3328 bytes of reclaim. +#![deny(rustdoc::broken_intra_doc_links)] +#![deny(rustdoc::private_intra_doc_links)] diff --git a/docs/sdk/src/guides/mod.rs b/docs/sdk/src/guides/mod.rs index 3120f25331099263087d3804d324e71555c0813d..f5f6d2b5e0c0768f1cff2f759769598c4703c601 100644 --- a/docs/sdk/src/guides/mod.rs +++ b/docs/sdk/src/guides/mod.rs @@ -23,3 +23,9 @@ pub mod cumulus_enabled_parachain; /// How to make a given runtime XCM-enabled, capable of sending messages (`Transact`) between itself /// and the relay chain to which it is connected. pub mod xcm_enabled_parachain; + +/// How to enable storage weight reclaiming in a parachain node and runtime. +pub mod enable_pov_reclaim; + +/// How to enable metadata hash verification in the runtime. +pub mod enable_metadata_hash; diff --git a/docs/sdk/src/meta_contributing.rs b/docs/sdk/src/meta_contributing.rs index fcdcea9934bb6b8cf7ee6ec090ebd0939888238c..a029595254c84dfa58639279b4fcd486f25c3f0e 100644 --- a/docs/sdk/src/meta_contributing.rs +++ b/docs/sdk/src/meta_contributing.rs @@ -139,7 +139,7 @@ //! //! ```sh //! SKIP_WASM_BUILD=1 \ -//! RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/headers/header.html --extend-css $(pwd)/docs/sdk/headers/theme.css --default-theme=ayu" \ +//! RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/assets/header.html --extend-css $(pwd)/docs/sdk/assets/theme.css --default-theme=ayu" \ //! cargo doc -p polkadot-sdk-docs --no-deps --open //! ``` //! diff --git a/docs/sdk/src/polkadot_sdk/polkadot.rs b/docs/sdk/src/polkadot_sdk/polkadot.rs index 61a6877696cb9298ed831562923d96d4a701bcc4..e2dcca4dc7dfcd2726d24b9f7725a67bad50246b 100644 --- a/docs/sdk/src/polkadot_sdk/polkadot.rs +++ b/docs/sdk/src/polkadot_sdk/polkadot.rs @@ -6,14 +6,16 @@ //! //! - [Polkadot Forum](https://forum.polkadot.network/) //! - [Polkadot Parachains](https://parachains.info/) -//! - [Polkadot (multi-chain) Explorer](https://subscan.io/) +//! - [Polkadot (multi-chain) Explorer: Subscan](https://subscan.io/) //! - Polkadot Fellowship //! - [Manifesto](https://github.com/polkadot-fellows/manifesto) //! - [Runtimes](https://github.com/polkadot-fellows/runtimes) //! - [RFCs](https://github.com/polkadot-fellows/rfcs) +//! - [Dashboard](https://polkadot-fellows.github.io/dashboard/) //! - [Polkadot Specs](spec.polkadot.network) //! - [The Polkadot Parachain Host Implementers' Guide](https://paritytech.github.io/polkadot-sdk/book/) //! - [Whitepaper](https://www.polkadot.network/whitepaper/) +//! - [JAM Graypaper](https://graypaper.com) //! //! ## Alternative Node Implementations 🌈 //! diff --git a/docs/sdk/src/polkadot_sdk/xcm.rs b/docs/sdk/src/polkadot_sdk/xcm.rs index 5dcdc9e1de076c4507cb64517360df73e6733dc7..58f54068642444e2010d3623d6a49d00f050ebf8 100644 --- a/docs/sdk/src/polkadot_sdk/xcm.rs +++ b/docs/sdk/src/polkadot_sdk/xcm.rs @@ -50,7 +50,7 @@ //! //! ## Get started //! -//! To learn how it works and to get started, go to the [XCM docs](https://paritytech.github.io/xcm-docs/). +//! To learn how it works and to get started, go to the [XCM docs](xcm_docs). #[cfg(test)] mod tests { diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index 145df8844f26e5b58d737a4290035e3886bf63fe..6fa25bf36e1b542d6412aa48d7fa8e62a7cd5769 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -106,3 +106,6 @@ pub mod frame_offchain_workers; /// Learn about the different ways through which multiple [`frame`] pallets can be combined to work /// together. pub mod frame_pallet_coupling; + +/// Learn about the Polkadot Umbrella crate that re-exports all other crates. +pub mod umbrella_crate; diff --git a/docs/sdk/src/reference_docs/umbrella_crate.rs b/docs/sdk/src/reference_docs/umbrella_crate.rs new file mode 100644 index 0000000000000000000000000000000000000000..9751b0ad5ad6d94a20e027e902ac055fa9e49181 --- /dev/null +++ b/docs/sdk/src/reference_docs/umbrella_crate.rs @@ -0,0 +1,89 @@ +//! # Umbrella Crate +//! +//! The Polkadot-SDK "umbrella" is a crate that re-exports all other published crates. This makes it +//! possible to have a very small `Cargo.toml` file that only has one dependency, the umbrella +//! crate. This helps with selecting the right combination of crate versions, since otherwise 3rd +//! party tools are needed to select a compatible set of versions. +//! +//! ## Features +//! +//! The umbrella crate supports no-std builds and can therefore be used in the runtime and node. +//! There are two main features: `runtime` and `node`. The `runtime` feature enables all `no-std` +//! crates, while the `node` feature enables all `std` crates. It should be used like any other +//! crate in the repo, with `default-features = false`. +//! +//! For more fine-grained control, additionally, each crate can be enabled selectively. The umbrella +//! exposes one feature per dependency. For example, if you only want to use the `frame-support` +//! crate, you can enable the `frame-support` feature. +//! +//! The umbrella exposes a few more general features: +//! - `tuples-96`: Needs to be enabled for runtimes that have more than 64 pallets. +//! - `serde`: Specifically enable `serde` en/decoding support. +//! - `experimental`: Experimental enable experimental features - should not yet used in production. +//! - `with-tracing`: Enable tracing support. +//! - `try-runtime`, `runtime-benchmarks` and `std`: These follow the standard conventions. +//! - `runtime`: As described above, enable all `no-std` crates. +//! - `node`: As described above, enable all `std` crates. +//! - There does *not* exist a dedicated docs feature. To generate docs, enable the `runtime` and +//! `node` feature. For docs.rs the manifest contains specific configuration to make it show up +//! all re-exports. +//! +//! There is a specific `zepter` check in place to ensure that the features of the umbrella are +//! correctly configured. This check is run in CI and locally when running `zepter`. +//! +//! ## Generation +//! +//! The umbrella crate needs to be updated every time when a new crate is added or removed from the +//! workspace. It is checked in CI by calling its generation script. The generation script is +//! located in `./scripts/generate-umbrella.py` and needs dependency `cargo_workspace`. +//! +//! Example: `python3 scripts/generate-umbrella.py --sdk . --version 1.9.0` +//! +//! ## Usage +//! +//! > Note: You can see a live example in the `staging-node-cli` and `kitchensink-runtime` crates. +//! +//! The umbrella crate can be added to your runtime crate like this: +//! +//! `polkadot-sdk = { path = "../../../../umbrella", features = ["runtime"], default-features = +//! false }` +//! +//! or for a node: +//! +//! `polkadot-sdk = { path = "../../../../umbrella", features = ["node"], default-features = false +//! }` +//! +//! In the code, it is then possible to bring all dependencies into scope via: +//! +//! `use polkadot_sdk::*;` +//! +//! ### Known Issues +//! +//! The only known issue so far is the fact that the `use` statement brings the dependencies only +//! into the outer module scope - not the global crate scope. For example, the following code would +//! need to be adjusted: +//! +//! ```rust +//! use polkadot_sdk::*; +//! +//! mod foo { +//! // This does sadly not compile: +//! frame_support::parameter_types! { } +//! +//! // Instead, we need to do this (or add an equivalent `use` statement): +//! polkadot_sdk::frame_support::parameter_types! { } +//! } +//! ``` +//! +//! Apart from this, no issues are known. There could be some bugs with how macros locate their own +//! re-exports. Please compile issues that arise from using this crate. +//! +//! ## Dependencies +//! +//! The umbrella crate re-exports all published crates, with a few exceptions: +//! - Runtime crates like `rococo-runtime` etc are not exported. This otherwise leads to very weird +//! compile errors and should not be needed anyway. +//! - Example and fuzzing crates are not exported. This is currently detected by checking the name +//! of the crate for these magic words. In the future, it will utilize custom metadata, as it is +//! done in the `rococo-runtime` crate. +//! - The umbrella crate itself. Should be obvious :) diff --git a/polkadot/Cargo.toml b/polkadot/Cargo.toml index 659edcb041c35625b6f7c6ee7841eab27c4c1175..3aeec8d5961e35133233c35c38f57c2145c7f62c 100644 --- a/polkadot/Cargo.toml +++ b/polkadot/Cargo.toml @@ -43,7 +43,7 @@ tikv-jemallocator = { version = "0.5.0", features = ["unprefixed_malloc_on_suppo [dev-dependencies] assert_cmd = "2.0.4" -nix = { version = "0.26.1", features = ["signal"] } +nix = { version = "0.28.0", features = ["signal"] } tempfile = "3.2.0" tokio = "1.37" substrate-rpc-client = { path = "../substrate/utils/frame/rpc/client" } diff --git a/polkadot/core-primitives/Cargo.toml b/polkadot/core-primitives/Cargo.toml index 8dfa0b87328b1af0bc4cbc1bcd677919acaaf892..9794f8286ac324b3f0fde27cb13db9d8d1cb8941 100644 --- a/polkadot/core-primitives/Cargo.toml +++ b/polkadot/core-primitives/Cargo.toml @@ -14,7 +14,7 @@ sp-core = { path = "../../substrate/primitives/core", default-features = false } sp-std = { path = "../../substrate/primitives/std", default-features = false } sp-runtime = { path = "../../substrate/primitives/runtime", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } [features] default = ["std"] diff --git a/polkadot/erasure-coding/Cargo.toml b/polkadot/erasure-coding/Cargo.toml index 677f15c4b9a1446c7828c78f92933f7811733ee8..bf152e03be711b6ec3e1afc3d049cf5e1f727401 100644 --- a/polkadot/erasure-coding/Cargo.toml +++ b/polkadot/erasure-coding/Cargo.toml @@ -13,13 +13,14 @@ workspace = true polkadot-primitives = { path = "../primitives" } polkadot-node-primitives = { package = "polkadot-node-primitives", path = "../node/primitives" } novelpoly = { package = "reed-solomon-novelpoly", version = "2.0.0" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "std"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "std"] } sp-core = { path = "../../substrate/primitives/core" } sp-trie = { path = "../../substrate/primitives/trie" } thiserror = { workspace = true } [dev-dependencies] -criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support"] } +quickcheck = { version = "1.0.3", default-features = false } +criterion = { version = "0.5.1", default-features = false, features = ["cargo_bench_support"] } [[bench]] name = "scaling_with_validators" diff --git a/polkadot/erasure-coding/benches/README.md b/polkadot/erasure-coding/benches/README.md index 94fca5400c610636831c08b5282d6d47f4199878..20f79827d280b23782368c4f56f2a85f5d4eed41 100644 --- a/polkadot/erasure-coding/benches/README.md +++ b/polkadot/erasure-coding/benches/README.md @@ -7,7 +7,8 @@ cargo bench ## `scaling_with_validators` This benchmark evaluates the performance of constructing the chunks and the erasure root from PoV and -reconstructing the PoV from chunks. You can see the results of running this bench on 5950x below. +reconstructing the PoV from chunks (either from systematic chunks or regular chunks). +You can see the results of running this bench on 5950x below (only including recovery from regular chunks). Interestingly, with `10_000` chunks (validators) its slower than with `50_000` for both construction and reconstruction. ``` @@ -37,3 +38,6 @@ reconstruct/10000 time: [496.35 ms 505.17 ms 515.42 ms] reconstruct/50000 time: [276.56 ms 277.53 ms 278.58 ms] thrpt: [17.948 MiB/s 18.016 MiB/s 18.079 MiB/s] ``` + +Results from running on an Apple M2 Pro, systematic recovery is generally 40 times faster than +regular recovery, achieving 1 Gib/s. diff --git a/polkadot/erasure-coding/benches/scaling_with_validators.rs b/polkadot/erasure-coding/benches/scaling_with_validators.rs index 759385bbdef4ed85e5db087d2d93c7cb51250db8..3d743faa4169b48f651e99e2e005237d727841d7 100644 --- a/polkadot/erasure-coding/benches/scaling_with_validators.rs +++ b/polkadot/erasure-coding/benches/scaling_with_validators.rs @@ -53,12 +53,16 @@ fn construct_and_reconstruct_5mb_pov(c: &mut Criterion) { } group.finish(); - let mut group = c.benchmark_group("reconstruct"); + let mut group = c.benchmark_group("reconstruct_regular"); for n_validators in N_VALIDATORS { let all_chunks = chunks(n_validators, &pov); - let mut c: Vec<_> = all_chunks.iter().enumerate().map(|(i, c)| (&c[..], i)).collect(); - let last_chunks = c.split_off((c.len() - 1) * 2 / 3); + let chunks: Vec<_> = all_chunks + .iter() + .enumerate() + .take(polkadot_erasure_coding::recovery_threshold(n_validators).unwrap()) + .map(|(i, c)| (&c[..], i)) + .collect(); group.throughput(Throughput::Bytes(pov.len() as u64)); group.bench_with_input( @@ -67,7 +71,31 @@ fn construct_and_reconstruct_5mb_pov(c: &mut Criterion) { |b, &n| { b.iter(|| { let _pov: Vec = - polkadot_erasure_coding::reconstruct(n, last_chunks.clone()).unwrap(); + polkadot_erasure_coding::reconstruct(n, chunks.clone()).unwrap(); + }); + }, + ); + } + group.finish(); + + let mut group = c.benchmark_group("reconstruct_systematic"); + for n_validators in N_VALIDATORS { + let all_chunks = chunks(n_validators, &pov); + + let chunks = all_chunks + .into_iter() + .take(polkadot_erasure_coding::systematic_recovery_threshold(n_validators).unwrap()) + .collect::>(); + + group.throughput(Throughput::Bytes(pov.len() as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(n_validators), + &n_validators, + |b, &n| { + b.iter(|| { + let _pov: Vec = + polkadot_erasure_coding::reconstruct_from_systematic(n, chunks.clone()) + .unwrap(); }); }, ); diff --git a/polkadot/erasure-coding/src/lib.rs b/polkadot/erasure-coding/src/lib.rs index e5155df4beba95aa9e7944e3e9a67d4e55a1db9c..b354c3dac64ceaff4668f1edf66465214d58b54a 100644 --- a/polkadot/erasure-coding/src/lib.rs +++ b/polkadot/erasure-coding/src/lib.rs @@ -69,6 +69,9 @@ pub enum Error { /// Bad payload in reconstructed bytes. #[error("Reconstructed payload invalid")] BadPayload, + /// Unable to decode reconstructed bytes. + #[error("Unable to decode reconstructed payload: {0}")] + Decode(#[source] parity_scale_codec::Error), /// Invalid branch proof. #[error("Invalid branch proof")] InvalidBranchProof, @@ -110,6 +113,14 @@ pub const fn recovery_threshold(n_validators: usize) -> Result { Ok(needed + 1) } +/// Obtain the threshold of systematic chunks that should be enough to recover the data. +/// +/// If the regular `recovery_threshold` is a power of two, then it returns the same value. +/// Otherwise, it returns the next lower power of two. +pub fn systematic_recovery_threshold(n_validators: usize) -> Result { + code_params(n_validators).map(|params| params.k()) +} + fn code_params(n_validators: usize) -> Result { // we need to be able to reconstruct from 1/3 - eps @@ -127,6 +138,41 @@ fn code_params(n_validators: usize) -> Result { }) } +/// Reconstruct the v1 available data from the set of systematic chunks. +/// +/// Provide a vector containing chunk data. If too few chunks are provided, recovery is not +/// possible. +pub fn reconstruct_from_systematic_v1( + n_validators: usize, + chunks: Vec>, +) -> Result { + reconstruct_from_systematic(n_validators, chunks) +} + +/// Reconstruct the available data from the set of systematic chunks. +/// +/// Provide a vector containing the first k chunks in order. If too few chunks are provided, +/// recovery is not possible. +pub fn reconstruct_from_systematic( + n_validators: usize, + chunks: Vec>, +) -> Result { + let code_params = code_params(n_validators)?; + let k = code_params.k(); + + for chunk_data in chunks.iter().take(k) { + if chunk_data.len() % 2 != 0 { + return Err(Error::UnevenLength) + } + } + + let bytes = code_params.make_encoder().reconstruct_from_systematic( + chunks.into_iter().take(k).map(|data| WrappedShard::new(data)).collect(), + )?; + + Decode::decode(&mut &bytes[..]).map_err(|err| Error::Decode(err)) +} + /// Obtain erasure-coded chunks for v1 `AvailableData`, one for each validator. /// /// Works only up to 65536 validators, and `n_validators` must be non-zero. @@ -285,13 +331,41 @@ pub fn branch_hash(root: &H256, branch_nodes: &Proof, index: usize) -> Result

Self { + // Limit the POV len to 1 mib, otherwise the test will take forever + let pov_len = (u32::arbitrary(g) % (1024 * 1024)).max(2); + + let pov = (0..pov_len).map(|_| u8::arbitrary(g)).collect(); + + let pvd = PersistedValidationData { + parent_head: HeadData((0..u16::arbitrary(g)).map(|_| u8::arbitrary(g)).collect()), + relay_parent_number: u32::arbitrary(g), + relay_parent_storage_root: [u8::arbitrary(g); 32].into(), + max_pov_size: u32::arbitrary(g), + }; + + ArbitraryAvailableData(AvailableData { + pov: Arc::new(PoV { block_data: BlockData(pov) }), + validation_data: pvd, + }) + } + } + #[test] fn field_order_is_right_size() { assert_eq!(MAX_VALIDATORS, 65536); @@ -318,6 +392,25 @@ mod tests { assert_eq!(reconstructed, available_data); } + #[test] + fn round_trip_systematic_works() { + fn property(available_data: ArbitraryAvailableData, n_validators: u16) { + let n_validators = n_validators.max(2); + let kpow2 = systematic_recovery_threshold(n_validators as usize).unwrap(); + let chunks = obtain_chunks(n_validators as usize, &available_data.0).unwrap(); + assert_eq!( + reconstruct_from_systematic_v1( + n_validators as usize, + chunks.into_iter().take(kpow2).collect() + ) + .unwrap(), + available_data.0 + ); + } + + QuickCheck::new().quickcheck(property as fn(ArbitraryAvailableData, u16)) + } + #[test] fn reconstruct_does_not_panic_on_low_validator_count() { let reconstructed = reconstruct_v1(1, [].iter().cloned()); diff --git a/polkadot/node/collation-generation/Cargo.toml b/polkadot/node/collation-generation/Cargo.toml index ebc53a9e01bbe5abc6ba18e500ad3bafcf35ead3..0a28c3a830d101a08a49a3c9eda3dc0f60c9665d 100644 --- a/polkadot/node/collation-generation/Cargo.toml +++ b/polkadot/node/collation-generation/Cargo.toml @@ -20,7 +20,7 @@ polkadot-primitives = { path = "../../primitives" } sp-core = { path = "../../../substrate/primitives/core" } sp-maybe-compressed-blob = { path = "../../../substrate/primitives/maybe-compressed-blob" } thiserror = { workspace = true } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } diff --git a/polkadot/node/core/approval-voting/Cargo.toml b/polkadot/node/core/approval-voting/Cargo.toml index 473bc67923b6f084f6f45f3864c22cfbae885ffe..5bf80d59ede93b9fb3cab3ffdf409f895d24dbe4 100644 --- a/polkadot/node/core/approval-voting/Cargo.toml +++ b/polkadot/node/core/approval-voting/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] futures = "0.3.30" futures-timer = "3.0.2" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } gum = { package = "tracing-gum", path = "../../gum" } bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } schnellru = "0.2.1" @@ -21,7 +21,7 @@ schnorrkel = "0.11.4" kvdb = "0.13.0" derive_more = "0.99.17" thiserror = { workspace = true } -itertools = "0.10.5" +itertools = "0.11" polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } diff --git a/polkadot/node/core/approval-voting/benches/approval-voting-regression-bench.rs b/polkadot/node/core/approval-voting/benches/approval-voting-regression-bench.rs index 9a5f0d29dbd3180676a01eba0b382dbb26ef11ea..687063dd0eb302c4b61b224ee74bb9c4a56fbe5b 100644 --- a/polkadot/node/core/approval-voting/benches/approval-voting-regression-bench.rs +++ b/polkadot/node/core/approval-voting/benches/approval-voting-regression-bench.rs @@ -61,7 +61,7 @@ fn main() -> Result<(), String> { print!("\r[{}{}]", "#".repeat(n), "_".repeat(BENCH_COUNT - n)); std::io::stdout().flush().unwrap(); let (mut env, state) = prepare_test(config.clone(), options.clone(), false); - env.runtime().block_on(bench_approvals("approvals_throughput", &mut env, state)) + env.runtime().block_on(bench_approvals(&mut env, state)) }) .collect(); println!("\rDone!{}", " ".repeat(BENCH_COUNT)); @@ -81,8 +81,8 @@ fn main() -> Result<(), String> { ("Sent to peers", 63547.0330, 0.001), ])); messages.extend(average_usage.check_cpu_usage(&[ - ("approval-distribution", 7.0317, 0.1), - ("approval-voting", 9.5751, 0.1), + ("approval-distribution", 7.4075, 0.1), + ("approval-voting", 9.9873, 0.1), ])); if messages.is_empty() { diff --git a/polkadot/node/core/approval-voting/src/import.rs b/polkadot/node/core/approval-voting/src/import.rs index f4be42a4845080ce90fb87ddc838e2c1ab792ed1..13b0b1bae1bc3281b89b6405ce166ab0cecbd512 100644 --- a/polkadot/node/core/approval-voting/src/import.rs +++ b/polkadot/node/core/approval-voting/src/import.rs @@ -607,7 +607,7 @@ pub(crate) mod tests { use super::*; use crate::{ approval_db::common::{load_block_entry, DbBackend}, - RuntimeInfo, RuntimeInfoConfig, + RuntimeInfo, RuntimeInfoConfig, MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS, }; use ::test_helpers::{dummy_candidate_receipt, dummy_hash}; use assert_matches::assert_matches; @@ -622,6 +622,7 @@ pub(crate) mod tests { node_features::FeatureIndex, ExecutorParams, Id as ParaId, IndexedVec, NodeFeatures, SessionInfo, ValidatorId, ValidatorIndex, }; + use schnellru::{ByLength, LruMap}; pub(crate) use sp_consensus_babe::{ digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest}, AllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, @@ -658,6 +659,9 @@ pub(crate) mod tests { clock: Box::new(MockClock::default()), assignment_criteria: Box::new(MockAssignmentCriteria::default()), spans: HashMap::new(), + per_block_assignments_gathering_times: LruMap::new(ByLength::new( + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS, + )), } } diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index b5ed92fa39c873c0a1e5f40c52705a5803971b60..eece6b15805c233c8a7e674bed79fe49a682de96 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -63,6 +63,12 @@ use sc_keystore::LocalKeystore; use sp_application_crypto::Pair; use sp_consensus::SyncOracle; use sp_consensus_slots::Slot; +use std::time::Instant; + +// The max number of blocks we keep track of assignments gathering times. Normally, +// this would never be reached because we prune the data on finalization, but we need +// to also ensure the data is not growing unecessarily large. +const MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS: u32 = 100; use futures::{ channel::oneshot, @@ -182,6 +188,14 @@ struct MetricsInner { time_recover_and_approve: prometheus::Histogram, candidate_signatures_requests_total: prometheus::Counter, unapproved_candidates_in_unfinalized_chain: prometheus::Gauge, + // The time it takes in each stage to gather enough assignments. + // We defined a `stage` as being the entire process of gathering enough assignments to + // be able to approve a candidate: + // E.g: + // - Stage 0: We wait for the needed_approvals assignments to be gathered. + // - Stage 1: We wait for enough tranches to cover all no-shows in stage 0. + // - Stage 2: We wait for enough tranches to cover all no-shows of stage 1. + assignments_gathering_time_by_stage: prometheus::HistogramVec, } /// Approval Voting metrics. @@ -302,6 +316,20 @@ impl Metrics { metrics.unapproved_candidates_in_unfinalized_chain.set(count as u64); } } + + pub fn observe_assignment_gathering_time(&self, stage: usize, elapsed_as_millis: usize) { + if let Some(metrics) = &self.0 { + let stage_string = stage.to_string(); + // We don't want to have too many metrics entries with this label to not put unncessary + // pressure on the metrics infrastructure, so we cap the stage at 10, which is + // equivalent to having already a finalization lag to 10 * no_show_slots, so it should + // be more than enough. + metrics + .assignments_gathering_time_by_stage + .with_label_values(&[if stage < 10 { stage_string.as_str() } else { "inf" }]) + .observe(elapsed_as_millis as f64); + } + } } impl metrics::Metrics for Metrics { @@ -431,6 +459,17 @@ impl metrics::Metrics for Metrics { )?, registry, )?, + assignments_gathering_time_by_stage: prometheus::register( + prometheus::HistogramVec::new( + prometheus::HistogramOpts::new( + "polkadot_parachain_assignments_gather_time_by_stage_ms", + "The time in ms it takes for each stage to gather enough assignments needed for approval", + ) + .buckets(vec![0.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0, 32000.0]), + &["stage"], + )?, + registry, + )?, }; Ok(Metrics(Some(metrics))) @@ -788,6 +827,28 @@ struct State { clock: Box, assignment_criteria: Box, spans: HashMap, + // Per block, candidate records about how long we take until we gather enough + // assignments, this is relevant because it gives us a good idea about how many + // tranches we trigger and why. + per_block_assignments_gathering_times: + LruMap>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct AssignmentGatheringRecord { + // The stage we are in. + // Candidate assignment gathering goes in stages, first we wait for needed_approvals(stage 0) + // Then if we have no-shows, we move into stage 1 and wait for enough tranches to cover all + // no-shows. + stage: usize, + // The time we started the stage. + stage_start: Option, +} + +impl Default for AssignmentGatheringRecord { + fn default() -> Self { + AssignmentGatheringRecord { stage: 0, stage_start: Some(Instant::now()) } + } } #[overseer::contextbounds(ApprovalVoting, prefix = self::overseer)] @@ -893,6 +954,96 @@ impl State { }, } } + + fn mark_begining_of_gathering_assignments( + &mut self, + block_number: BlockNumber, + block_hash: Hash, + candidate: CandidateHash, + ) { + if let Some(record) = self + .per_block_assignments_gathering_times + .get_or_insert(block_number, HashMap::new) + .and_then(|records| Some(records.entry((block_hash, candidate)).or_default())) + { + if record.stage_start.is_none() { + record.stage += 1; + gum::debug!( + target: LOG_TARGET, + stage = ?record.stage, + ?block_hash, + ?candidate, + "Started a new assignment gathering stage", + ); + record.stage_start = Some(Instant::now()); + } + } + } + + fn mark_gathered_enough_assignments( + &mut self, + block_number: BlockNumber, + block_hash: Hash, + candidate: CandidateHash, + ) -> AssignmentGatheringRecord { + let record = self + .per_block_assignments_gathering_times + .get(&block_number) + .and_then(|entry| entry.get_mut(&(block_hash, candidate))); + let stage = record.as_ref().map(|record| record.stage).unwrap_or_default(); + AssignmentGatheringRecord { + stage, + stage_start: record.and_then(|record| record.stage_start.take()), + } + } + + fn cleanup_assignments_gathering_timestamp(&mut self, remove_lower_than: BlockNumber) { + while let Some((block_number, _)) = self.per_block_assignments_gathering_times.peek_oldest() + { + if *block_number < remove_lower_than { + self.per_block_assignments_gathering_times.pop_oldest(); + } else { + break + } + } + } + + fn observe_assignment_gathering_status( + &mut self, + metrics: &Metrics, + required_tranches: &RequiredTranches, + block_hash: Hash, + block_number: BlockNumber, + candidate_hash: CandidateHash, + ) { + match required_tranches { + RequiredTranches::All | RequiredTranches::Pending { .. } => { + self.mark_begining_of_gathering_assignments( + block_number, + block_hash, + candidate_hash, + ); + }, + RequiredTranches::Exact { .. } => { + let time_to_gather = + self.mark_gathered_enough_assignments(block_number, block_hash, candidate_hash); + if let Some(gathering_started) = time_to_gather.stage_start { + if gathering_started.elapsed().as_millis() > 6000 { + gum::trace!( + target: LOG_TARGET, + ?block_hash, + ?candidate_hash, + "Long assignment gathering time", + ); + } + metrics.observe_assignment_gathering_time( + time_to_gather.stage, + gathering_started.elapsed().as_millis() as usize, + ) + } + }, + } + } } #[derive(Debug, Clone)] @@ -914,6 +1065,7 @@ enum Action { candidate: CandidateReceipt, backing_group: GroupIndex, distribute_assignment: bool, + core_index: Option, }, NoteApprovedInChainSelection(Hash), IssueApproval(CandidateHash, ApprovalVoteRequest), @@ -941,6 +1093,9 @@ where clock: subsystem.clock, assignment_criteria, spans: HashMap::new(), + per_block_assignments_gathering_times: LruMap::new(ByLength::new( + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS, + )), }; // `None` on start-up. Gets initialized/updated on leaf update @@ -972,7 +1127,7 @@ where subsystem.metrics.on_wakeup(); process_wakeup( &mut ctx, - &state, + &mut state, &mut overlayed_db, &mut session_info_provider, woken_block, @@ -1174,6 +1329,7 @@ async fn handle_actions( candidate, backing_group, distribute_assignment, + core_index, } => { // Don't launch approval work if the node is syncing. if let Mode::Syncing(_) = *mode { @@ -1230,6 +1386,7 @@ async fn handle_actions( block_hash, backing_group, executor_params, + core_index, &launch_approval_span, ) .await @@ -1467,6 +1624,7 @@ async fn distribution_messages_for_activation( candidate: candidate_entry.candidate_receipt().clone(), backing_group: approval_entry.backing_group(), distribute_assignment: false, + core_index: Some(*core_index), }); } }, @@ -1628,6 +1786,7 @@ async fn handle_from_overseer( // `prune_finalized_wakeups` prunes all finalized block hashes. We prune spans // accordingly. wakeups.prune_finalized_wakeups(block_number, &mut state.spans); + state.cleanup_assignments_gathering_timestamp(block_number); // // `prune_finalized_wakeups` prunes all finalized block hashes. We prune spans // accordingly. let hash_set = @@ -2474,7 +2633,7 @@ where async fn check_and_import_approval( sender: &mut Sender, - state: &State, + state: &mut State, db: &mut OverlayedBackend<'_, impl Backend>, session_info_provider: &mut RuntimeInfo, metrics: &Metrics, @@ -2706,7 +2865,7 @@ impl ApprovalStateTransition { // as necessary and schedules any further wakeups. async fn advance_approval_state( sender: &mut Sender, - state: &State, + state: &mut State, db: &mut OverlayedBackend<'_, impl Backend>, session_info_provider: &mut RuntimeInfo, metrics: &Metrics, @@ -2757,6 +2916,13 @@ where approval_entry, status.required_tranches.clone(), ); + state.observe_assignment_gathering_status( + &metrics, + &status.required_tranches, + block_hash, + block_entry.block_number(), + candidate_hash, + ); // Check whether this is approved, while allowing a maximum // assignment tick of `now - APPROVAL_DELAY` - that is, that @@ -2937,7 +3103,7 @@ fn should_trigger_assignment( #[overseer::contextbounds(ApprovalVoting, prefix = self::overseer)] async fn process_wakeup( ctx: &mut Context, - state: &State, + state: &mut State, db: &mut OverlayedBackend<'_, impl Backend>, session_info_provider: &mut RuntimeInfo, relay_block: Hash, @@ -3050,6 +3216,11 @@ async fn process_wakeup( "Launching approval work.", ); + let candidate_core_index = block_entry + .candidates() + .iter() + .find_map(|(core_index, h)| (h == &candidate_hash).then_some(*core_index)); + if let Some(claimed_core_indices) = get_assignment_core_indices(&indirect_cert.cert.kind, &candidate_hash, &block_entry) { @@ -3062,7 +3233,6 @@ async fn process_wakeup( true }; db.write_block_entry(block_entry.clone()); - actions.push(Action::LaunchApproval { claimed_candidate_indices, candidate_hash, @@ -3074,10 +3244,12 @@ async fn process_wakeup( candidate: candidate_receipt, backing_group, distribute_assignment, + core_index: candidate_core_index, }); }, Err(err) => { - // Never happens, it should only happen if no cores are claimed, which is a bug. + // Never happens, it should only happen if no cores are claimed, which is a + // bug. gum::warn!( target: LOG_TARGET, block_hash = ?relay_block, @@ -3133,6 +3305,7 @@ async fn launch_approval( block_hash: Hash, backing_group: GroupIndex, executor_params: ExecutorParams, + core_index: Option, span: &jaeger::Span, ) -> SubsystemResult> { let (a_tx, a_rx) = oneshot::channel(); @@ -3179,6 +3352,7 @@ async fn launch_approval( candidate.clone(), session_index, Some(backing_group), + core_index, a_tx, )) .await; diff --git a/polkadot/node/core/approval-voting/src/persisted_entries.rs b/polkadot/node/core/approval-voting/src/persisted_entries.rs index 6eeb99cb99ffa017492dba93e72556eab9104c8e..59a4618100515a179a3cdc8b72aee41024ff0bbb 100644 --- a/polkadot/node/core/approval-voting/src/persisted_entries.rs +++ b/polkadot/node/core/approval-voting/src/persisted_entries.rs @@ -559,7 +559,7 @@ impl BlockEntry { self.distributed_assignments.resize(new_len, false); self.distributed_assignments |= bitfield; - // If the an operation did not change our current bitfied, we return true. + // If the an operation did not change our current bitfield, we return true. let distributed = total_one_bits == self.distributed_assignments.count_ones(); distributed diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index 312d805bbefb7b2b2605093fa2cadde0a1f10511..43af8d476a6ba7b786be89d8d4e425d9ff44b106 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -17,6 +17,10 @@ use self::test_helpers::mock::new_leaf; use super::*; use crate::backend::V1ReadBackend; +use overseer::prometheus::{ + prometheus::{IntCounter, IntCounterVec}, + Histogram, HistogramOpts, HistogramVec, Opts, +}; use polkadot_node_primitives::{ approval::{ v1::{ @@ -40,7 +44,7 @@ use polkadot_primitives::{ ApprovalVote, CandidateCommitments, CandidateEvent, CoreIndex, GroupIndex, Header, Id as ParaId, IndexedVec, NodeFeatures, ValidationCode, ValidatorSignature, }; -use std::time::Duration; +use std::{cmp::max, time::Duration}; use assert_matches::assert_matches; use async_trait::async_trait; @@ -3330,7 +3334,7 @@ async fn recover_available_data(virtual_overseer: &mut VirtualOverseer) { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Ok(available_data)).unwrap(); }, @@ -5049,3 +5053,233 @@ fn subsystem_sends_pending_approvals_on_approval_restart() { virtual_overseer }); } + +// Test we correctly update the timer when we mark the beginning of gathering assignments. +#[test] +fn test_gathering_assignments_statements() { + let mut state = State { + keystore: Arc::new(LocalKeystore::in_memory()), + slot_duration_millis: 6_000, + clock: Box::new(MockClock::default()), + assignment_criteria: Box::new(MockAssignmentCriteria::check_only(|_| Ok(0))), + spans: HashMap::new(), + per_block_assignments_gathering_times: LruMap::new(ByLength::new( + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS, + )), + }; + + for i in 0..200i32 { + state.mark_begining_of_gathering_assignments( + i as u32, + Hash::repeat_byte(i as u8), + CandidateHash(Hash::repeat_byte(i as u8)), + ); + assert!( + state.per_block_assignments_gathering_times.len() <= + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS as usize + ); + + assert_eq!( + state + .per_block_assignments_gathering_times + .iter() + .map(|(block_number, _)| block_number) + .min(), + Some(max(0, i - MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS as i32 + 1) as u32).as_ref() + ) + } + assert_eq!( + state.per_block_assignments_gathering_times.len(), + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS as usize + ); + + let nothing_changes = state + .per_block_assignments_gathering_times + .iter() + .map(|(block_number, _)| *block_number) + .sorted() + .collect::>(); + + for i in 150..200i32 { + state.mark_begining_of_gathering_assignments( + i as u32, + Hash::repeat_byte(i as u8), + CandidateHash(Hash::repeat_byte(i as u8)), + ); + assert_eq!( + nothing_changes, + state + .per_block_assignments_gathering_times + .iter() + .map(|(block_number, _)| *block_number) + .sorted() + .collect::>() + ); + } + + for i in 110..120 { + let block_hash = Hash::repeat_byte(i as u8); + let candidate_hash = CandidateHash(Hash::repeat_byte(i as u8)); + + state.mark_gathered_enough_assignments(i as u32, block_hash, candidate_hash); + + assert!(state + .per_block_assignments_gathering_times + .get(&i) + .unwrap() + .get(&(block_hash, candidate_hash)) + .unwrap() + .stage_start + .is_none()); + state.mark_begining_of_gathering_assignments(i as u32, block_hash, candidate_hash); + let record = state + .per_block_assignments_gathering_times + .get(&i) + .unwrap() + .get(&(block_hash, candidate_hash)) + .unwrap(); + + assert!(record.stage_start.is_some()); + assert_eq!(record.stage, 1); + } + + state.cleanup_assignments_gathering_timestamp(200); + assert_eq!(state.per_block_assignments_gathering_times.len(), 0); +} + +// Test we note the time we took to transition RequiredTranche from Pending to Exact and +// that we increase the stage when we transition from Exact to Pending. +#[test] +fn test_observe_assignment_gathering_status() { + let mut state = State { + keystore: Arc::new(LocalKeystore::in_memory()), + slot_duration_millis: 6_000, + clock: Box::new(MockClock::default()), + assignment_criteria: Box::new(MockAssignmentCriteria::check_only(|_| Ok(0))), + spans: HashMap::new(), + per_block_assignments_gathering_times: LruMap::new(ByLength::new( + MAX_BLOCKS_WITH_ASSIGNMENT_TIMESTAMPS, + )), + }; + + let metrics_inner = MetricsInner { + imported_candidates_total: IntCounter::new("dummy", "dummy").unwrap(), + assignments_produced: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")).unwrap(), + approvals_produced_total: IntCounterVec::new(Opts::new("dummy", "dummy"), &["dummy"]) + .unwrap(), + no_shows_total: IntCounter::new("dummy", "dummy").unwrap(), + observed_no_shows: IntCounter::new("dummy", "dummy").unwrap(), + approved_by_one_third: IntCounter::new("dummy", "dummy").unwrap(), + wakeups_triggered_total: IntCounter::new("dummy", "dummy").unwrap(), + coalesced_approvals_buckets: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")) + .unwrap(), + coalesced_approvals_delay: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")) + .unwrap(), + candidate_approval_time_ticks: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")) + .unwrap(), + block_approval_time_ticks: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")) + .unwrap(), + time_db_transaction: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")).unwrap(), + time_recover_and_approve: Histogram::with_opts(HistogramOpts::new("dummy", "dummy")) + .unwrap(), + candidate_signatures_requests_total: IntCounter::new("dummy", "dummy").unwrap(), + unapproved_candidates_in_unfinalized_chain: prometheus::Gauge::::new( + "dummy", "dummy", + ) + .unwrap(), + assignments_gathering_time_by_stage: HistogramVec::new( + HistogramOpts::new("test", "test"), + &["stage"], + ) + .unwrap(), + }; + + let metrics = Metrics(Some(metrics_inner)); + let block_hash = Hash::repeat_byte(1); + let candidate_hash = CandidateHash(Hash::repeat_byte(1)); + let block_number = 1; + + // Transition from Pending to Exact and check stage 0 time is recorded. + state.observe_assignment_gathering_status( + &metrics, + &RequiredTranches::Pending { + considered: 0, + next_no_show: None, + maximum_broadcast: 0, + clock_drift: 0, + }, + block_hash, + block_number, + candidate_hash, + ); + + state.observe_assignment_gathering_status( + &metrics, + &RequiredTranches::Exact { + needed: 2, + tolerated_missing: 2, + next_no_show: None, + last_assignment_tick: None, + }, + block_hash, + block_number, + candidate_hash, + ); + + let value = metrics + .0 + .as_ref() + .unwrap() + .assignments_gathering_time_by_stage + .get_metric_with_label_values(&["0"]) + .unwrap(); + + assert_eq!(value.get_sample_count(), 1); + + // Transition from Exact to Pending to Exact and check stage 1 time is recorded. + state.observe_assignment_gathering_status( + &metrics, + &RequiredTranches::Pending { + considered: 0, + next_no_show: None, + maximum_broadcast: 0, + clock_drift: 0, + }, + block_hash, + block_number, + candidate_hash, + ); + + state.observe_assignment_gathering_status( + &metrics, + &RequiredTranches::Exact { + needed: 2, + tolerated_missing: 2, + next_no_show: None, + last_assignment_tick: None, + }, + block_hash, + block_number, + candidate_hash, + ); + + let value = metrics + .0 + .as_ref() + .unwrap() + .assignments_gathering_time_by_stage + .get_metric_with_label_values(&["0"]) + .unwrap(); + + assert_eq!(value.get_sample_count(), 1); + + let value = metrics + .0 + .as_ref() + .unwrap() + .assignments_gathering_time_by_stage + .get_metric_with_label_values(&["1"]) + .unwrap(); + + assert_eq!(value.get_sample_count(), 1); +} diff --git a/polkadot/node/core/av-store/Cargo.toml b/polkadot/node/core/av-store/Cargo.toml index bc9b979228a1db8c4adfc01bd2d60470721bfcac..c5b3c382011b12ac80e130500d7c64b481989331 100644 --- a/polkadot/node/core/av-store/Cargo.toml +++ b/polkadot/node/core/av-store/Cargo.toml @@ -17,7 +17,7 @@ thiserror = { workspace = true } gum = { package = "tracing-gum", path = "../../gum" } bitvec = "1.0.0" -parity-scale-codec = { version = "3.6.1", features = ["derive"] } +parity-scale-codec = { version = "3.6.12", features = ["derive"] } erasure = { package = "polkadot-erasure-coding", path = "../../../erasure-coding" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } diff --git a/polkadot/node/core/av-store/src/lib.rs b/polkadot/node/core/av-store/src/lib.rs index 68db4686a9740bb052f7d05031d148cd5b05e0a2..59a35a6a45a91446793099b72ff36d9a2a573f52 100644 --- a/polkadot/node/core/av-store/src/lib.rs +++ b/polkadot/node/core/av-store/src/lib.rs @@ -48,8 +48,10 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_util as util; use polkadot_primitives::{ - BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, Hash, Header, ValidatorIndex, + BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, Hash, + Header, NodeFeatures, ValidatorIndex, }; +use util::availability_chunks::availability_chunk_indices; mod metrics; pub use self::metrics::*; @@ -208,9 +210,9 @@ fn load_chunk( db: &Arc, config: &Config, candidate_hash: &CandidateHash, - chunk_index: ValidatorIndex, + validator_index: ValidatorIndex, ) -> Result, Error> { - let key = (CHUNK_PREFIX, candidate_hash, chunk_index).encode(); + let key = (CHUNK_PREFIX, candidate_hash, validator_index).encode(); query_inner(db, config.col_data, &key) } @@ -219,10 +221,10 @@ fn write_chunk( tx: &mut DBTransaction, config: &Config, candidate_hash: &CandidateHash, - chunk_index: ValidatorIndex, + validator_index: ValidatorIndex, erasure_chunk: &ErasureChunk, ) { - let key = (CHUNK_PREFIX, candidate_hash, chunk_index).encode(); + let key = (CHUNK_PREFIX, candidate_hash, validator_index).encode(); tx.put_vec(config.col_data, &key, erasure_chunk.encode()); } @@ -231,9 +233,9 @@ fn delete_chunk( tx: &mut DBTransaction, config: &Config, candidate_hash: &CandidateHash, - chunk_index: ValidatorIndex, + validator_index: ValidatorIndex, ) { - let key = (CHUNK_PREFIX, candidate_hash, chunk_index).encode(); + let key = (CHUNK_PREFIX, candidate_hash, validator_index).encode(); tx.delete(config.col_data, &key[..]); } @@ -1139,20 +1141,23 @@ fn process_message( Some(meta) => { let mut chunks = Vec::new(); - for (index, _) in meta.chunks_stored.iter().enumerate().filter(|(_, b)| **b) { + for (validator_index, _) in + meta.chunks_stored.iter().enumerate().filter(|(_, b)| **b) + { + let validator_index = ValidatorIndex(validator_index as _); let _timer = subsystem.metrics.time_get_chunk(); match load_chunk( &subsystem.db, &subsystem.config, &candidate, - ValidatorIndex(index as _), + validator_index, )? { - Some(c) => chunks.push(c), + Some(c) => chunks.push((validator_index, c)), None => { gum::warn!( target: LOG_TARGET, ?candidate, - index, + ?validator_index, "No chunk found for set bit in meta" ); }, @@ -1169,11 +1174,17 @@ fn process_message( }); let _ = tx.send(a); }, - AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk, tx } => { + AvailabilityStoreMessage::StoreChunk { candidate_hash, validator_index, chunk, tx } => { subsystem.metrics.on_chunks_received(1); let _timer = subsystem.metrics.time_store_chunk(); - match store_chunk(&subsystem.db, &subsystem.config, candidate_hash, chunk) { + match store_chunk( + &subsystem.db, + &subsystem.config, + candidate_hash, + validator_index, + chunk, + ) { Ok(true) => { let _ = tx.send(Ok(())); }, @@ -1191,6 +1202,8 @@ fn process_message( n_validators, available_data, expected_erasure_root, + core_index, + node_features, tx, } => { subsystem.metrics.on_chunks_received(n_validators as _); @@ -1203,6 +1216,8 @@ fn process_message( n_validators as _, available_data, expected_erasure_root, + core_index, + node_features, ); match res { @@ -1233,6 +1248,7 @@ fn store_chunk( db: &Arc, config: &Config, candidate_hash: CandidateHash, + validator_index: ValidatorIndex, chunk: ErasureChunk, ) -> Result { let mut tx = DBTransaction::new(); @@ -1242,12 +1258,12 @@ fn store_chunk( None => return Ok(false), // we weren't informed of this candidate by import events. }; - match meta.chunks_stored.get(chunk.index.0 as usize).map(|b| *b) { + match meta.chunks_stored.get(validator_index.0 as usize).map(|b| *b) { Some(true) => return Ok(true), // already stored. Some(false) => { - meta.chunks_stored.set(chunk.index.0 as usize, true); + meta.chunks_stored.set(validator_index.0 as usize, true); - write_chunk(&mut tx, config, &candidate_hash, chunk.index, &chunk); + write_chunk(&mut tx, config, &candidate_hash, validator_index, &chunk); write_meta(&mut tx, config, &candidate_hash, &meta); }, None => return Ok(false), // out of bounds. @@ -1257,6 +1273,7 @@ fn store_chunk( target: LOG_TARGET, ?candidate_hash, chunk_index = %chunk.index.0, + validator_index = %validator_index.0, "Stored chunk index for candidate.", ); @@ -1264,13 +1281,14 @@ fn store_chunk( Ok(true) } -// Ok(true) on success, Ok(false) on failure, and Err on internal error. fn store_available_data( subsystem: &AvailabilityStoreSubsystem, candidate_hash: CandidateHash, n_validators: usize, available_data: AvailableData, expected_erasure_root: Hash, + core_index: CoreIndex, + node_features: NodeFeatures, ) -> Result<(), Error> { let mut tx = DBTransaction::new(); @@ -1312,16 +1330,26 @@ fn store_available_data( drop(erasure_span); - let erasure_chunks = chunks.iter().zip(branches.map(|(proof, _)| proof)).enumerate().map( - |(index, (chunk, proof))| ErasureChunk { + let erasure_chunks: Vec<_> = chunks + .iter() + .zip(branches.map(|(proof, _)| proof)) + .enumerate() + .map(|(index, (chunk, proof))| ErasureChunk { chunk: chunk.clone(), proof, - index: ValidatorIndex(index as u32), - }, - ); + index: ChunkIndex(index as u32), + }) + .collect(); - for chunk in erasure_chunks { - write_chunk(&mut tx, &subsystem.config, &candidate_hash, chunk.index, &chunk); + let chunk_indices = availability_chunk_indices(Some(&node_features), n_validators, core_index)?; + for (validator_index, chunk_index) in chunk_indices.into_iter().enumerate() { + write_chunk( + &mut tx, + &subsystem.config, + &candidate_hash, + ValidatorIndex(validator_index as u32), + &erasure_chunks[chunk_index.0 as usize], + ); } meta.data_available = true; diff --git a/polkadot/node/core/av-store/src/tests.rs b/polkadot/node/core/av-store/src/tests.rs index 652bf2a3fda4822fdae0020bcd48993ed8e771ed..e87f7cc3b8d6cb48c0a12e5f48d810db7cae5024 100644 --- a/polkadot/node/core/av-store/src/tests.rs +++ b/polkadot/node/core/av-store/src/tests.rs @@ -18,6 +18,7 @@ use super::*; use assert_matches::assert_matches; use futures::{channel::oneshot, executor, future, Future}; +use util::availability_chunks::availability_chunk_index; use self::test_helpers::mock::new_leaf; use ::test_helpers::TestCandidateBuilder; @@ -31,7 +32,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{database::Database, TimeoutExt}; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, HeadData, Header, + node_features, CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, HeadData, Header, PersistedValidationData, ValidatorId, }; use sp_keyring::Sr25519Keyring; @@ -272,8 +273,7 @@ fn runtime_api_error_does_not_stop_the_subsystem() { // but that's fine, we're still alive let (tx, rx) = oneshot::channel(); let candidate_hash = CandidateHash(Hash::repeat_byte(33)); - let validator_index = ValidatorIndex(5); - let query_chunk = AvailabilityStoreMessage::QueryChunk(candidate_hash, validator_index, tx); + let query_chunk = AvailabilityStoreMessage::QueryChunk(candidate_hash, 5.into(), tx); overseer_send(&mut virtual_overseer, query_chunk.into()).await; @@ -288,12 +288,13 @@ fn store_chunk_works() { test_harness(TestState::default(), store.clone(), |mut virtual_overseer| async move { let candidate_hash = CandidateHash(Hash::repeat_byte(33)); - let validator_index = ValidatorIndex(5); + let chunk_index = ChunkIndex(5); + let validator_index = ValidatorIndex(2); let n_validators = 10; let chunk = ErasureChunk { chunk: vec![1, 2, 3], - index: validator_index, + index: chunk_index, proof: Proof::try_from(vec![vec![3, 4, 5]]).unwrap(), }; @@ -314,8 +315,12 @@ fn store_chunk_works() { let (tx, rx) = oneshot::channel(); - let chunk_msg = - AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk: chunk.clone(), tx }; + let chunk_msg = AvailabilityStoreMessage::StoreChunk { + candidate_hash, + validator_index, + chunk: chunk.clone(), + tx, + }; overseer_send(&mut virtual_overseer, chunk_msg).await; assert_eq!(rx.await.unwrap(), Ok(())); @@ -336,18 +341,23 @@ fn store_chunk_does_nothing_if_no_entry_already() { test_harness(TestState::default(), store.clone(), |mut virtual_overseer| async move { let candidate_hash = CandidateHash(Hash::repeat_byte(33)); - let validator_index = ValidatorIndex(5); + let chunk_index = ChunkIndex(5); + let validator_index = ValidatorIndex(2); let chunk = ErasureChunk { chunk: vec![1, 2, 3], - index: validator_index, + index: chunk_index, proof: Proof::try_from(vec![vec![3, 4, 5]]).unwrap(), }; let (tx, rx) = oneshot::channel(); - let chunk_msg = - AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk: chunk.clone(), tx }; + let chunk_msg = AvailabilityStoreMessage::StoreChunk { + candidate_hash, + validator_index, + chunk: chunk.clone(), + tx, + }; overseer_send(&mut virtual_overseer, chunk_msg).await; assert_eq!(rx.await.unwrap(), Err(())); @@ -418,6 +428,8 @@ fn store_available_data_erasure_mismatch() { let candidate_hash = CandidateHash(Hash::repeat_byte(1)); let validator_index = ValidatorIndex(5); let n_validators = 10; + let core_index = CoreIndex(8); + let node_features = NodeFeatures::EMPTY; let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; @@ -431,6 +443,8 @@ fn store_available_data_erasure_mismatch() { candidate_hash, n_validators, available_data: available_data.clone(), + core_index, + node_features, tx, // A dummy erasure root should lead to failure. expected_erasure_root: Hash::default(), @@ -450,97 +464,183 @@ fn store_available_data_erasure_mismatch() { } #[test] -fn store_block_works() { - let store = test_store(); - let test_state = TestState::default(); - test_harness(test_state.clone(), store.clone(), |mut virtual_overseer| async move { - let candidate_hash = CandidateHash(Hash::repeat_byte(1)); - let validator_index = ValidatorIndex(5); - let n_validators = 10; - - let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; - - let available_data = AvailableData { - pov: Arc::new(pov), - validation_data: test_state.persisted_validation_data.clone(), - }; - let (tx, rx) = oneshot::channel(); - - let chunks = erasure::obtain_chunks_v1(10, &available_data).unwrap(); - let mut branches = erasure::branches(chunks.as_ref()); - - let block_msg = AvailabilityStoreMessage::StoreAvailableData { - candidate_hash, - n_validators, - available_data: available_data.clone(), - tx, - expected_erasure_root: branches.root(), - }; - - virtual_overseer.send(FromOrchestra::Communication { msg: block_msg }).await; - assert_eq!(rx.await.unwrap(), Ok(())); - - let pov = query_available_data(&mut virtual_overseer, candidate_hash).await.unwrap(); - assert_eq!(pov, available_data); - - let chunk = query_chunk(&mut virtual_overseer, candidate_hash, validator_index) - .await - .unwrap(); - - let branch = branches.nth(5).unwrap(); - let expected_chunk = ErasureChunk { - chunk: branch.1.to_vec(), - index: ValidatorIndex(5), - proof: Proof::try_from(branch.0).unwrap(), - }; - - assert_eq!(chunk, expected_chunk); - virtual_overseer - }); -} - -#[test] -fn store_pov_and_query_chunk_works() { - let store = test_store(); - let test_state = TestState::default(); - - test_harness(test_state.clone(), store.clone(), |mut virtual_overseer| async move { - let candidate_hash = CandidateHash(Hash::repeat_byte(1)); - let n_validators = 10; - - let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; - - let available_data = AvailableData { - pov: Arc::new(pov), - validation_data: test_state.persisted_validation_data.clone(), - }; - - let chunks_expected = - erasure::obtain_chunks_v1(n_validators as _, &available_data).unwrap(); - let branches = erasure::branches(chunks_expected.as_ref()); - - let (tx, rx) = oneshot::channel(); - let block_msg = AvailabilityStoreMessage::StoreAvailableData { - candidate_hash, - n_validators, - available_data, - tx, - expected_erasure_root: branches.root(), - }; - - virtual_overseer.send(FromOrchestra::Communication { msg: block_msg }).await; +fn store_pov_and_queries_work() { + // If the AvailabilityChunkMapping feature is not enabled, + // ValidatorIndex->ChunkIndex mapping should be 1:1 for all core indices. + { + let n_cores = 4; + for core_index in 0..n_cores { + let store = test_store(); + let test_state = TestState::default(); + let core_index = CoreIndex(core_index); + + test_harness(test_state.clone(), store.clone(), |mut virtual_overseer| async move { + let node_features = NodeFeatures::EMPTY; + let candidate_hash = CandidateHash(Hash::repeat_byte(1)); + let n_validators = 10; + + let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; + let available_data = AvailableData { + pov: Arc::new(pov), + validation_data: test_state.persisted_validation_data.clone(), + }; + + let chunks = erasure::obtain_chunks_v1(n_validators as _, &available_data).unwrap(); + + let branches = erasure::branches(chunks.as_ref()); + + let (tx, rx) = oneshot::channel(); + let block_msg = AvailabilityStoreMessage::StoreAvailableData { + candidate_hash, + n_validators, + available_data: available_data.clone(), + tx, + core_index, + expected_erasure_root: branches.root(), + node_features: node_features.clone(), + }; + + virtual_overseer.send(FromOrchestra::Communication { msg: block_msg }).await; + assert_eq!(rx.await.unwrap(), Ok(())); + + let pov: AvailableData = + query_available_data(&mut virtual_overseer, candidate_hash).await.unwrap(); + assert_eq!(pov, available_data); + + let query_all_chunks_res = query_all_chunks( + &mut virtual_overseer, + availability_chunk_indices( + Some(&node_features), + n_validators as usize, + core_index, + ) + .unwrap(), + candidate_hash, + ) + .await; + assert_eq!(query_all_chunks_res.len(), chunks.len()); + + let branches: Vec<_> = branches.collect(); + + for validator_index in 0..n_validators { + let chunk = query_chunk( + &mut virtual_overseer, + candidate_hash, + ValidatorIndex(validator_index as _), + ) + .await + .unwrap(); + let branch = &branches[validator_index as usize]; + let expected_chunk = ErasureChunk { + chunk: branch.1.to_vec(), + index: validator_index.into(), + proof: Proof::try_from(branch.0.clone()).unwrap(), + }; + assert_eq!(chunk, expected_chunk); + assert_eq!(chunk, query_all_chunks_res[validator_index as usize]); + } - assert_eq!(rx.await.unwrap(), Ok(())); + virtual_overseer + }); + } + } - for i in 0..n_validators { - let chunk = query_chunk(&mut virtual_overseer, candidate_hash, ValidatorIndex(i as _)) - .await - .unwrap(); + // If the AvailabilityChunkMapping feature is enabled, let's also test the + // ValidatorIndex -> ChunkIndex mapping. + { + let n_cores = 4; + for core_index in 0..n_cores { + let store = test_store(); + let test_state = TestState::default(); + + test_harness(test_state.clone(), store.clone(), |mut virtual_overseer| async move { + let mut node_features = NodeFeatures::EMPTY; + let feature_bit = node_features::FeatureIndex::AvailabilityChunkMapping; + node_features.resize((feature_bit as u8 + 1) as usize, false); + node_features.set(feature_bit as u8 as usize, true); + + let candidate_hash = CandidateHash(Hash::repeat_byte(1)); + let n_validators = 10; + + let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; + let available_data = AvailableData { + pov: Arc::new(pov), + validation_data: test_state.persisted_validation_data.clone(), + }; + + let chunks = erasure::obtain_chunks_v1(n_validators as _, &available_data).unwrap(); + + let branches = erasure::branches(chunks.as_ref()); + let core_index = CoreIndex(core_index); + + let (tx, rx) = oneshot::channel(); + let block_msg = AvailabilityStoreMessage::StoreAvailableData { + candidate_hash, + n_validators, + available_data: available_data.clone(), + tx, + core_index, + expected_erasure_root: branches.root(), + node_features: node_features.clone(), + }; + + virtual_overseer.send(FromOrchestra::Communication { msg: block_msg }).await; + assert_eq!(rx.await.unwrap(), Ok(())); + + let pov: AvailableData = + query_available_data(&mut virtual_overseer, candidate_hash).await.unwrap(); + assert_eq!(pov, available_data); + + let query_all_chunks_res = query_all_chunks( + &mut virtual_overseer, + availability_chunk_indices( + Some(&node_features), + n_validators as usize, + core_index, + ) + .unwrap(), + candidate_hash, + ) + .await; + assert_eq!(query_all_chunks_res.len(), chunks.len()); + + let branches: Vec<_> = branches.collect(); + + for validator_index in 0..n_validators { + let chunk = query_chunk( + &mut virtual_overseer, + candidate_hash, + ValidatorIndex(validator_index as _), + ) + .await + .unwrap(); + let expected_chunk_index = availability_chunk_index( + Some(&node_features), + n_validators as usize, + core_index, + ValidatorIndex(validator_index), + ) + .unwrap(); + let branch = &branches[expected_chunk_index.0 as usize]; + let expected_chunk = ErasureChunk { + chunk: branch.1.to_vec(), + index: expected_chunk_index, + proof: Proof::try_from(branch.0.clone()).unwrap(), + }; + assert_eq!(chunk, expected_chunk); + assert_eq!( + &chunk, + query_all_chunks_res + .iter() + .find(|c| c.index == expected_chunk_index) + .unwrap() + ); + } - assert_eq!(chunk.chunk, chunks_expected[i as usize]); + virtual_overseer + }); } - virtual_overseer - }); + } } #[test] @@ -575,6 +675,8 @@ fn query_all_chunks_works() { n_validators, available_data, tx, + core_index: CoreIndex(1), + node_features: NodeFeatures::EMPTY, expected_erasure_root: branches.root(), }; @@ -598,7 +700,7 @@ fn query_all_chunks_works() { let chunk = ErasureChunk { chunk: vec![1, 2, 3], - index: ValidatorIndex(1), + index: ChunkIndex(1), proof: Proof::try_from(vec![vec![3, 4, 5]]).unwrap(), }; @@ -606,6 +708,7 @@ fn query_all_chunks_works() { let store_chunk_msg = AvailabilityStoreMessage::StoreChunk { candidate_hash: candidate_hash_2, chunk, + validator_index: ValidatorIndex(1), tx, }; @@ -615,29 +718,29 @@ fn query_all_chunks_works() { assert_eq!(rx.await.unwrap(), Ok(())); } - { - let (tx, rx) = oneshot::channel(); + let chunk_indices = + availability_chunk_indices(None, n_validators as usize, CoreIndex(0)).unwrap(); - let msg = AvailabilityStoreMessage::QueryAllChunks(candidate_hash_1, tx); - virtual_overseer.send(FromOrchestra::Communication { msg }).await; - assert_eq!(rx.await.unwrap().len(), n_validators as usize); - } - - { - let (tx, rx) = oneshot::channel(); - - let msg = AvailabilityStoreMessage::QueryAllChunks(candidate_hash_2, tx); - virtual_overseer.send(FromOrchestra::Communication { msg }).await; - assert_eq!(rx.await.unwrap().len(), 1); - } + assert_eq!( + query_all_chunks(&mut virtual_overseer, chunk_indices.clone(), candidate_hash_1) + .await + .len(), + n_validators as usize + ); - { - let (tx, rx) = oneshot::channel(); + assert_eq!( + query_all_chunks(&mut virtual_overseer, chunk_indices.clone(), candidate_hash_2) + .await + .len(), + 1 + ); + assert_eq!( + query_all_chunks(&mut virtual_overseer, chunk_indices.clone(), candidate_hash_3) + .await + .len(), + 0 + ); - let msg = AvailabilityStoreMessage::QueryAllChunks(candidate_hash_3, tx); - virtual_overseer.send(FromOrchestra::Communication { msg }).await; - assert_eq!(rx.await.unwrap().len(), 0); - } virtual_overseer }); } @@ -667,6 +770,8 @@ fn stored_but_not_included_data_is_pruned() { n_validators, available_data: available_data.clone(), tx, + node_features: NodeFeatures::EMPTY, + core_index: CoreIndex(1), expected_erasure_root: branches.root(), }; @@ -723,6 +828,8 @@ fn stored_data_kept_until_finalized() { n_validators, available_data: available_data.clone(), tx, + node_features: NodeFeatures::EMPTY, + core_index: CoreIndex(1), expected_erasure_root: branches.root(), }; @@ -998,6 +1105,8 @@ fn forkfullness_works() { n_validators, available_data: available_data_1.clone(), tx, + node_features: NodeFeatures::EMPTY, + core_index: CoreIndex(1), expected_erasure_root: branches.root(), }; @@ -1014,6 +1123,8 @@ fn forkfullness_works() { n_validators, available_data: available_data_2.clone(), tx, + node_features: NodeFeatures::EMPTY, + core_index: CoreIndex(1), expected_erasure_root: branches.root(), }; @@ -1126,6 +1237,25 @@ async fn query_chunk( rx.await.unwrap() } +async fn query_all_chunks( + virtual_overseer: &mut VirtualOverseer, + chunk_mapping: Vec, + candidate_hash: CandidateHash, +) -> Vec { + let (tx, rx) = oneshot::channel(); + + let msg = AvailabilityStoreMessage::QueryAllChunks(candidate_hash, tx); + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + + let resp = rx.await.unwrap(); + resp.into_iter() + .map(|(val_idx, chunk)| { + assert_eq!(chunk.index, chunk_mapping[val_idx.0 as usize]); + chunk + }) + .collect() +} + async fn has_all_chunks( virtual_overseer: &mut VirtualOverseer, candidate_hash: CandidateHash, @@ -1206,12 +1336,12 @@ fn query_chunk_size_works() { test_harness(TestState::default(), store.clone(), |mut virtual_overseer| async move { let candidate_hash = CandidateHash(Hash::repeat_byte(33)); - let validator_index = ValidatorIndex(5); + let chunk_index = ChunkIndex(5); let n_validators = 10; let chunk = ErasureChunk { chunk: vec![1, 2, 3], - index: validator_index, + index: chunk_index, proof: Proof::try_from(vec![vec![3, 4, 5]]).unwrap(), }; @@ -1232,8 +1362,12 @@ fn query_chunk_size_works() { let (tx, rx) = oneshot::channel(); - let chunk_msg = - AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk: chunk.clone(), tx }; + let chunk_msg = AvailabilityStoreMessage::StoreChunk { + candidate_hash, + chunk: chunk.clone(), + tx, + validator_index: chunk_index.into(), + }; overseer_send(&mut virtual_overseer, chunk_msg).await; assert_eq!(rx.await.unwrap(), Ok(())); diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index 26fa54470fbda6c1e5a22999a34022173b003fe6..f426f73284e8c36d7bc11eef051c8dddbbf40518 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -21,7 +21,7 @@ statement-table = { package = "polkadot-statement-table", path = "../../../state bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } gum = { package = "tracing-gum", path = "../../gum" } thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" schnellru = "0.2.1" [dev-dependencies] diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 23acb0450944e8eedea437da545830174ed84449..2fa8ad29efe5fbddafeb4f212161ed8f7ee2ac9c 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -30,7 +30,7 @@ //! assigned group of validators may be backed on-chain and proceed to the availability //! stage. //! -//! Depth is a concept relating to asynchronous backing, by which validators +//! Depth is a concept relating to asynchronous backing, by which //! short sub-chains of candidates are backed and extended off-chain, and then placed //! asynchronously into blocks of the relay chain as those are authored and as the //! relay-chain state becomes ready for them. Asynchronous backing allows parachains to @@ -66,7 +66,7 @@ #![deny(unused_crate_dependencies)] use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{HashMap, HashSet}, sync::Arc, }; @@ -88,7 +88,7 @@ use polkadot_node_subsystem::{ messages::{ AvailabilityDistributionMessage, AvailabilityStoreMessage, CanSecondRequest, CandidateBackingMessage, CandidateValidationMessage, CollatorProtocolMessage, - HypotheticalCandidate, HypotheticalFrontierRequest, IntroduceCandidateRequest, + HypotheticalCandidate, HypotheticalMembershipRequest, IntroduceSecondedCandidateRequest, ProspectiveParachainsMessage, ProvisionableData, ProvisionerMessage, RuntimeApiMessage, RuntimeApiRequest, StatementDistributionMessage, StoreAvailableDataError, }, @@ -210,6 +210,8 @@ struct PerRelayParentState { prospective_parachains_mode: ProspectiveParachainsMode, /// The hash of the relay parent on top of which this job is doing it's work. parent: Hash, + /// Session index. + session_index: SessionIndex, /// The `ParaId` assigned to the local validator at this relay parent. assigned_para: Option, /// The `CoreIndex` assigned to the local validator at this relay parent. @@ -242,20 +244,44 @@ struct PerRelayParentState { struct PerCandidateState { persisted_validation_data: PersistedValidationData, seconded_locally: bool, - para_id: ParaId, relay_parent: Hash, } -struct ActiveLeafState { - prospective_parachains_mode: ProspectiveParachainsMode, - /// The candidates seconded at various depths under this active - /// leaf with respect to parachain id. A candidate can only be - /// seconded when its hypothetical frontier under every active leaf - /// has an empty entry in this map. - /// - /// When prospective parachains are disabled, the only depth - /// which is allowed is 0. - seconded_at_depth: HashMap>, +enum ActiveLeafState { + // If prospective-parachains is disabled, one validator may only back one candidate per + // paraid. + ProspectiveParachainsDisabled { seconded: HashSet }, + ProspectiveParachainsEnabled { max_candidate_depth: usize, allowed_ancestry_len: usize }, +} + +impl ActiveLeafState { + fn new(mode: ProspectiveParachainsMode) -> Self { + match mode { + ProspectiveParachainsMode::Disabled => + Self::ProspectiveParachainsDisabled { seconded: HashSet::new() }, + ProspectiveParachainsMode::Enabled { max_candidate_depth, allowed_ancestry_len } => + Self::ProspectiveParachainsEnabled { max_candidate_depth, allowed_ancestry_len }, + } + } + + fn add_seconded_candidate(&mut self, para_id: ParaId) { + if let Self::ProspectiveParachainsDisabled { seconded } = self { + seconded.insert(para_id); + } + } +} + +impl From<&ActiveLeafState> for ProspectiveParachainsMode { + fn from(state: &ActiveLeafState) -> Self { + match *state { + ActiveLeafState::ProspectiveParachainsDisabled { .. } => + ProspectiveParachainsMode::Disabled, + ActiveLeafState::ProspectiveParachainsEnabled { + max_candidate_depth, + allowed_ancestry_len, + } => ProspectiveParachainsMode::Enabled { max_candidate_depth, allowed_ancestry_len }, + } + } } /// The state of the subsystem. @@ -277,11 +303,11 @@ struct State { /// parachains. /// /// Relay-chain blocks which don't support prospective parachains are - /// never included in the fragment trees of active leaves which do. + /// never included in the fragment chains of active leaves which do. /// /// While it would be technically possible to support such leaves in - /// fragment trees, it only benefits the transition period when asynchronous - /// backing is being enabled and complicates code complexity. + /// fragment chains, it only benefits the transition period when asynchronous + /// backing is being enabled and complicates code. per_relay_parent: HashMap, /// State tracked for all candidates relevant to the implicit view. /// @@ -510,6 +536,8 @@ async fn store_available_data( candidate_hash: CandidateHash, available_data: AvailableData, expected_erasure_root: Hash, + core_index: CoreIndex, + node_features: NodeFeatures, ) -> Result<(), Error> { let (tx, rx) = oneshot::channel(); // Important: the `av-store` subsystem will check if the erasure root of the `available_data` @@ -522,6 +550,8 @@ async fn store_available_data( n_validators, available_data, expected_erasure_root, + core_index, + node_features, tx, }) .await; @@ -545,6 +575,8 @@ async fn make_pov_available( candidate_hash: CandidateHash, validation_data: PersistedValidationData, expected_erasure_root: Hash, + core_index: CoreIndex, + node_features: NodeFeatures, ) -> Result<(), Error> { store_available_data( sender, @@ -552,6 +584,8 @@ async fn make_pov_available( candidate_hash, AvailableData { pov, validation_data }, expected_erasure_root, + core_index, + node_features, ) .await } @@ -622,6 +656,7 @@ struct BackgroundValidationParams { tx_command: mpsc::Sender<(Hash, ValidatedCandidateCommand)>, candidate: CandidateReceipt, relay_parent: Hash, + session_index: SessionIndex, persisted_validation_data: PersistedValidationData, pov: PoVData, n_validators: usize, @@ -633,12 +668,14 @@ async fn validate_and_make_available( impl overseer::CandidateBackingSenderTrait, impl Fn(BackgroundValidationResult) -> ValidatedCandidateCommand + Sync, >, + core_index: CoreIndex, ) -> Result<(), Error> { let BackgroundValidationParams { mut sender, mut tx_command, candidate, relay_parent, + session_index, persisted_validation_data, pov, n_validators, @@ -668,6 +705,10 @@ async fn validate_and_make_available( Err(e) => return Err(Error::UtilError(e)), }; + let node_features = request_node_features(relay_parent, session_index, &mut sender) + .await? + .unwrap_or(NodeFeatures::EMPTY); + let pov = match pov { PoVData::Ready(pov) => pov, PoVData::FetchFromValidator { from_validator, candidate_hash, pov_hash } => @@ -723,6 +764,8 @@ async fn validate_and_make_available( candidate.hash(), validation_data.clone(), candidate.descriptor.erasure_root, + core_index, + node_features, ) .await; @@ -864,17 +907,9 @@ async fn handle_active_leaves_update( return Ok(()) } - state.per_leaf.insert( - leaf.hash, - ActiveLeafState { - prospective_parachains_mode: ProspectiveParachainsMode::Disabled, - // This is empty because the only allowed relay-parent and depth - // when prospective parachains are disabled is the leaf hash and 0, - // respectively. We've just learned about the leaf hash, so we cannot - // have any candidates seconded with it as a relay-parent yet. - seconded_at_depth: HashMap::new(), - }, - ); + state + .per_leaf + .insert(leaf.hash, ActiveLeafState::new(ProspectiveParachainsMode::Disabled)); (vec![leaf.hash], ProspectiveParachainsMode::Disabled) }, @@ -882,63 +917,9 @@ async fn handle_active_leaves_update( let fresh_relay_parents = state.implicit_view.known_allowed_relay_parents_under(&leaf.hash, None); - // At this point, all candidates outside of the implicit view - // have been cleaned up. For all which remain, which we've seconded, - // we ask the prospective parachains subsystem where they land in the fragment - // tree for the given active leaf. This comprises our `seconded_at_depth`. - - let remaining_seconded = state - .per_candidate - .iter() - .filter(|(_, cd)| cd.seconded_locally) - .map(|(c_hash, cd)| (*c_hash, cd.para_id)); - - // one-to-one correspondence to remaining_seconded - let mut membership_answers = FuturesOrdered::new(); - - for (candidate_hash, para_id) in remaining_seconded { - let (tx, rx) = oneshot::channel(); - membership_answers - .push_back(rx.map_ok(move |membership| (para_id, candidate_hash, membership))); - - ctx.send_message(ProspectiveParachainsMessage::GetTreeMembership( - para_id, - candidate_hash, - tx, - )) - .await; - } - - let mut seconded_at_depth = HashMap::new(); - while let Some(response) = membership_answers.next().await { - match response { - Err(oneshot::Canceled) => { - gum::warn!( - target: LOG_TARGET, - "Prospective parachains subsystem unreachable for membership request", - ); - }, - Ok((para_id, candidate_hash, membership)) => { - // This request gives membership in all fragment trees. We have some - // wasted data here, and it can be optimized if it proves - // relevant to performance. - if let Some((_, depths)) = - membership.into_iter().find(|(leaf_hash, _)| leaf_hash == &leaf.hash) - { - let para_entry: &mut BTreeMap = - seconded_at_depth.entry(para_id).or_default(); - for depth in depths { - para_entry.insert(depth, candidate_hash); - } - } - }, - } - } + let active_leaf_state = ActiveLeafState::new(prospective_parachains_mode); - state.per_leaf.insert( - leaf.hash, - ActiveLeafState { prospective_parachains_mode, seconded_at_depth }, - ); + state.per_leaf.insert(leaf.hash, active_leaf_state); let fresh_relay_parent = match fresh_relay_parents { Some(f) => f.to_vec(), @@ -981,7 +962,7 @@ async fn handle_active_leaves_update( // block itself did. leaf_mode }, - Some(l) => l.prospective_parachains_mode, + Some(l) => l.into(), }; // construct a `PerRelayParent` from the runtime API @@ -1229,6 +1210,7 @@ async fn construct_per_relay_parent_state( Ok(Some(PerRelayParentState { prospective_parachains_mode: mode, parent, + session_index, assigned_core, assigned_para, backed: HashSet::new(), @@ -1247,20 +1229,20 @@ async fn construct_per_relay_parent_state( enum SecondingAllowed { No, - Yes(Vec<(Hash, Vec)>), + // On which leaves is seconding allowed. + Yes(Vec), } -/// Checks whether a candidate can be seconded based on its hypothetical frontiers in the fragment -/// tree and what we've already seconded in all active leaves. +/// Checks whether a candidate can be seconded based on its hypothetical membership in the fragment +/// chain. #[overseer::contextbounds(CandidateBacking, prefix = self::overseer)] async fn seconding_sanity_check( ctx: &mut Context, active_leaves: &HashMap, implicit_view: &ImplicitView, hypothetical_candidate: HypotheticalCandidate, - backed_in_path_only: bool, ) -> SecondingAllowed { - let mut membership = Vec::new(); + let mut leaves_for_seconding = Vec::new(); let mut responses = FuturesOrdered::>>::new(); let candidate_para = hypothetical_candidate.candidate_para(); @@ -1268,7 +1250,7 @@ async fn seconding_sanity_check( let candidate_hash = hypothetical_candidate.candidate_hash(); for (head, leaf_state) in active_leaves { - if leaf_state.prospective_parachains_mode.is_enabled() { + if ProspectiveParachainsMode::from(leaf_state).is_enabled() { // Check that the candidate relay parent is allowed for para, skip the // leaf otherwise. let allowed_parents_for_para = @@ -1278,40 +1260,36 @@ async fn seconding_sanity_check( } let (tx, rx) = oneshot::channel(); - ctx.send_message(ProspectiveParachainsMessage::GetHypotheticalFrontier( - HypotheticalFrontierRequest { + ctx.send_message(ProspectiveParachainsMessage::GetHypotheticalMembership( + HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(*head), - backed_in_path_only, + fragment_chain_relay_parent: Some(*head), }, tx, )) .await; - let response = rx.map_ok(move |frontiers| { - let depths: Vec = frontiers + let response = rx.map_ok(move |candidate_memberships| { + let is_member_or_potential = candidate_memberships .into_iter() - .flat_map(|(candidate, memberships)| { - debug_assert_eq!(candidate.candidate_hash(), candidate_hash); - memberships.into_iter().flat_map(|(relay_parent, depths)| { - debug_assert_eq!(relay_parent, *head); - depths - }) + .find_map(|(candidate, leaves)| { + (candidate.candidate_hash() == candidate_hash).then_some(leaves) }) - .collect(); - (depths, head, leaf_state) + .and_then(|leaves| leaves.into_iter().find(|leaf| leaf == head)) + .is_some(); + + (is_member_or_potential, head) }); responses.push_back(response.boxed()); } else { if *head == candidate_relay_parent { - if leaf_state - .seconded_at_depth - .get(&candidate_para) - .map_or(false, |occupied| occupied.contains_key(&0)) - { - // The leaf is already occupied. - return SecondingAllowed::No + if let ActiveLeafState::ProspectiveParachainsDisabled { seconded } = leaf_state { + if seconded.contains(&candidate_para) { + // The leaf is already occupied. For non-prospective parachains, we only + // second one candidate. + return SecondingAllowed::No + } } - responses.push_back(futures::future::ok((vec![0], head, leaf_state)).boxed()); + responses.push_back(futures::future::ok((true, head)).boxed()); } } } @@ -1325,38 +1303,32 @@ async fn seconding_sanity_check( Err(oneshot::Canceled) => { gum::warn!( target: LOG_TARGET, - "Failed to reach prospective parachains subsystem for hypothetical frontiers", + "Failed to reach prospective parachains subsystem for hypothetical membership", ); return SecondingAllowed::No }, - Ok((depths, head, leaf_state)) => { - for depth in &depths { - if leaf_state - .seconded_at_depth - .get(&candidate_para) - .map_or(false, |occupied| occupied.contains_key(&depth)) - { - gum::debug!( - target: LOG_TARGET, - ?candidate_hash, - depth, - leaf_hash = ?head, - "Refusing to second candidate at depth - already occupied." - ); - - return SecondingAllowed::No - } - } - - membership.push((*head, depths)); + Ok((is_member_or_potential, head)) => match is_member_or_potential { + false => { + gum::debug!( + target: LOG_TARGET, + ?candidate_hash, + leaf_hash = ?head, + "Refusing to second candidate at leaf. Is not a potential member.", + ); + }, + true => { + leaves_for_seconding.push(*head); + }, }, } } - // At this point we've checked the depths of the candidate against all active - // leaves. - SecondingAllowed::Yes(membership) + if leaves_for_seconding.is_empty() { + SecondingAllowed::No + } else { + SecondingAllowed::Yes(leaves_for_seconding) + } } /// Performs seconding sanity check for an advertisement. @@ -1385,16 +1357,12 @@ async fn handle_can_second_request( &state.per_leaf, &state.implicit_view, hypothetical_candidate, - true, ) .await; match result { SecondingAllowed::No => false, - SecondingAllowed::Yes(membership) => { - // Candidate should be recognized by at least some fragment tree. - membership.iter().any(|(_, m)| !m.is_empty()) - }, + SecondingAllowed::Yes(leaves) => !leaves.is_empty(), } } else { // Relay parent is unknown or async backing is disabled. @@ -1435,20 +1403,6 @@ async fn handle_validated_candidate_command( commitments, }; - let parent_head_data_hash = persisted_validation_data.parent_head.hash(); - // Note that `GetHypotheticalFrontier` doesn't account for recursion, - // i.e. candidates can appear at multiple depths in the tree and in fact - // at all depths, and we don't know what depths a candidate will ultimately - // occupy because that's dependent on other candidates we haven't yet - // received. - // - // The only way to effectively rule this out is to have candidate receipts - // directly commit to the parachain block number or some other incrementing - // counter. That requires a major primitives format upgrade, so for now - // we just rule out trivial cycles. - if parent_head_data_hash == receipt.commitments.head_data.hash() { - return Ok(()) - } let hypothetical_candidate = HypotheticalCandidate::Complete { candidate_hash, receipt: Arc::new(receipt.clone()), @@ -1457,12 +1411,11 @@ async fn handle_validated_candidate_command( // sanity check that we're allowed to second the candidate // and that it doesn't conflict with other candidates we've // seconded. - let fragment_tree_membership = match seconding_sanity_check( + let hypothetical_membership = match seconding_sanity_check( ctx, &state.per_leaf, &state.implicit_view, hypothetical_candidate, - false, ) .await { @@ -1517,8 +1470,8 @@ async fn handle_validated_candidate_command( Some(p) => p.seconded_locally = true, } - // update seconded depths in active leaves. - for (leaf, depths) in fragment_tree_membership { + // record seconded candidates for non-prospective-parachains mode. + for leaf in hypothetical_membership { let leaf_data = match state.per_leaf.get_mut(&leaf) { None => { gum::warn!( @@ -1532,14 +1485,7 @@ async fn handle_validated_candidate_command( Some(d) => d, }; - let seconded_at_depth = leaf_data - .seconded_at_depth - .entry(candidate.descriptor().para_id) - .or_default(); - - for depth in depths { - seconded_at_depth.insert(depth, candidate_hash); - } + leaf_data.add_seconded_candidate(candidate.descriptor().para_id); } rp_state.issued_statements.insert(candidate_hash); @@ -1650,7 +1596,7 @@ fn sign_statement( /// and any of the following are true: /// 1. There is no `PersistedValidationData` attached. /// 2. Prospective parachains are enabled for the relay parent and the prospective parachains -/// subsystem returned an empty `FragmentTreeMembership` i.e. did not recognize the candidate as +/// subsystem returned an empty `HypotheticalMembership` i.e. did not recognize the candidate as /// being applicable to any of the active leaves. #[overseer::contextbounds(CandidateBacking, prefix = self::overseer)] async fn import_statement( @@ -1686,8 +1632,8 @@ async fn import_statement( if !per_candidate.contains_key(&candidate_hash) { if rp_state.prospective_parachains_mode.is_enabled() { let (tx, rx) = oneshot::channel(); - ctx.send_message(ProspectiveParachainsMessage::IntroduceCandidate( - IntroduceCandidateRequest { + ctx.send_message(ProspectiveParachainsMessage::IntroduceSecondedCandidate( + IntroduceSecondedCandidateRequest { candidate_para: candidate.descriptor().para_id, candidate_receipt: candidate.clone(), persisted_validation_data: pvd.clone(), @@ -1705,17 +1651,9 @@ async fn import_statement( return Err(Error::RejectedByProspectiveParachains) }, - Ok(membership) => - if membership.is_empty() { - return Err(Error::RejectedByProspectiveParachains) - }, + Ok(false) => return Err(Error::RejectedByProspectiveParachains), + Ok(true) => {}, } - - ctx.send_message(ProspectiveParachainsMessage::CandidateSeconded( - candidate.descriptor().para_id, - candidate_hash, - )) - .await; } // Only save the candidate if it was approved by prospective parachains. @@ -1725,7 +1663,6 @@ async fn import_statement( persisted_validation_data: pvd.clone(), // This is set after importing when seconding locally. seconded_locally: false, - para_id: candidate.descriptor().para_id, relay_parent: candidate.descriptor().relay_parent, }, ); @@ -1786,13 +1723,6 @@ async fn post_import_statement_actions( candidate_hash, )) .await; - // Backed candidate potentially unblocks new advertisements, - // notify collator protocol. - ctx.send_message(CollatorProtocolMessage::Backed { - para_id, - para_head: backed.candidate().descriptor.para_head, - }) - .await; // Notify statement distribution of backed candidate. ctx.send_message(StatementDistributionMessage::Backed(candidate_hash)).await; } else { @@ -1878,10 +1808,11 @@ async fn background_validate_and_make_available( >, ) -> Result<(), Error> { let candidate_hash = params.candidate.hash(); + let Some(core_index) = rp_state.assigned_core else { return Ok(()) }; if rp_state.awaiting_validation.insert(candidate_hash) { // spawn background task. let bg = async move { - if let Err(error) = validate_and_make_available(params).await { + if let Err(error) = validate_and_make_available(params, core_index).await { if let Error::BackgroundValidationMpsc(error) = error { gum::debug!( target: LOG_TARGET, @@ -1956,6 +1887,7 @@ async fn kick_off_validation_work( tx_command: background_validation_tx.clone(), candidate: attesting.candidate, relay_parent: rp_state.parent, + session_index: rp_state.session_index, persisted_validation_data, pov, n_validators: rp_state.table_context.validators.len(), @@ -2016,7 +1948,7 @@ async fn maybe_validate_and_import( if let Some(summary) = summary { // import_statement already takes care of communicating with the // prospective parachains subsystem. At this point, the candidate - // has already been accepted into the fragment trees. + // has already been accepted by the subsystem. let candidate_hash = summary.candidate; @@ -2109,6 +2041,7 @@ async fn validate_and_second( tx_command: background_validation_tx.clone(), candidate: candidate.clone(), relay_parent: rp_state.parent, + session_index: rp_state.session_index, persisted_validation_data, pov: PoVData::Ready(pov), n_validators: rp_state.table_context.validators.len(), @@ -2174,8 +2107,7 @@ async fn handle_second_message( collation = ?candidate.descriptor().para_id, "Subsystem asked to second for para outside of our assignment", ); - - return Ok(()) + return Ok(()); } gum::debug!( diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index d1969e656db673b70b070c9b708bab867bec9fcb..00f9e4cd8ff688af3e3b7144cb9801a6eef42044 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -367,6 +367,15 @@ async fn assert_validation_requests( tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); } ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(sess_idx, tx)) + ) if sess_idx == 1 => { + tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); + } + ); } async fn assert_validate_from_exhaustive( @@ -2084,7 +2093,7 @@ fn retry_works() { virtual_overseer.send(FromOrchestra::Communication { msg: statement }).await; // Not deterministic which message comes first: - for _ in 0u32..5 { + for _ in 0u32..6 { match virtual_overseer.recv().await { AllMessages::Provisioner(ProvisionerMessage::ProvisionableData( _, @@ -2115,6 +2124,12 @@ fn retry_works() { )) => { tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); }, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::NodeFeatures(1, tx), + )) => { + tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); + }, msg => { assert!(false, "Unexpected message: {:?}", msg); }, @@ -2662,32 +2677,7 @@ fn validator_ignores_statements_from_disabled_validators() { virtual_overseer.send(FromOrchestra::Communication { msg: statement_3 }).await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::ValidationCodeByHash(hash, tx)) - ) if hash == validation_code.hash() => { - tx.send(Ok(Some(validation_code.clone()))).unwrap(); - } - ); - - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx)) - ) => { - tx.send(Ok(1u32.into())).unwrap(); - } - ); - - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionExecutorParams(sess_idx, tx)) - ) if sess_idx == 1 => { - tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); - } - ); + assert_validation_requests(&mut virtual_overseer, validation_code.clone()).await; // Sending a `Statement::Seconded` for our assignment will start // validation process. The first thing requested is the PoV. diff --git a/polkadot/node/core/backing/src/tests/prospective_parachains.rs b/polkadot/node/core/backing/src/tests/prospective_parachains.rs index 94310d2aa164650db84b78ddf361a9f465ac207d..5ef3a3b15285cc1e30577cd1abf5048b9da0b131 100644 --- a/polkadot/node/core/backing/src/tests/prospective_parachains.rs +++ b/polkadot/node/core/backing/src/tests/prospective_parachains.rs @@ -17,7 +17,7 @@ //! Tests for the backing subsystem with enabled prospective parachains. use polkadot_node_subsystem::{ - messages::{ChainApiMessage, FragmentTreeMembership}, + messages::{ChainApiMessage, HypotheticalMembership}, ActivatedLeaf, TimeoutExt, }; use polkadot_primitives::{AsyncBackingParams, BlockNumber, Header, OccupiedCore}; @@ -40,7 +40,6 @@ async fn activate_leaf( virtual_overseer: &mut VirtualOverseer, leaf: TestLeaf, test_state: &TestState, - seconded_in_view: usize, ) { let TestLeaf { activated, min_relay_parents } = leaf; let leaf_hash = activated.hash; @@ -68,15 +67,6 @@ async fn activate_leaf( .min() .unwrap_or(&leaf_number); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx) - ) if parent == leaf_hash => { - tx.send(min_relay_parents).unwrap(); - } - ); - let ancestry_len = leaf_number + 1 - min_min; let ancestry_hashes = std::iter::successors(Some(leaf_hash), |h| Some(get_parent_hash(*h))) @@ -118,23 +108,20 @@ async fn activate_leaf( tx.send(Ok(Some(header))).unwrap(); } ); - requested_len += 1; - } - } - for _ in 0..seconded_in_view { - let msg = match next_overseer_message.take() { - Some(msg) => msg, - None => virtual_overseer.recv().await, - }; - assert_matches!( - msg, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetTreeMembership(.., tx), - ) => { - tx.send(Vec::new()).unwrap(); + if requested_len == 0 { + assert_matches!( + virtual_overseer.recv().await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx) + ) if parent == leaf_hash => { + tx.send(min_relay_parents.clone()).unwrap(); + } + ); } - ); + + requested_len += 1; + } } for (hash, number) in ancestry_iter.take(requested_len) { @@ -297,11 +284,11 @@ async fn assert_validate_seconded_candidate( ); } -async fn assert_hypothetical_frontier_requests( +async fn assert_hypothetical_membership_requests( virtual_overseer: &mut VirtualOverseer, mut expected_requests: Vec<( - HypotheticalFrontierRequest, - Vec<(HypotheticalCandidate, FragmentTreeMembership)>, + HypotheticalMembershipRequest, + Vec<(HypotheticalCandidate, HypotheticalMembership)>, )>, ) { // Requests come with no particular order. @@ -311,13 +298,13 @@ async fn assert_hypothetical_frontier_requests( assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetHypotheticalFrontier(request, tx), + ProspectiveParachainsMessage::GetHypotheticalMembership(request, tx), ) => { let idx = match expected_requests.iter().position(|r| r.0 == request) { Some(idx) => idx, None => panic!( - "unexpected hypothetical frontier request, no match found for {:?}", + "unexpected hypothetical membership request, no match found for {:?}", request ), }; @@ -330,18 +317,17 @@ async fn assert_hypothetical_frontier_requests( } } -fn make_hypothetical_frontier_response( - depths: Vec, +fn make_hypothetical_membership_response( hypothetical_candidate: HypotheticalCandidate, relay_parent_hash: Hash, -) -> Vec<(HypotheticalCandidate, FragmentTreeMembership)> { - vec![(hypothetical_candidate, vec![(relay_parent_hash, depths)])] +) -> Vec<(HypotheticalCandidate, HypotheticalMembership)> { + vec![(hypothetical_candidate, vec![relay_parent_hash])] } // Test that `seconding_sanity_check` works when a candidate is allowed // for all leaves. #[test] -fn seconding_sanity_check_allowed() { +fn seconding_sanity_check_allowed_on_all() { let test_state = TestState::default(); test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move { // Candidate is seconded in a parent of the activated `leaf_a`. @@ -364,8 +350,8 @@ fn seconding_sanity_check_allowed() { let min_relay_parents = vec![(para_id, LEAF_B_BLOCK_NUMBER - LEAF_B_ANCESTRY_LEN)]; let test_leaf_b = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; - activate_leaf(&mut virtual_overseer, test_leaf_b, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; + activate_leaf(&mut virtual_overseer, test_leaf_b, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -412,24 +398,19 @@ fn seconding_sanity_check_allowed() { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }; - let expected_request_a = HypotheticalFrontierRequest { + let expected_request_a = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_a_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_a_hash), }; - let expected_response_a = make_hypothetical_frontier_response( - vec![0, 1, 2, 3], - hypothetical_candidate.clone(), - leaf_a_hash, - ); - let expected_request_b = HypotheticalFrontierRequest { + let expected_response_a = + make_hypothetical_membership_response(hypothetical_candidate.clone(), leaf_a_hash); + let expected_request_b = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_b_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_b_hash), }; let expected_response_b = - make_hypothetical_frontier_response(vec![3], hypothetical_candidate, leaf_b_hash); - assert_hypothetical_frontier_requests( + make_hypothetical_membership_response(hypothetical_candidate, leaf_b_hash); + assert_hypothetical_membership_requests( &mut virtual_overseer, vec![ (expected_request_a, expected_response_a), @@ -441,7 +422,7 @@ fn seconding_sanity_check_allowed() { assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -449,19 +430,10 @@ fn seconding_sanity_check_allowed() { req.candidate_receipt == candidate && req.candidate_para == para_id && pvd == req.persisted_validation_data => { - // Any non-empty response will do. - tx.send(vec![(leaf_a_hash, vec![0, 1, 2, 3])]).unwrap(); + tx.send(true).unwrap(); } ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains(ProspectiveParachainsMessage::CandidateSeconded( - _, - _ - )) - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::StatementDistribution( @@ -484,8 +456,8 @@ fn seconding_sanity_check_allowed() { }); } -// Test that `seconding_sanity_check` works when a candidate is disallowed -// for at least one leaf. +// Test that `seconding_sanity_check` disallows seconding when a candidate is disallowed +// for all leaves. #[test] fn seconding_sanity_check_disallowed() { let test_state = TestState::default(); @@ -510,7 +482,7 @@ fn seconding_sanity_check_disallowed() { let min_relay_parents = vec![(para_id, LEAF_B_BLOCK_NUMBER - LEAF_B_ANCESTRY_LEN)]; let test_leaf_b = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -557,17 +529,13 @@ fn seconding_sanity_check_disallowed() { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }; - let expected_request_a = HypotheticalFrontierRequest { + let expected_request_a = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_a_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_a_hash), }; - let expected_response_a = make_hypothetical_frontier_response( - vec![0, 1, 2, 3], - hypothetical_candidate, - leaf_a_hash, - ); - assert_hypothetical_frontier_requests( + let expected_response_a = + make_hypothetical_membership_response(hypothetical_candidate, leaf_a_hash); + assert_hypothetical_membership_requests( &mut virtual_overseer, vec![(expected_request_a, expected_response_a)], ) @@ -576,7 +544,7 @@ fn seconding_sanity_check_disallowed() { assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -584,19 +552,10 @@ fn seconding_sanity_check_disallowed() { req.candidate_receipt == candidate && req.candidate_para == para_id && pvd == req.persisted_validation_data => { - // Any non-empty response will do. - tx.send(vec![(leaf_a_hash, vec![0, 2, 3])]).unwrap(); + tx.send(true).unwrap(); } ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains(ProspectiveParachainsMessage::CandidateSeconded( - _, - _ - )) - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::StatementDistribution( @@ -615,10 +574,7 @@ fn seconding_sanity_check_disallowed() { } ); - // A seconded candidate occupies a depth, try to second another one. - // It is allowed in a new leaf but not allowed in the old one. - // Expect it to be rejected. - activate_leaf(&mut virtual_overseer, test_leaf_b, &test_state, 1).await; + activate_leaf(&mut virtual_overseer, test_leaf_b, &test_state).await; let leaf_a_grandparent = get_parent_hash(leaf_a_parent); let candidate = TestCandidateBuilder { para_id, @@ -659,28 +615,20 @@ fn seconding_sanity_check_disallowed() { receipt: Arc::new(candidate), persisted_validation_data: pvd, }; - let expected_request_a = HypotheticalFrontierRequest { + let expected_request_a = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_a_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_a_hash), }; - let expected_response_a = make_hypothetical_frontier_response( - vec![3], - hypothetical_candidate.clone(), - leaf_a_hash, - ); - let expected_request_b = HypotheticalFrontierRequest { + let expected_empty_response = vec![(hypothetical_candidate.clone(), vec![])]; + let expected_request_b = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_b_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_b_hash), }; - let expected_response_b = - make_hypothetical_frontier_response(vec![1], hypothetical_candidate, leaf_b_hash); - assert_hypothetical_frontier_requests( + assert_hypothetical_membership_requests( &mut virtual_overseer, vec![ - (expected_request_a, expected_response_a), // All depths are occupied. - (expected_request_b, expected_response_b), + (expected_request_a, expected_empty_response.clone()), + (expected_request_b, expected_empty_response), ], ) .await; @@ -695,6 +643,137 @@ fn seconding_sanity_check_disallowed() { }); } +// Test that `seconding_sanity_check` allows seconding a candidate when it's allowed on at least one +// leaf. +#[test] +fn seconding_sanity_check_allowed_on_at_least_one_leaf() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move { + // Candidate is seconded in a parent of the activated `leaf_a`. + const LEAF_A_BLOCK_NUMBER: BlockNumber = 100; + const LEAF_A_ANCESTRY_LEN: BlockNumber = 3; + let para_id = test_state.chain_ids[0]; + + // `a` is grandparent of `b`. + let leaf_a_hash = Hash::from_low_u64_be(130); + let leaf_a_parent = get_parent_hash(leaf_a_hash); + let activated = new_leaf(leaf_a_hash, LEAF_A_BLOCK_NUMBER); + let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; + let test_leaf_a = TestLeaf { activated, min_relay_parents }; + + const LEAF_B_BLOCK_NUMBER: BlockNumber = LEAF_A_BLOCK_NUMBER + 2; + const LEAF_B_ANCESTRY_LEN: BlockNumber = 4; + + let leaf_b_hash = Hash::from_low_u64_be(128); + let activated = new_leaf(leaf_b_hash, LEAF_B_BLOCK_NUMBER); + let min_relay_parents = vec![(para_id, LEAF_B_BLOCK_NUMBER - LEAF_B_ANCESTRY_LEN)]; + let test_leaf_b = TestLeaf { activated, min_relay_parents }; + + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; + activate_leaf(&mut virtual_overseer, test_leaf_b, &test_state).await; + + let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; + let pvd = dummy_pvd(); + let validation_code = ValidationCode(vec![1, 2, 3]); + + let expected_head_data = test_state.head_data.get(¶_id).unwrap(); + + let pov_hash = pov.hash(); + let candidate = TestCandidateBuilder { + para_id, + relay_parent: leaf_a_parent, + pov_hash, + head_data: expected_head_data.clone(), + erasure_root: make_erasure_root(&test_state, pov.clone(), pvd.clone()), + persisted_validation_data_hash: pvd.hash(), + validation_code: validation_code.0.clone(), + } + .build(); + + let second = CandidateBackingMessage::Second( + leaf_a_hash, + candidate.to_plain(), + pvd.clone(), + pov.clone(), + ); + + virtual_overseer.send(FromOrchestra::Communication { msg: second }).await; + + assert_validate_seconded_candidate( + &mut virtual_overseer, + leaf_a_parent, + &candidate, + &pov, + &pvd, + &validation_code, + expected_head_data, + false, + ) + .await; + + // `seconding_sanity_check` + let hypothetical_candidate = HypotheticalCandidate::Complete { + candidate_hash: candidate.hash(), + receipt: Arc::new(candidate.clone()), + persisted_validation_data: pvd.clone(), + }; + let expected_request_a = HypotheticalMembershipRequest { + candidates: vec![hypothetical_candidate.clone()], + fragment_chain_relay_parent: Some(leaf_a_hash), + }; + let expected_response_a = + make_hypothetical_membership_response(hypothetical_candidate.clone(), leaf_a_hash); + let expected_request_b = HypotheticalMembershipRequest { + candidates: vec![hypothetical_candidate.clone()], + fragment_chain_relay_parent: Some(leaf_b_hash), + }; + let expected_response_b = vec![(hypothetical_candidate.clone(), vec![])]; + assert_hypothetical_membership_requests( + &mut virtual_overseer, + vec![ + (expected_request_a, expected_response_a), + (expected_request_b, expected_response_b), + ], + ) + .await; + // Prospective parachains are notified. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( + req, + tx, + ), + ) if + req.candidate_receipt == candidate + && req.candidate_para == para_id + && pvd == req.persisted_validation_data => { + tx.send(true).unwrap(); + } + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + parent_hash, + _signed_statement, + ) + ) if parent_hash == leaf_a_parent => {} + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CollatorProtocol(CollatorProtocolMessage::Seconded(hash, statement)) => { + assert_eq!(leaf_a_parent, hash); + assert_matches!(statement.payload(), Statement::Seconded(_)); + } + ); + + virtual_overseer + }); +} + // Test that a seconded candidate which is not approved by prospective parachains // subsystem doesn't change the view. #[test] @@ -712,7 +791,7 @@ fn prospective_parachains_reject_candidate() { let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -760,25 +839,20 @@ fn prospective_parachains_reject_candidate() { persisted_validation_data: pvd.clone(), }; let expected_request_a = vec![( - HypotheticalFrontierRequest { + HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_a_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_a_hash), }, - make_hypothetical_frontier_response( - vec![0, 1, 2, 3], - hypothetical_candidate, - leaf_a_hash, - ), + make_hypothetical_membership_response(hypothetical_candidate, leaf_a_hash), )]; - assert_hypothetical_frontier_requests(&mut virtual_overseer, expected_request_a.clone()) + assert_hypothetical_membership_requests(&mut virtual_overseer, expected_request_a.clone()) .await; // Prospective parachains are notified. assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -787,7 +861,7 @@ fn prospective_parachains_reject_candidate() { && req.candidate_para == para_id && pvd == req.persisted_validation_data => { // Reject it. - tx.send(Vec::new()).unwrap(); + tx.send(false).unwrap(); } ); @@ -825,12 +899,12 @@ fn prospective_parachains_reject_candidate() { .await; // `seconding_sanity_check` - assert_hypothetical_frontier_requests(&mut virtual_overseer, expected_request_a).await; + assert_hypothetical_membership_requests(&mut virtual_overseer, expected_request_a).await; // Prospective parachains are notified. assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -838,19 +912,10 @@ fn prospective_parachains_reject_candidate() { req.candidate_receipt == candidate && req.candidate_para == para_id && pvd == req.persisted_validation_data => { - // Any non-empty response will do. - tx.send(vec![(leaf_a_hash, vec![0, 2, 3])]).unwrap(); + tx.send(true).unwrap(); } ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains(ProspectiveParachainsMessage::CandidateSeconded( - _, - _ - )) - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::StatementDistribution( @@ -890,7 +955,7 @@ fn second_multiple_candidates_per_relay_parent() { let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -911,12 +976,10 @@ fn second_multiple_candidates_per_relay_parent() { let mut candidate_b = candidate_a.clone(); candidate_b.relay_parent = leaf_grandparent; - // With depths. - let candidate_a = (candidate_a.build(), 1); - let candidate_b = (candidate_b.build(), 2); + let candidate_a = candidate_a.build(); + let candidate_b = candidate_b.build(); for candidate in &[candidate_a, candidate_b] { - let (candidate, depth) = candidate; let second = CandidateBackingMessage::Second( leaf_hash, candidate.to_plain(), @@ -945,46 +1008,33 @@ fn second_multiple_candidates_per_relay_parent() { persisted_validation_data: pvd.clone(), }; let expected_request_a = vec![( - HypotheticalFrontierRequest { + HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_hash), }, - make_hypothetical_frontier_response( - vec![*depth], - hypothetical_candidate, - leaf_hash, - ), + make_hypothetical_membership_response(hypothetical_candidate, leaf_hash), )]; - assert_hypothetical_frontier_requests( + assert_hypothetical_membership_requests( &mut virtual_overseer, expected_request_a.clone(), ) .await; // Prospective parachains are notified. - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( - req, - tx, - ), - ) if - &req.candidate_receipt == candidate - && req.candidate_para == para_id - && pvd == req.persisted_validation_data - => { - // Any non-empty response will do. - tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap(); - } - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::CandidateSeconded(_, _) - ) + ProspectiveParachainsMessage::IntroduceSecondedCandidate( + req, + tx, + ), + ) if + &req.candidate_receipt == candidate + && req.candidate_para == para_id + && pvd == req.persisted_validation_data + => { + tx.send(true).unwrap(); + } ); assert_matches!( @@ -1026,7 +1076,7 @@ fn backing_works() { let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -1048,7 +1098,6 @@ fn backing_works() { .build(); let candidate_a_hash = candidate_a.hash(); - let candidate_a_para_head = candidate_a.descriptor().para_head; let public1 = Keystore::sr25519_generate_new( &*test_state.keystore, @@ -1096,7 +1145,7 @@ fn backing_works() { assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -1104,19 +1153,10 @@ fn backing_works() { req.candidate_receipt == candidate_a && req.candidate_para == para_id && pvd == req.persisted_validation_data => { - // Any non-empty response will do. - tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap(); + tx.send(true).unwrap(); } ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains(ProspectiveParachainsMessage::CandidateSeconded( - _, - _ - )) - ); - assert_validate_seconded_candidate( &mut virtual_overseer, candidate_a.descriptor().relay_parent, @@ -1147,13 +1187,6 @@ fn backing_works() { ), ) if candidate_a_hash == candidate_hash && candidate_para_id == para_id ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::CollatorProtocol(CollatorProtocolMessage::Backed { - para_id: _para_id, - para_head, - }) if para_id == _para_id && candidate_a_para_head == para_head - ); assert_matches!( virtual_overseer.recv().await, AllMessages::StatementDistribution(StatementDistributionMessage::Backed ( @@ -1187,7 +1220,7 @@ fn concurrent_dependent_candidates() { let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let head_data = &[ HeadData(vec![10, 20, 30]), // Before `a`. @@ -1299,13 +1332,10 @@ fn concurrent_dependent_candidates() { // Order is not guaranteed since we have 2 statements being handled concurrently. match msg { AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate(_, tx), + ProspectiveParachainsMessage::IntroduceSecondedCandidate(_, tx), ) => { - tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap(); + tx.send(true).unwrap(); }, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::CandidateSeconded(_, _), - ) => {}, AllMessages::RuntimeApi(RuntimeApiMessage::Request( _, RuntimeApiRequest::ValidationCodeByHash(_, tx), @@ -1362,7 +1392,6 @@ fn concurrent_dependent_candidates() { AllMessages::ProspectiveParachains( ProspectiveParachainsMessage::CandidateBacked(..), ) => {}, - AllMessages::CollatorProtocol(CollatorProtocolMessage::Backed { .. }) => {}, AllMessages::StatementDistribution(StatementDistributionMessage::Share( _, statement, @@ -1406,7 +1435,13 @@ fn concurrent_dependent_candidates() { )) => { tx.send(Ok(test_state.validator_groups.clone())).unwrap(); }, - + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::NodeFeatures(sess_idx, tx), + )) => { + assert_eq!(sess_idx, 1); + tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); + }, AllMessages::RuntimeApi(RuntimeApiMessage::Request( _parent, RuntimeApiRequest::AvailabilityCores(tx), @@ -1447,7 +1482,7 @@ fn seconding_sanity_check_occupy_same_depth() { let min_relay_parents = vec![(para_id_a, min_block_number), (para_id_b, min_block_number)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -1506,44 +1541,35 @@ fn seconding_sanity_check_occupy_same_depth() { persisted_validation_data: pvd.clone(), }; let expected_request_a = vec![( - HypotheticalFrontierRequest { + HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_hash), }, // Send the same membership for both candidates. - make_hypothetical_frontier_response(vec![0, 1], hypothetical_candidate, leaf_hash), + make_hypothetical_membership_response(hypothetical_candidate, leaf_hash), )]; - assert_hypothetical_frontier_requests( + assert_hypothetical_membership_requests( &mut virtual_overseer, expected_request_a.clone(), ) .await; // Prospective parachains are notified. - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( - req, - tx, - ), - ) if - &req.candidate_receipt == candidate - && &req.candidate_para == para_id - && pvd == req.persisted_validation_data - => { - // Any non-empty response will do. - tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap(); - } - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::CandidateSeconded(_, _) - ) + ProspectiveParachainsMessage::IntroduceSecondedCandidate( + req, + tx, + ), + ) if + &req.candidate_receipt == candidate + && &req.candidate_para == para_id + && pvd == req.persisted_validation_data + => { + tx.send(true).unwrap(); + } ); assert_matches!( @@ -1600,7 +1626,7 @@ fn occupied_core_assignment() { let min_relay_parents = vec![(para_id, LEAF_A_BLOCK_NUMBER - LEAF_A_ANCESTRY_LEN)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; - activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state).await; let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; let pvd = dummy_pvd(); @@ -1648,23 +1674,18 @@ fn occupied_core_assignment() { persisted_validation_data: pvd.clone(), }; let expected_request = vec![( - HypotheticalFrontierRequest { + HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(leaf_a_hash), - backed_in_path_only: false, + fragment_chain_relay_parent: Some(leaf_a_hash), }, - make_hypothetical_frontier_response( - vec![0, 1, 2, 3], - hypothetical_candidate, - leaf_a_hash, - ), + make_hypothetical_membership_response(hypothetical_candidate, leaf_a_hash), )]; - assert_hypothetical_frontier_requests(&mut virtual_overseer, expected_request).await; + assert_hypothetical_membership_requests(&mut virtual_overseer, expected_request).await; // Prospective parachains are notified. assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::IntroduceCandidate( + ProspectiveParachainsMessage::IntroduceSecondedCandidate( req, tx, ), @@ -1673,19 +1694,10 @@ fn occupied_core_assignment() { && req.candidate_para == para_id && pvd == req.persisted_validation_data => { - // Any non-empty response will do. - tx.send(vec![(leaf_a_hash, vec![0, 1, 2, 3])]).unwrap(); + tx.send(true).unwrap(); } ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains(ProspectiveParachainsMessage::CandidateSeconded( - _, - _ - )) - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::StatementDistribution( diff --git a/polkadot/node/core/bitfield-signing/src/lib.rs b/polkadot/node/core/bitfield-signing/src/lib.rs index 89851c4a033b58428fa8eac366aafcd5f7144140..e3effb7949eaea0381c556c47eae0a1b6f09dc33 100644 --- a/polkadot/node/core/bitfield-signing/src/lib.rs +++ b/polkadot/node/core/bitfield-signing/src/lib.rs @@ -27,15 +27,14 @@ use futures::{ FutureExt, }; use polkadot_node_subsystem::{ - errors::RuntimeApiError, jaeger, - messages::{ - AvailabilityStoreMessage, BitfieldDistributionMessage, RuntimeApiMessage, RuntimeApiRequest, - }, + messages::{AvailabilityStoreMessage, BitfieldDistributionMessage}, overseer, ActivatedLeaf, FromOrchestra, OverseerSignal, PerLeafSpan, SpawnedSubsystem, - SubsystemError, SubsystemResult, SubsystemSender, + SubsystemError, SubsystemResult, +}; +use polkadot_node_subsystem_util::{ + self as util, request_availability_cores, runtime::recv_runtime, Validator, }; -use polkadot_node_subsystem_util::{self as util, Validator}; use polkadot_primitives::{AvailabilityBitfield, CoreState, Hash, ValidatorIndex}; use sp_keystore::{Error as KeystoreError, KeystorePtr}; use std::{collections::HashMap, time::Duration}; @@ -69,7 +68,7 @@ pub enum Error { MpscSend(#[from] mpsc::SendError), #[error(transparent)] - Runtime(#[from] RuntimeApiError), + Runtime(#[from] util::runtime::Error), #[error("Keystore failed: {0:?}")] Keystore(KeystoreError), @@ -79,8 +78,8 @@ pub enum Error { /// for whether we have the availability chunk for our validator index. async fn get_core_availability( core: &CoreState, - validator_idx: ValidatorIndex, - sender: &Mutex<&mut impl SubsystemSender>, + validator_index: ValidatorIndex, + sender: &Mutex<&mut impl overseer::BitfieldSigningSenderTrait>, span: &jaeger::Span, ) -> Result { if let CoreState::Occupied(core) = core { @@ -90,14 +89,11 @@ async fn get_core_availability( sender .lock() .await - .send_message( - AvailabilityStoreMessage::QueryChunkAvailability( - core.candidate_hash, - validator_idx, - tx, - ) - .into(), - ) + .send_message(AvailabilityStoreMessage::QueryChunkAvailability( + core.candidate_hash, + validator_index, + tx, + )) .await; let res = rx.await.map_err(Into::into); @@ -116,25 +112,6 @@ async fn get_core_availability( } } -/// delegates to the v1 runtime API -async fn get_availability_cores( - relay_parent: Hash, - sender: &mut impl SubsystemSender, -) -> Result, Error> { - let (tx, rx) = oneshot::channel(); - sender - .send_message( - RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::AvailabilityCores(tx)) - .into(), - ) - .await; - match rx.await { - Ok(Ok(out)) => Ok(out), - Ok(Err(runtime_err)) => Err(runtime_err.into()), - Err(err) => Err(err.into()), - } -} - /// - get the list of core states from the runtime /// - for each core, concurrently determine chunk availability (see `get_core_availability`) /// - return the bitfield if there were no errors at any point in this process (otherwise, it's @@ -143,12 +120,12 @@ async fn construct_availability_bitfield( relay_parent: Hash, span: &jaeger::Span, validator_idx: ValidatorIndex, - sender: &mut impl SubsystemSender, + sender: &mut impl overseer::BitfieldSigningSenderTrait, ) -> Result { // get the set of availability cores from the runtime let availability_cores = { let _span = span.child("get-availability-cores"); - get_availability_cores(relay_parent, sender).await? + recv_runtime(request_availability_cores(relay_parent, sender).await).await? }; // Wrap the sender in a Mutex to share it between the futures. diff --git a/polkadot/node/core/bitfield-signing/src/tests.rs b/polkadot/node/core/bitfield-signing/src/tests.rs index 106ecc06b1569862d7adeacada748e03b586b4ec..0e61e6086d28503eb9b092326b8cadd5442e9dbc 100644 --- a/polkadot/node/core/bitfield-signing/src/tests.rs +++ b/polkadot/node/core/bitfield-signing/src/tests.rs @@ -16,7 +16,7 @@ use super::*; use futures::{executor::block_on, pin_mut, StreamExt}; -use polkadot_node_subsystem::messages::AllMessages; +use polkadot_node_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}; use polkadot_primitives::{CandidateHash, OccupiedCore}; use test_helpers::dummy_candidate_descriptor; @@ -64,7 +64,7 @@ fn construct_availability_bitfield_works() { AllMessages::AvailabilityStore( AvailabilityStoreMessage::QueryChunkAvailability(c_hash, vidx, tx), ) => { - assert_eq!(validator_index, vidx); + assert_eq!(validator_index, vidx.into()); tx.send(c_hash == hash_a).unwrap(); }, diff --git a/polkadot/node/core/candidate-validation/Cargo.toml b/polkadot/node/core/candidate-validation/Cargo.toml index 0cf4707aad29b3931cab7d65005799cf58c8c38e..e79b3a734b8f6ed1f0d18c92a0697a8a5ba2e255 100644 --- a/polkadot/node/core/candidate-validation/Cargo.toml +++ b/polkadot/node/core/candidate-validation/Cargo.toml @@ -16,7 +16,7 @@ futures-timer = "3.0.2" gum = { package = "tracing-gum", path = "../../gum" } sp-maybe-compressed-blob = { package = "sp-maybe-compressed-blob", path = "../../../../substrate/primitives/maybe-compressed-blob" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } polkadot-primitives = { path = "../../../primitives" } polkadot-parachain-primitives = { path = "../../../parachain" } diff --git a/polkadot/node/core/chain-api/Cargo.toml b/polkadot/node/core/chain-api/Cargo.toml index f4d02d3f47b23ac4e71fa44c790bf4b0d1538902..bd8531c207847142a3b2ecd4407ef11253251034 100644 --- a/polkadot/node/core/chain-api/Cargo.toml +++ b/polkadot/node/core/chain-api/Cargo.toml @@ -21,7 +21,7 @@ sc-consensus-babe = { path = "../../../../substrate/client/consensus/babe" } [dev-dependencies] futures = { version = "0.3.30", features = ["thread-pool"] } maplit = "1.0.2" -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" polkadot-node-primitives = { path = "../../primitives" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/polkadot/node/core/chain-selection/Cargo.toml b/polkadot/node/core/chain-selection/Cargo.toml index 318f27a43086e4c6bee0bf0a0b18a78c9cf525be..b58053b5417eceb0bddfc2f34df5f1d84126c1c0 100644 --- a/polkadot/node/core/chain-selection/Cargo.toml +++ b/polkadot/node/core/chain-selection/Cargo.toml @@ -19,7 +19,7 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } kvdb = "0.13.0" thiserror = { workspace = true } -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/polkadot/node/core/dispute-coordinator/Cargo.toml b/polkadot/node/core/dispute-coordinator/Cargo.toml index cd3238449bea9d19ec65f418237282523ff3448a..8bd510697c913f10020605d335fb1748a2bb43c3 100644 --- a/polkadot/node/core/dispute-coordinator/Cargo.toml +++ b/polkadot/node/core/dispute-coordinator/Cargo.toml @@ -12,11 +12,11 @@ workspace = true [dependencies] futures = "0.3.30" gum = { package = "tracing-gum", path = "../../gum" } -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" kvdb = "0.13.0" thiserror = { workspace = true } schnellru = "0.2.1" -fatality = "0.0.6" +fatality = "0.1.1" polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } diff --git a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs index 05ea7323af1419d770cb7b68e15ee7887ceeaab8..b58ce570f8fff767a975487364cc6fe826c329e3 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs @@ -305,6 +305,7 @@ async fn participate( req.candidate_receipt().clone(), req.session(), None, + None, recover_available_data_tx, )) .await; diff --git a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs index 367454115f0be8e9aaccaf73b13e721a585c9dd7..1316508e84cf82dbecb49f7cc8509eabeeb00ea3 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs @@ -132,7 +132,7 @@ pub async fn participation_missing_availability(ctx_handle: &mut VirtualOverseer assert_matches!( ctx_handle.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Err(RecoveryError::Unavailable)).unwrap(); }, @@ -151,7 +151,7 @@ async fn recover_available_data(virtual_overseer: &mut VirtualOverseer) { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Ok(available_data)).unwrap(); }, @@ -195,7 +195,7 @@ fn same_req_wont_get_queued_if_participation_is_already_running() { assert_matches!( ctx_handle.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Err(RecoveryError::Unavailable)).unwrap(); }, @@ -260,7 +260,7 @@ fn reqs_get_queued_when_out_of_capacity() { { match ctx_handle.recv().await { AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx), + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx), ) => { tx.send(Err(RecoveryError::Unavailable)).unwrap(); recover_available_data_msg_count += 1; @@ -346,7 +346,7 @@ fn cannot_participate_if_cannot_recover_available_data() { assert_matches!( ctx_handle.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Err(RecoveryError::Unavailable)).unwrap(); }, @@ -412,7 +412,7 @@ fn cast_invalid_vote_if_available_data_is_invalid() { assert_matches!( ctx_handle.recv().await, AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, _, tx) ) => { tx.send(Err(RecoveryError::Invalid)).unwrap(); }, diff --git a/polkadot/node/core/prospective-parachains/Cargo.toml b/polkadot/node/core/prospective-parachains/Cargo.toml index ab3cef99e54ff6da279ec30728c308ed8bbf3da6..5b4f12a5fbdaffd345cc8f01d92691232deb5046 100644 --- a/polkadot/node/core/prospective-parachains/Cargo.toml +++ b/polkadot/node/core/prospective-parachains/Cargo.toml @@ -12,9 +12,9 @@ workspace = true [dependencies] futures = "0.3.30" gum = { package = "tracing-gum", path = "../../gum" } -parity-scale-codec = "3.6.4" +parity-scale-codec = "3.6.12" thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" bitvec = "1" polkadot-primitives = { path = "../../../primitives" } @@ -23,7 +23,6 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } [dev-dependencies] -rstest = "0.18.2" assert_matches = "1" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-node-subsystem-types = { path = "../../subsystem-types" } diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs index 86814b976d13424281203aa5bca59b0a918b7251..f87d4820ff9af242bf28ca7170527ec72d1963b8 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs @@ -14,35 +14,49 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! A tree utility for managing parachain fragments not referenced by the relay-chain. +//! Utility for managing parachain fragments not referenced by the relay-chain. //! //! # Overview //! -//! This module exposes two main types: [`FragmentTree`] and [`CandidateStorage`] which are meant to -//! be used in close conjunction. Each fragment tree is associated with a particular relay-parent -//! and each node in the tree represents a candidate. Each parachain has a single candidate storage, -//! but can have multiple trees for each relay chain block in the view. +//! This module exposes two main types: [`FragmentChain`] and [`CandidateStorage`] which are meant +//! to be used in close conjunction. Each fragment chain is associated with a particular +//! relay-parent and each node in the chain represents a candidate. Each parachain has a single +//! candidate storage, but can have one chain for each relay chain block in the view. +//! Therefore, the same candidate can be present in multiple fragment chains of a parachain. One of +//! the purposes of the candidate storage is to deduplicate the large candidate data that is being +//! referenced from multiple fragment chains. //! -//! A tree has an associated [`Scope`] which defines limits on candidates within the tree. +//! A chain has an associated [`Scope`] which defines limits on candidates within the chain. //! Candidates themselves have their own [`Constraints`] which are either the constraints from the -//! scope, or, if there are previous nodes in the tree, a modified version of the previous +//! scope, or, if there are previous nodes in the chain, a modified version of the previous //! candidate's constraints. //! +//! Another use of the `CandidateStorage` is to keep a record of candidates which may not be yet +//! included in any chain, but which may become part of a chain in the future. This is needed for +//! elastic scaling, so that we may parallelise the backing process across different groups. As long +//! as some basic constraints are not violated by an unconnected candidate (like the relay parent +//! being in scope), we proceed with the backing process, hoping that its predecessors will be +//! backed soon enough. This is commonly called a potential candidate. Note that not all potential +//! candidates will be maintained in the CandidateStorage. The total number of connected + potential +//! candidates will be at most max_candidate_depth + 1. +//! //! This module also makes use of types provided by the Inclusion Emulator module, such as //! [`Fragment`] and [`Constraints`]. These perform the actual job of checking for validity of //! prospective fragments. //! -//! # Usage +//! # Parachain forks //! -//! It's expected that higher-level code will have a tree for each relay-chain block which might -//! reasonably have blocks built upon it. +//! Parachains are expected to not create forks, hence the use of fragment chains as opposed to +//! fragment trees. If parachains do create forks, their performance in regards to async backing and +//! elastic scaling will suffer, because different validators will have different views of the +//! future. //! -//! Because a para only has a single candidate storage, trees only store indices into the storage. -//! The storage is meant to be pruned when trees are dropped by higher-level code. +//! This is a compromise we can make - collators which want to use async backing and elastic scaling +//! need to cooperate for the highest throughput. //! -//! # Cycles +//! # Parachain cycles //! -//! Nodes do not uniquely refer to a parachain block for two reasons. +//! Parachains can create cycles, because: //! 1. There's no requirement that head-data is unique for a parachain. Furthermore, a parachain //! is under no obligation to be acyclic, and this is mostly just because it's totally //! inefficient to enforce it. Practical use-cases are acyclic, but there is still more than @@ -50,34 +64,17 @@ //! 2. and candidates only refer to their parent by its head-data. This whole issue could be //! resolved by having candidates reference their parent by candidate hash. //! -//! The implication is that when we receive a candidate receipt, there are actually multiple -//! possibilities for any candidates between the para-head recorded in the relay parent's state -//! and the candidate in question. -//! -//! This means that our candidates need to handle multiple parents and that depth is an -//! attribute of a node in a tree, not a candidate. Put another way, the same candidate might -//! have different depths in different parts of the tree. +//! However, dealing with cycles increases complexity during the backing/inclusion process for no +//! practical reason. Therefore, fragment chains will not accept such candidates. //! -//! As an extreme example, a candidate which produces head-data which is the same as its parent -//! can correspond to multiple nodes within the same [`FragmentTree`]. Such cycles are bounded -//! by the maximum depth allowed by the tree. An example with `max_depth: 4`: +//! On the other hand, enforcing that a parachain will NEVER be acyclic would be very complicated +//! (looping through the entire parachain's history on every new candidate or changing the candidate +//! receipt to reference the parent's candidate hash). //! -//! ```text -//! committed head -//! | -//! depth 0: head_a -//! | -//! depth 1: head_b -//! | -//! depth 2: head_a -//! | -//! depth 3: head_b -//! | -//! depth 4: head_a -//! ``` +//! # Spam protection //! //! As long as the [`CandidateStorage`] has bounded input on the number of candidates supplied, -//! [`FragmentTree`] complexity is bounded. This means that higher-level code needs to be selective +//! [`FragmentChain`] complexity is bounded. This means that higher-level code needs to be selective //! about limiting the amount of candidates that are considered. //! //! The code in this module is not designed for speed or efficiency, but conceptual simplicity. @@ -90,16 +87,15 @@ mod tests; use std::{ - borrow::Cow, collections::{ hash_map::{Entry, HashMap}, BTreeMap, HashSet, }, + sync::Arc, }; use super::LOG_TARGET; -use bitvec::prelude::*; -use polkadot_node_subsystem::messages::Ancestors; +use polkadot_node_subsystem::messages::{Ancestors, HypotheticalCandidate}; use polkadot_node_subsystem_util::inclusion_emulator::{ ConstraintModifications, Constraints, Fragment, ProspectiveCandidate, RelayChainBlockInfo, }; @@ -120,11 +116,19 @@ pub enum CandidateStorageInsertionError { /// Stores candidates and information about them such as their relay-parents and their backing /// states. +#[derive(Clone, Default)] pub(crate) struct CandidateStorage { - // Index from head data hash to candidate hashes with that head data as a parent. + // Index from head data hash to candidate hashes with that head data as a parent. Purely for + // efficiency when responding to `ProspectiveValidationDataRequest`s or when trying to find a + // new candidate to push to a chain. + // Even though having multiple candidates with same parent would be invalid for a parachain, it + // could happen across different relay chain forks, hence the HashSet. by_parent_head: HashMap>, - // Index from head data hash to candidate hashes outputting that head data. + // Index from head data hash to candidate hashes outputting that head data. Purely for + // efficiency when responding to `ProspectiveValidationDataRequest`s. + // Even though having multiple candidates with same output would be invalid for a parachain, + // it could happen across different relay chain forks. by_output_head: HashMap>, // Index from candidate hash to fragment node. @@ -132,23 +136,14 @@ pub(crate) struct CandidateStorage { } impl CandidateStorage { - /// Create a new `CandidateStorage`. - pub fn new() -> Self { - CandidateStorage { - by_parent_head: HashMap::new(), - by_output_head: HashMap::new(), - by_candidate_hash: HashMap::new(), - } - } - /// Introduce a new candidate. pub fn add_candidate( &mut self, candidate: CommittedCandidateReceipt, persisted_validation_data: PersistedValidationData, + state: CandidateState, ) -> Result { let candidate_hash = candidate.hash(); - if self.by_candidate_hash.contains_key(&candidate_hash) { return Err(CandidateStorageInsertionError::CandidateAlreadyKnown(candidate_hash)) } @@ -157,24 +152,30 @@ impl CandidateStorage { return Err(CandidateStorageInsertionError::PersistedValidationDataMismatch) } - let parent_head_hash = persisted_validation_data.parent_head.hash(); - let output_head_hash = candidate.commitments.head_data.hash(); let entry = CandidateEntry { candidate_hash, + parent_head_data_hash: persisted_validation_data.parent_head.hash(), + output_head_data_hash: candidate.commitments.head_data.hash(), relay_parent: candidate.descriptor.relay_parent, - state: CandidateState::Introduced, - candidate: ProspectiveCandidate { - commitments: Cow::Owned(candidate.commitments), + state, + candidate: Arc::new(ProspectiveCandidate { + commitments: candidate.commitments, collator: candidate.descriptor.collator, collator_signature: candidate.descriptor.signature, persisted_validation_data, pov_hash: candidate.descriptor.pov_hash, validation_code_hash: candidate.descriptor.validation_code_hash, - }, + }), }; - self.by_parent_head.entry(parent_head_hash).or_default().insert(candidate_hash); - self.by_output_head.entry(output_head_hash).or_default().insert(candidate_hash); + self.by_parent_head + .entry(entry.parent_head_data_hash()) + .or_default() + .insert(candidate_hash); + self.by_output_head + .entry(entry.output_head_data_hash()) + .or_default() + .insert(candidate_hash); // sanity-checked already. self.by_candidate_hash.insert(candidate_hash, entry); @@ -184,21 +185,20 @@ impl CandidateStorage { /// Remove a candidate from the store. pub fn remove_candidate(&mut self, candidate_hash: &CandidateHash) { if let Some(entry) = self.by_candidate_hash.remove(candidate_hash) { - let parent_head_hash = entry.candidate.persisted_validation_data.parent_head.hash(); - if let Entry::Occupied(mut e) = self.by_parent_head.entry(parent_head_hash) { + if let Entry::Occupied(mut e) = self.by_parent_head.entry(entry.parent_head_data_hash()) + { e.get_mut().remove(&candidate_hash); if e.get().is_empty() { e.remove(); } } - } - } - /// Note that an existing candidate has been seconded. - pub fn mark_seconded(&mut self, candidate_hash: &CandidateHash) { - if let Some(entry) = self.by_candidate_hash.get_mut(candidate_hash) { - if entry.state != CandidateState::Backed { - entry.state = CandidateState::Seconded; + if let Entry::Occupied(mut e) = self.by_output_head.entry(entry.output_head_data_hash()) + { + e.get_mut().remove(&candidate_hash); + if e.get().is_empty() { + e.remove(); + } } } } @@ -225,6 +225,11 @@ impl CandidateStorage { self.by_candidate_hash.contains_key(candidate_hash) } + /// Return an iterator over the stored candidates. + pub fn candidates(&self) -> impl Iterator { + self.by_candidate_hash.values() + } + /// Retain only candidates which pass the predicate. pub(crate) fn retain(&mut self, pred: impl Fn(&CandidateHash) -> bool) { self.by_candidate_hash.retain(|h, _v| pred(h)); @@ -260,16 +265,17 @@ impl CandidateStorage { } /// Returns candidate's relay parent, if present. - pub(crate) fn relay_parent_by_candidate_hash( - &self, - candidate_hash: &CandidateHash, - ) -> Option { + pub(crate) fn relay_parent_of_candidate(&self, candidate_hash: &CandidateHash) -> Option { self.by_candidate_hash.get(candidate_hash).map(|entry| entry.relay_parent) } - fn iter_para_children<'a>( + /// Returns the candidates which have the given head data hash as parent. + /// We don't allow forks in a parachain, but we may have multiple candidates with same parent + /// across different relay chain forks. That's why it returns an iterator (but only one will be + /// valid and used in the end). + fn possible_para_children<'a>( &'a self, - parent_head_hash: &Hash, + parent_head_hash: &'a Hash, ) -> impl Iterator + 'a { let by_candidate_hash = &self.by_candidate_hash; self.by_parent_head @@ -279,10 +285,6 @@ impl CandidateStorage { .filter_map(move |h| by_candidate_hash.get(h)) } - fn get(&'_ self, candidate_hash: &CandidateHash) -> Option<&'_ CandidateEntry> { - self.by_candidate_hash.get(candidate_hash) - } - #[cfg(test)] pub fn len(&self) -> (usize, usize) { (self.by_parent_head.len(), self.by_candidate_hash.len()) @@ -292,25 +294,38 @@ impl CandidateStorage { /// The state of a candidate. /// /// Candidates aren't even considered until they've at least been seconded. -#[derive(Debug, PartialEq)] -enum CandidateState { - /// The candidate has been introduced in a spam-protected way but - /// is not necessarily backed. - Introduced, +#[derive(Debug, PartialEq, Clone)] +pub(crate) enum CandidateState { /// The candidate has been seconded. Seconded, /// The candidate has been completely backed by the group. Backed, } -#[derive(Debug)] -struct CandidateEntry { +#[derive(Debug, Clone)] +pub(crate) struct CandidateEntry { candidate_hash: CandidateHash, + parent_head_data_hash: Hash, + output_head_data_hash: Hash, relay_parent: Hash, - candidate: ProspectiveCandidate<'static>, + candidate: Arc, state: CandidateState, } +impl CandidateEntry { + pub fn hash(&self) -> CandidateHash { + self.candidate_hash + } + + pub fn parent_head_data_hash(&self) -> Hash { + self.parent_head_data_hash + } + + pub fn output_head_data_hash(&self) -> Hash { + self.output_head_data_hash + } +} + /// A candidate existing on-chain but pending availability, for special treatment /// in the [`Scope`]. #[derive(Debug, Clone)] @@ -321,15 +336,22 @@ pub(crate) struct PendingAvailability { pub relay_parent: RelayChainBlockInfo, } -/// The scope of a [`FragmentTree`]. -#[derive(Debug)] +/// The scope of a [`FragmentChain`]. +#[derive(Debug, Clone)] pub(crate) struct Scope { + /// The assigned para id of this `FragmentChain`. para: ParaId, + /// The relay parent we're currently building on top of. relay_parent: RelayChainBlockInfo, + /// The other relay parents candidates are allowed to build upon, mapped by the block number. ancestors: BTreeMap, + /// The other relay parents candidates are allowed to build upon, mapped by the block hash. ancestors_by_hash: HashMap, + /// The candidates pending availability at this block. pending_availability: Vec, + /// The base constraints derived from the latest included candidate. base_constraints: Constraints, + /// Equal to `max_candidate_depth`. max_depth: usize, } @@ -398,7 +420,7 @@ impl Scope { }) } - /// Get the earliest relay-parent allowed in the scope of the fragment tree. + /// Get the earliest relay-parent allowed in the scope of the fragment chain. pub fn earliest_relay_parent(&self) -> RelayChainBlockInfo { self.ancestors .iter() @@ -407,8 +429,8 @@ impl Scope { .unwrap_or_else(|| self.relay_parent.clone()) } - /// Get the ancestor of the fragment tree by hash. - pub fn ancestor_by_hash(&self, hash: &Hash) -> Option { + /// Get the relay ancestor of the fragment chain by hash. + pub fn ancestor(&self, hash: &Hash) -> Option { if hash == &self.relay_parent.hash { return Some(self.relay_parent.clone()) } @@ -430,67 +452,48 @@ impl Scope { } } -/// We use indices into a flat vector to refer to nodes in the tree. -/// Every tree also has an implicit root. -#[derive(Debug, Clone, Copy, PartialEq)] -enum NodePointer { - Root, - Storage(usize), -} - -/// A hypothetical candidate, which may or may not exist in -/// the fragment tree already. -pub(crate) enum HypotheticalCandidate<'a> { - Complete { - receipt: Cow<'a, CommittedCandidateReceipt>, - persisted_validation_data: Cow<'a, PersistedValidationData>, - }, - Incomplete { - relay_parent: Hash, - parent_head_data_hash: Hash, - }, +pub struct FragmentNode { + fragment: Fragment, + candidate_hash: CandidateHash, + cumulative_modifications: ConstraintModifications, } -impl<'a> HypotheticalCandidate<'a> { - fn parent_head_data_hash(&self) -> Hash { - match *self { - HypotheticalCandidate::Complete { ref persisted_validation_data, .. } => - persisted_validation_data.as_ref().parent_head.hash(), - HypotheticalCandidate::Incomplete { ref parent_head_data_hash, .. } => - *parent_head_data_hash, - } - } - +impl FragmentNode { fn relay_parent(&self) -> Hash { - match *self { - HypotheticalCandidate::Complete { ref receipt, .. } => - receipt.descriptor().relay_parent, - HypotheticalCandidate::Incomplete { ref relay_parent, .. } => *relay_parent, - } + self.fragment.relay_parent().hash } } -/// This is a tree of candidates based on some underlying storage of candidates and a scope. +/// Response given by `can_add_candidate_as_potential` +#[derive(PartialEq, Debug)] +pub enum PotentialAddition { + /// Can be added as either connected or unconnected candidate. + Anyhow, + /// Can only be added as a connected candidate to the chain. + IfConnected, + /// Cannot be added. + None, +} + +/// This is a chain of candidates based on some underlying storage of candidates and a scope. /// -/// All nodes in the tree must be either pending availability or within the scope. Within the scope +/// All nodes in the chain must be either pending availability or within the scope. Within the scope /// means it's built off of the relay-parent or an ancestor. -pub(crate) struct FragmentTree { +pub(crate) struct FragmentChain { scope: Scope, - // Invariant: a contiguous prefix of the 'nodes' storage will contain - // the top-level children. - nodes: Vec, + chain: Vec, + + candidates: HashSet, - // The candidates stored in this tree, mapped to a bitvec indicating the depths - // where the candidate is stored. - candidates: HashMap>, + // Index from head data hash to candidate hashes with that head data as a parent. + by_parent_head: HashMap, + // Index from head data hash to candidate hashes outputting that head data. + by_output_head: HashMap, } -impl FragmentTree { - /// Create a new [`FragmentTree`] with given scope and populated from the storage. - /// - /// Can be populated recursively (i.e. `populate` will pick up candidates that build on other - /// candidates). +impl FragmentChain { + /// Create a new [`FragmentChain`] with given scope and populated from the storage. pub fn populate(scope: Scope, storage: &CandidateStorage) -> Self { gum::trace!( target: LOG_TARGET, @@ -498,285 +501,152 @@ impl FragmentTree { relay_parent_num = scope.relay_parent.number, para_id = ?scope.para, ancestors = scope.ancestors.len(), - "Instantiating Fragment Tree", + "Instantiating Fragment Chain", ); - let mut tree = FragmentTree { scope, nodes: Vec::new(), candidates: HashMap::new() }; + let mut fragment_chain = Self { + scope, + chain: Vec::new(), + candidates: HashSet::new(), + by_parent_head: HashMap::new(), + by_output_head: HashMap::new(), + }; - tree.populate_from_bases(storage, vec![NodePointer::Root]); + fragment_chain.populate_chain(storage); - tree + fragment_chain } - /// Get the scope of the Fragment Tree. + /// Get the scope of the Fragment Chain. pub fn scope(&self) -> &Scope { &self.scope } - // Inserts a node and updates child references in a non-root parent. - fn insert_node(&mut self, node: FragmentNode) { - let pointer = NodePointer::Storage(self.nodes.len()); - let parent_pointer = node.parent; - let candidate_hash = node.candidate_hash; - - let max_depth = self.scope.max_depth; - - self.candidates - .entry(candidate_hash) - .or_insert_with(|| bitvec![u16, Msb0; 0; max_depth + 1]) - .set(node.depth, true); - - match parent_pointer { - NodePointer::Storage(ptr) => { - self.nodes.push(node); - self.nodes[ptr].children.push((pointer, candidate_hash)) - }, - NodePointer::Root => { - // Maintain the invariant of node storage beginning with depth-0. - if self.nodes.last().map_or(true, |last| last.parent == NodePointer::Root) { - self.nodes.push(node); - } else { - let pos = - self.nodes.iter().take_while(|n| n.parent == NodePointer::Root).count(); - self.nodes.insert(pos, node); - } - }, - } - } - - fn node_has_candidate_child( - &self, - pointer: NodePointer, - candidate_hash: &CandidateHash, - ) -> bool { - self.node_candidate_child(pointer, candidate_hash).is_some() - } - - fn node_candidate_child( - &self, - pointer: NodePointer, - candidate_hash: &CandidateHash, - ) -> Option { - match pointer { - NodePointer::Root => self - .nodes - .iter() - .take_while(|n| n.parent == NodePointer::Root) - .enumerate() - .find(|(_, n)| &n.candidate_hash == candidate_hash) - .map(|(i, _)| NodePointer::Storage(i)), - NodePointer::Storage(ptr) => - self.nodes.get(ptr).and_then(|n| n.candidate_child(candidate_hash)), - } + /// Returns the number of candidates in the chain + pub(crate) fn len(&self) -> usize { + self.candidates.len() } - /// Returns an O(n) iterator over the hashes of candidates contained in the - /// tree. - pub(crate) fn candidates(&self) -> impl Iterator + '_ { - self.candidates.keys().cloned() + /// Whether the candidate exists. + pub(crate) fn contains_candidate(&self, candidate: &CandidateHash) -> bool { + self.candidates.contains(candidate) } - /// Whether the candidate exists and at what depths. - pub(crate) fn candidate(&self, candidate: &CandidateHash) -> Option> { - self.candidates.get(candidate).map(|d| d.iter_ones().collect()) + /// Return a vector of the chain's candidate hashes, in-order. + pub(crate) fn to_vec(&self) -> Vec { + self.chain.iter().map(|candidate| candidate.candidate_hash).collect() } - /// Add a candidate and recursively populate from storage. + /// Try accumulating more candidates onto the chain. /// - /// Candidates can be added either as children of the root or children of other candidates. - pub(crate) fn add_and_populate(&mut self, hash: CandidateHash, storage: &CandidateStorage) { - let candidate_entry = match storage.get(&hash) { - None => return, - Some(e) => e, - }; - - let candidate_parent = &candidate_entry.candidate.persisted_validation_data.parent_head; - - // Select an initial set of bases, whose required relay-parent matches that of the - // candidate. - let root_base = if &self.scope.base_constraints.required_parent == candidate_parent { - Some(NodePointer::Root) - } else { - None - }; - - let non_root_bases = self - .nodes - .iter() - .enumerate() - .filter(|(_, n)| { - n.cumulative_modifications.required_parent.as_ref() == Some(candidate_parent) - }) - .map(|(i, _)| NodePointer::Storage(i)); - - let bases = root_base.into_iter().chain(non_root_bases).collect(); - - // Pass this into the population function, which will sanity-check stuff like depth, - // fragments, etc. and then recursively populate. - self.populate_from_bases(storage, bases); + /// Candidates can only be added if they build on the already existing chain. + pub(crate) fn extend_from_storage(&mut self, storage: &CandidateStorage) { + self.populate_chain(storage); } - /// Returns `true` if the path from the root to the node's parent (inclusive) - /// only contains backed candidates, `false` otherwise. - fn path_contains_backed_only_candidates( + /// Returns the hypothetical state of a candidate with the given hash and parent head data + /// in regards to the existing chain. + /// + /// Returns true if either: + /// - the candidate is already present + /// - the candidate can be added to the chain + /// - the candidate could potentially be added to the chain in the future (its ancestors are + /// still unknown but it doesn't violate other rules). + /// + /// If this returns false, the candidate could never be added to the current chain (not now, not + /// ever) + pub(crate) fn hypothetical_membership( &self, - mut parent_pointer: NodePointer, + candidate: HypotheticalCandidate, candidate_storage: &CandidateStorage, ) -> bool { - while let NodePointer::Storage(ptr) = parent_pointer { - let node = &self.nodes[ptr]; - let candidate_hash = &node.candidate_hash; - - if candidate_storage.get(candidate_hash).map_or(true, |candidate_entry| { - !matches!(candidate_entry.state, CandidateState::Backed) - }) { - return false - } - parent_pointer = node.parent; + let candidate_hash = candidate.candidate_hash(); + + // If we've already used this candidate in the chain + if self.candidates.contains(&candidate_hash) { + return true } - true - } + let can_add_as_potential = self.can_add_candidate_as_potential( + candidate_storage, + &candidate.candidate_hash(), + &candidate.relay_parent(), + candidate.parent_head_data_hash(), + candidate.output_head_data_hash(), + ); - /// Returns the hypothetical depths where a candidate with the given hash and parent head data - /// would be added to the tree, without applying other candidates recursively on top of it. - /// - /// If the candidate is already known, this returns the actual depths where this - /// candidate is part of the tree. - /// - /// Setting `backed_in_path_only` to `true` ensures this function only returns such membership - /// that every candidate in the path from the root is backed. - pub(crate) fn hypothetical_depths( - &self, - hash: CandidateHash, - candidate: HypotheticalCandidate, - candidate_storage: &CandidateStorage, - backed_in_path_only: bool, - ) -> Vec { - // if `true`, we always have to traverse the tree. - if !backed_in_path_only { - // if known. - if let Some(depths) = self.candidates.get(&hash) { - return depths.iter_ones().collect() - } + if can_add_as_potential == PotentialAddition::None { + return false } - // if out of scope. - let candidate_relay_parent = candidate.relay_parent(); - let candidate_relay_parent = if self.scope.relay_parent.hash == candidate_relay_parent { - self.scope.relay_parent.clone() - } else if let Some(info) = self.scope.ancestors_by_hash.get(&candidate_relay_parent) { - info.clone() + let Some(candidate_relay_parent) = self.scope.ancestor(&candidate.relay_parent()) else { + // can_add_candidate_as_potential already checked for this, but just to be safe. + return false + }; + + let identity_modifications = ConstraintModifications::identity(); + let cumulative_modifications = if let Some(last_candidate) = self.chain.last() { + &last_candidate.cumulative_modifications } else { - return Vec::new() + &identity_modifications }; - let max_depth = self.scope.max_depth; - let mut depths = bitvec![u16, Msb0; 0; max_depth + 1]; - - // iterate over all nodes where parent head-data matches, - // relay-parent number is <= candidate, and depth < max_depth. - let node_pointers = (0..self.nodes.len()).map(NodePointer::Storage); - for parent_pointer in std::iter::once(NodePointer::Root).chain(node_pointers) { - let (modifications, child_depth, earliest_rp) = match parent_pointer { - NodePointer::Root => - (ConstraintModifications::identity(), 0, self.scope.earliest_relay_parent()), - NodePointer::Storage(ptr) => { - let node = &self.nodes[ptr]; - let parent_rp = self - .scope - .ancestor_by_hash(&node.relay_parent()) - .or_else(|| { - self.scope - .get_pending_availability(&node.candidate_hash) - .map(|_| self.scope.earliest_relay_parent()) - }) - .expect("All nodes in tree are either pending availability or within scope; qed"); - - (node.cumulative_modifications.clone(), node.depth + 1, parent_rp) + let child_constraints = + match self.scope.base_constraints.apply_modifications(&cumulative_modifications) { + Err(e) => { + gum::debug!( + target: LOG_TARGET, + new_parent_head = ?cumulative_modifications.required_parent, + ?candidate_hash, + err = ?e, + "Failed to apply modifications", + ); + + return false }, + Ok(c) => c, }; - if child_depth > max_depth { - continue - } - - if earliest_rp.number > candidate_relay_parent.number { - continue - } - - let child_constraints = - match self.scope.base_constraints.apply_modifications(&modifications) { - Err(e) => { - gum::debug!( - target: LOG_TARGET, - new_parent_head = ?modifications.required_parent, - err = ?e, - "Failed to apply modifications", - ); - - continue - }, - Ok(c) => c, - }; - - let parent_head_hash = candidate.parent_head_data_hash(); - if parent_head_hash != child_constraints.required_parent.hash() { - continue - } - + let parent_head_hash = candidate.parent_head_data_hash(); + if parent_head_hash == child_constraints.required_parent.hash() { // We do additional checks for complete candidates. - if let HypotheticalCandidate::Complete { ref receipt, ref persisted_validation_data } = - candidate + if let HypotheticalCandidate::Complete { + ref receipt, + ref persisted_validation_data, + .. + } = candidate { - let prospective_candidate = ProspectiveCandidate { - commitments: Cow::Borrowed(&receipt.commitments), - collator: receipt.descriptor().collator.clone(), - collator_signature: receipt.descriptor().signature.clone(), - persisted_validation_data: persisted_validation_data.as_ref().clone(), - pov_hash: receipt.descriptor().pov_hash, - validation_code_hash: receipt.descriptor().validation_code_hash, - }; - - if Fragment::new( - candidate_relay_parent.clone(), - child_constraints, - prospective_candidate, + if Fragment::check_against_constraints( + &candidate_relay_parent, + &child_constraints, + &receipt.commitments, + &receipt.descriptor().validation_code_hash, + persisted_validation_data, ) .is_err() { - continue + gum::debug!( + target: LOG_TARGET, + "Fragment::check_against_constraints() returned error", + ); + return false } } - // Check that the path only contains backed candidates, if necessary. - if !backed_in_path_only || - self.path_contains_backed_only_candidates(parent_pointer, candidate_storage) - { - depths.set(child_depth, true); - } + // If we got this far, it can be added to the chain right now. + true + } else if can_add_as_potential == PotentialAddition::Anyhow { + // Otherwise it is or can be an unconnected candidate, but only if PotentialAddition + // does not force us to only add a connected candidate. + true + } else { + false } - - depths.iter_ones().collect() } /// Select `count` candidates after the given `ancestors` which pass /// the predicate and have not already been backed on chain. /// - /// Does an exhaustive search into the tree after traversing the ancestors path. - /// If the ancestors draw out a path that can be traversed in multiple ways, no - /// candidates will be returned. - /// If the ancestors do not draw out a full path (the path contains holes), candidates will be - /// suggested that may fill these holes. - /// If the ancestors don't draw out a valid path, no candidates will be returned. If there are - /// multiple possibilities of the same size, this will select the first one. If there is no - /// chain of size `count` that matches the criteria, this will return the largest chain it could - /// find with the criteria. If there are no candidates meeting those criteria, returns an empty - /// `Vec`. - /// Cycles are accepted, but this code expects that the runtime will deduplicate - /// identical candidates when occupying the cores (when proposing to back A->B->A, only A will - /// be backed on chain). - /// /// The intention of the `ancestors` is to allow queries on the basis of /// one or more candidates which were previously pending availability becoming /// available or candidates timing out. @@ -789,362 +659,334 @@ impl FragmentTree { if count == 0 { return vec![] } - // First, we need to order the ancestors. - // The node returned is the one from which we can start finding new backable candidates. - let Some(base_node) = self.find_ancestor_path(ancestors) else { return vec![] }; - - self.find_backable_chain_inner( - base_node, - count, - count, - &pred, - &mut Vec::with_capacity(count as usize), - ) - } + let base_pos = self.find_ancestor_path(ancestors); - // Try finding a candidate chain starting from `base_node` of length `expected_count`. - // If not possible, return the longest one we could find. - // Does a depth-first search, since we're optimistic that there won't be more than one such - // chains (parachains shouldn't usually have forks). So in the usual case, this will conclude - // in `O(expected_count)`. - // Cycles are accepted, but this doesn't allow for infinite execution time, because the maximum - // depth we'll reach is `expected_count`. - // - // Worst case performance is `O(num_forks ^ expected_count)`, the same as populating the tree. - // Although an exponential function, this is actually a constant that can only be altered via - // sudo/governance, because: - // 1. `num_forks` at a given level is at most `max_candidate_depth * max_validators_per_core` - // (because each validator in the assigned group can second `max_candidate_depth` - // candidates). The prospective-parachains subsystem assumes that the number of para forks is - // limited by collator-protocol and backing subsystems. In practice, this is a constant which - // can only be altered by sudo or governance. - // 2. `expected_count` is equal to the number of cores a para is scheduled on (in an elastic - // scaling scenario). For non-elastic-scaling, this is just 1. In practice, this should be a - // small number (1-3), capped by the total number of available cores (a constant alterable - // only via governance/sudo). - fn find_backable_chain_inner( - &self, - base_node: NodePointer, - expected_count: u32, - remaining_count: u32, - pred: &dyn Fn(&CandidateHash) -> bool, - accumulator: &mut Vec, - ) -> Vec { - if remaining_count == 0 { - // The best option is the chain we've accumulated so far. - return accumulator.to_vec(); + let actual_end_index = std::cmp::min(base_pos + (count as usize), self.chain.len()); + let mut res = Vec::with_capacity(actual_end_index - base_pos); + + for elem in &self.chain[base_pos..actual_end_index] { + if self.scope.get_pending_availability(&elem.candidate_hash).is_none() && + pred(&elem.candidate_hash) + { + res.push(elem.candidate_hash); + } else { + break + } } - let children: Vec<_> = match base_node { - NodePointer::Root => self - .nodes - .iter() - .enumerate() - .take_while(|(_, n)| n.parent == NodePointer::Root) - .filter(|(_, n)| self.scope.get_pending_availability(&n.candidate_hash).is_none()) - .filter(|(_, n)| pred(&n.candidate_hash)) - .map(|(ptr, n)| (NodePointer::Storage(ptr), n.candidate_hash)) - .collect(), - NodePointer::Storage(base_node_ptr) => { - let base_node = &self.nodes[base_node_ptr]; - - base_node - .children - .iter() - .filter(|(_, hash)| self.scope.get_pending_availability(&hash).is_none()) - .filter(|(_, hash)| pred(&hash)) - .map(|(ptr, hash)| (*ptr, *hash)) - .collect() - }, - }; + res + } + + // Tries to orders the ancestors into a viable path from root to the last one. + // Stops when the ancestors are all used or when a node in the chain is not present in the + // ancestor set. Returns the index in the chain were the search stopped. + fn find_ancestor_path(&self, mut ancestors: Ancestors) -> usize { + if self.chain.is_empty() { + return 0; + } - let mut best_result = accumulator.clone(); - for (child_ptr, child_hash) in children { - accumulator.push(child_hash); - - let result = self.find_backable_chain_inner( - child_ptr, - expected_count, - remaining_count - 1, - &pred, - accumulator, - ); - - accumulator.pop(); - - // Short-circuit the search if we've found the right length. Otherwise, we'll - // search for a max. - // Taking the first best selection doesn't introduce bias or become gameable, - // because `find_ancestor_path` uses a `HashSet` to track the ancestors, which - // makes the order in which ancestors are visited non-deterministic. - if result.len() == expected_count as usize { - return result - } else if best_result.len() < result.len() { - best_result = result; + for (index, candidate) in self.chain.iter().enumerate() { + if !ancestors.remove(&candidate.candidate_hash) { + return index } } - best_result + // This means that we found the entire chain in the ancestor set. There won't be anything + // left to back. + self.chain.len() + } + + // Return the earliest relay parent a new candidate can have in order to be added to the chain. + // This is the relay parent of the last candidate in the chain. + // The value returned may not be valid if we want to add a candidate pending availability, which + // may have a relay parent which is out of scope. Special handling is needed in that case. + // `None` is returned if the candidate's relay parent info cannot be found. + fn earliest_relay_parent(&self) -> Option { + if let Some(last_candidate) = self.chain.last() { + self.scope.ancestor(&last_candidate.relay_parent()).or_else(|| { + // if the relay-parent is out of scope _and_ it is in the chain, + // it must be a candidate pending availability. + self.scope + .get_pending_availability(&last_candidate.candidate_hash) + .map(|c| c.relay_parent.clone()) + }) + } else { + Some(self.scope.earliest_relay_parent()) + } + } + + // Checks if this candidate could be added in the future to this chain. + // This assumes that the chain does not already contain this candidate. It may or may not be + // present in the `CandidateStorage`. + // Even if the candidate is a potential candidate, this function will indicate that it can be + // kept only if there's enough room for it. + pub(crate) fn can_add_candidate_as_potential( + &self, + storage: &CandidateStorage, + candidate_hash: &CandidateHash, + relay_parent: &Hash, + parent_head_hash: Hash, + output_head_hash: Option, + ) -> PotentialAddition { + // If we've got enough candidates for the configured depth, no point in adding more. + if self.chain.len() > self.scope.max_depth { + return PotentialAddition::None + } + + if !self.check_potential(relay_parent, parent_head_hash, output_head_hash) { + return PotentialAddition::None + } + + let present_in_storage = storage.contains(candidate_hash); + + let unconnected = self + .find_unconnected_potential_candidates( + storage, + present_in_storage.then_some(candidate_hash), + ) + .len(); + + if (self.chain.len() + unconnected) < self.scope.max_depth { + PotentialAddition::Anyhow + } else if (self.chain.len() + unconnected) == self.scope.max_depth { + // If we've only one slot left to fill, it must be filled with a connected candidate. + PotentialAddition::IfConnected + } else { + PotentialAddition::None + } } - // Orders the ancestors into a viable path from root to the last one. - // Returns a pointer to the last node in the path. - // We assume that the ancestors form a chain (that the - // av-cores do not back parachain forks), None is returned otherwise. - // If we cannot use all ancestors, stop at the first found hole in the chain. This usually - // translates to a timed out candidate. - fn find_ancestor_path(&self, mut ancestors: Ancestors) -> Option { - // The number of elements in the path we've processed so far. - let mut depth = 0; - let mut last_node = NodePointer::Root; - let mut next_node: Option = Some(NodePointer::Root); - - while let Some(node) = next_node { - if depth > self.scope.max_depth { - return None; + // The candidates which are present in `CandidateStorage`, are not part of this chain but could + // become part of this chain in the future. Capped at the max depth minus the existing chain + // length. + // If `ignore_candidate` is supplied and found in storage, it won't be counted. + pub(crate) fn find_unconnected_potential_candidates( + &self, + storage: &CandidateStorage, + ignore_candidate: Option<&CandidateHash>, + ) -> Vec { + let mut candidates = vec![]; + for candidate in storage.candidates() { + if let Some(ignore_candidate) = ignore_candidate { + if ignore_candidate == &candidate.candidate_hash { + continue + } + } + // We stop at max_depth + 1 with the search. There's no point in looping further. + if (self.chain.len() + candidates.len()) > self.scope.max_depth { + break + } + if !self.candidates.contains(&candidate.candidate_hash) && + self.check_potential( + &candidate.relay_parent, + candidate.candidate.persisted_validation_data.parent_head.hash(), + Some(candidate.candidate.commitments.head_data.hash()), + ) { + candidates.push(candidate.candidate_hash); } + } + + candidates + } - last_node = node; + // Check if adding a candidate which transitions `parent_head_hash` to `output_head_hash` would + // introduce a fork or a cycle in the parachain. + // `output_head_hash` is optional because we sometimes make this check before retrieving the + // collation. + fn is_fork_or_cycle(&self, parent_head_hash: Hash, output_head_hash: Option) -> bool { + if self.by_parent_head.contains_key(&parent_head_hash) { + // fork. our parent has another child already + return true + } - next_node = match node { - NodePointer::Root => { - let children = self - .nodes - .iter() - .enumerate() - .take_while(|n| n.1.parent == NodePointer::Root) - .map(|(index, node)| (NodePointer::Storage(index), node.candidate_hash)) - .collect::>(); + if let Some(output_head_hash) = output_head_hash { + if self.by_output_head.contains_key(&output_head_hash) { + // this is not a chain, there are multiple paths to the same state. + return true + } - self.find_valid_child(&mut ancestors, children.iter()).ok()? - }, - NodePointer::Storage(ptr) => { - let children = self.nodes.get(ptr).and_then(|n| Some(n.children.iter())); - if let Some(children) = children { - self.find_valid_child(&mut ancestors, children).ok()? - } else { - None - } - }, - }; + // trivial 0-length cycle. + if parent_head_hash == output_head_hash { + return true + } - depth += 1; + // this should catch any other cycles. our output state cannot already be the parent + // state of another candidate, unless this is a cycle, since the already added + // candidates form a chain. + if self.by_parent_head.contains_key(&output_head_hash) { + return true + } } - Some(last_node) + false } - // Find a node from the given iterator which is present in the ancestors - // collection. If there are multiple such nodes, return an error and log a warning. We don't - // accept forks in a parachain to be backed. The supplied ancestors should all form a chain. - // If there is no such node, return None. - fn find_valid_child<'a>( + // Checks the potential of a candidate to be added to the chain in the future. + // Verifies that the relay parent is in scope and not moving backwards and that we're not + // introducing forks or cycles with other candidates in the chain. + // `output_head_hash` is optional because we sometimes make this check before retrieving the + // collation. + fn check_potential( &self, - ancestors: &'a mut Ancestors, - nodes: impl Iterator + 'a, - ) -> Result, ()> { - let mut possible_children = - nodes.filter_map(|(node_ptr, hash)| match ancestors.remove(&hash) { - true => Some(node_ptr), - false => None, - }); - - // We don't accept forks in a parachain to be backed. The supplied ancestors - // should all form a chain. - let next = possible_children.next(); - if let Some(second_child) = possible_children.next() { - if let (Some(NodePointer::Storage(first_child)), NodePointer::Storage(second_child)) = - (next, second_child) - { - gum::error!( - target: LOG_TARGET, - para_id = ?self.scope.para, - relay_parent = ?self.scope.relay_parent, - "Trying to find new backable candidates for a parachain for which we've backed a fork.\ - This is a bug and the runtime should not have allowed it.\n\ - Backed candidates with the same parent: {}, {}", - self.nodes[*first_child].candidate_hash, - self.nodes[*second_child].candidate_hash, - ); - } + relay_parent: &Hash, + parent_head_hash: Hash, + output_head_hash: Option, + ) -> bool { + if self.is_fork_or_cycle(parent_head_hash, output_head_hash) { + return false + } - Err(()) - } else { - Ok(next.copied()) + let Some(earliest_rp) = self.earliest_relay_parent() else { return false }; + + let Some(relay_parent) = self.scope.ancestor(relay_parent) else { return false }; + + if relay_parent.number < earliest_rp.number { + return false // relay parent moved backwards. } + + true } - fn populate_from_bases(&mut self, storage: &CandidateStorage, initial_bases: Vec) { - // Populate the tree breadth-first. - let mut last_sweep_start = None; + // Populate the fragment chain with candidates from CandidateStorage. + // Can be called by the constructor or when introducing a new candidate. + // If we're introducing a new candidate onto an existing chain, we may introduce more than one, + // since we may connect already existing candidates to the chain. + fn populate_chain(&mut self, storage: &CandidateStorage) { + let mut cumulative_modifications = if let Some(last_candidate) = self.chain.last() { + last_candidate.cumulative_modifications.clone() + } else { + ConstraintModifications::identity() + }; + let Some(mut earliest_rp) = self.earliest_relay_parent() else { return }; loop { - let sweep_start = self.nodes.len(); - - if Some(sweep_start) == last_sweep_start { - break + if self.chain.len() > self.scope.max_depth { + break; } - let parents: Vec = if let Some(last_start) = last_sweep_start { - (last_start..self.nodes.len()).map(NodePointer::Storage).collect() - } else { - initial_bases.clone() - }; + let child_constraints = + match self.scope.base_constraints.apply_modifications(&cumulative_modifications) { + Err(e) => { + gum::debug!( + target: LOG_TARGET, + new_parent_head = ?cumulative_modifications.required_parent, + err = ?e, + "Failed to apply modifications", + ); - // 1. get parent head and find constraints - // 2. iterate all candidates building on the right head and viable relay parent - // 3. add new node - for parent_pointer in parents { - let (modifications, child_depth, earliest_rp) = match parent_pointer { - NodePointer::Root => - (ConstraintModifications::identity(), 0, self.scope.earliest_relay_parent()), - NodePointer::Storage(ptr) => { - let node = &self.nodes[ptr]; - let parent_rp = self - .scope - .ancestor_by_hash(&node.relay_parent()) - .or_else(|| { - // if the relay-parent is out of scope _and_ it is in the tree, - // it must be a candidate pending availability. - self.scope - .get_pending_availability(&node.candidate_hash) - .map(|c| c.relay_parent.clone()) - }) - .expect("All nodes in tree are either pending availability or within scope; qed"); - - (node.cumulative_modifications.clone(), node.depth + 1, parent_rp) + break }, + Ok(c) => c, }; - if child_depth > self.scope.max_depth { + let required_head_hash = child_constraints.required_parent.hash(); + // Even though we don't allow parachain forks under the same active leaf, they may still + // appear under different relay chain forks, hence the iterator below. + let possible_children = storage.possible_para_children(&required_head_hash); + let mut added_child = false; + for candidate in possible_children { + // Add one node to chain if + // 1. it does not introduce a fork or a cycle. + // 2. parent hash is correct. + // 3. relay-parent does not move backwards. + // 4. all non-pending-availability candidates have relay-parent in scope. + // 5. candidate outputs fulfill constraints + + if self.is_fork_or_cycle( + candidate.parent_head_data_hash(), + Some(candidate.output_head_data_hash()), + ) { continue } - let child_constraints = - match self.scope.base_constraints.apply_modifications(&modifications) { + let pending = self.scope.get_pending_availability(&candidate.candidate_hash); + let Some(relay_parent) = pending + .map(|p| p.relay_parent.clone()) + .or_else(|| self.scope.ancestor(&candidate.relay_parent)) + else { + continue + }; + + // require: candidates don't move backwards + // and only pending availability candidates can be out-of-scope. + // + // earliest_rp can be before the earliest relay parent in the scope + // when the parent is a pending availability candidate as well, but + // only other pending candidates can have a relay parent out of scope. + let min_relay_parent_number = pending + .map(|p| match self.chain.len() { + 0 => p.relay_parent.number, + _ => earliest_rp.number, + }) + .unwrap_or_else(|| earliest_rp.number); + + if relay_parent.number < min_relay_parent_number { + continue // relay parent moved backwards. + } + + // don't add candidates if they're already present in the chain. + // this can never happen, as candidates can only be duplicated if there's a cycle + // and we shouldn't have allowed for a cycle to be chained. + if self.contains_candidate(&candidate.candidate_hash) { + continue + } + + let fragment = { + let mut constraints = child_constraints.clone(); + if let Some(ref p) = pending { + // overwrite for candidates pending availability as a special-case. + constraints.min_relay_parent_number = p.relay_parent.number; + } + + let f = Fragment::new( + relay_parent.clone(), + constraints, + // It's cheap to clone because it's wrapped in an Arc + candidate.candidate.clone(), + ); + + match f { + Ok(f) => f, Err(e) => { gum::debug!( target: LOG_TARGET, - new_parent_head = ?modifications.required_parent, err = ?e, - "Failed to apply modifications", + ?relay_parent, + candidate_hash = ?candidate.candidate_hash, + "Failed to instantiate fragment", ); - continue + break }, - Ok(c) => c, - }; - - // Add nodes to tree wherever - // 1. parent hash is correct - // 2. relay-parent does not move backwards. - // 3. all non-pending-availability candidates have relay-parent in scope. - // 4. candidate outputs fulfill constraints - let required_head_hash = child_constraints.required_parent.hash(); - for candidate in storage.iter_para_children(&required_head_hash) { - let pending = self.scope.get_pending_availability(&candidate.candidate_hash); - let relay_parent = pending - .map(|p| p.relay_parent.clone()) - .or_else(|| self.scope.ancestor_by_hash(&candidate.relay_parent)); - - let relay_parent = match relay_parent { - Some(r) => r, - None => continue, - }; - - // require: pending availability candidates don't move backwards - // and only those can be out-of-scope. - // - // earliest_rp can be before the earliest relay parent in the scope - // when the parent is a pending availability candidate as well, but - // only other pending candidates can have a relay parent out of scope. - let min_relay_parent_number = pending - .map(|p| match parent_pointer { - NodePointer::Root => p.relay_parent.number, - NodePointer::Storage(_) => earliest_rp.number, - }) - .unwrap_or_else(|| { - std::cmp::max( - earliest_rp.number, - self.scope.earliest_relay_parent().number, - ) - }); - - if relay_parent.number < min_relay_parent_number { - continue // relay parent moved backwards. } + }; - // don't add candidates where the parent already has it as a child. - if self.node_has_candidate_child(parent_pointer, &candidate.candidate_hash) { - continue - } + // Update the cumulative constraint modifications. + cumulative_modifications.stack(fragment.constraint_modifications()); + // Update the earliest rp + earliest_rp = relay_parent; - let fragment = { - let mut constraints = child_constraints.clone(); - if let Some(ref p) = pending { - // overwrite for candidates pending availability as a special-case. - constraints.min_relay_parent_number = p.relay_parent.number; - } - - let f = Fragment::new( - relay_parent.clone(), - constraints, - candidate.candidate.partial_clone(), - ); + let node = FragmentNode { + fragment, + candidate_hash: candidate.candidate_hash, + cumulative_modifications: cumulative_modifications.clone(), + }; - match f { - Ok(f) => f.into_owned(), - Err(e) => { - gum::debug!( - target: LOG_TARGET, - err = ?e, - ?relay_parent, - candidate_hash = ?candidate.candidate_hash, - "Failed to instantiate fragment", - ); - - continue - }, - } - }; - - let mut cumulative_modifications = modifications.clone(); - cumulative_modifications.stack(fragment.constraint_modifications()); - - let node = FragmentNode { - parent: parent_pointer, - fragment, - candidate_hash: candidate.candidate_hash, - depth: child_depth, - cumulative_modifications, - children: Vec::new(), - }; - - self.insert_node(node); - } + self.chain.push(node); + self.candidates.insert(candidate.candidate_hash); + // We've already checked for forks and cycles. + self.by_parent_head + .insert(candidate.parent_head_data_hash(), candidate.candidate_hash); + self.by_output_head + .insert(candidate.output_head_data_hash(), candidate.candidate_hash); + added_child = true; + // We can only add one child for a candidate. (it's a chain, not a tree) + break; } - last_sweep_start = Some(sweep_start); + if !added_child { + break + } } } } - -struct FragmentNode { - // A pointer to the parent node. - parent: NodePointer, - fragment: Fragment<'static>, - candidate_hash: CandidateHash, - depth: usize, - cumulative_modifications: ConstraintModifications, - children: Vec<(NodePointer, CandidateHash)>, -} - -impl FragmentNode { - fn relay_parent(&self) -> Hash { - self.fragment.relay_parent().hash - } - - fn candidate_child(&self, candidate_hash: &CandidateHash) -> Option { - self.children.iter().find(|(_, c)| c == candidate_hash).map(|(p, _)| *p) - } -} diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs index fd41be55f7f960367ee0a57ccd4a4c2251b90d13..26ee94d59d8ebd50bda29218c85b38476f077111 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs @@ -19,17 +19,6 @@ use assert_matches::assert_matches; use polkadot_node_subsystem_util::inclusion_emulator::InboundHrmpLimitations; use polkadot_primitives::{BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData}; use polkadot_primitives_test_helpers as test_helpers; -use rstest::rstest; -use std::iter; - -impl NodePointer { - fn unwrap_idx(self) -> usize { - match self { - NodePointer::Root => panic!("Unexpected root"), - NodePointer::Storage(index) => index, - } - } -} fn make_constraints( min_relay_parent_number: BlockNumber, @@ -204,8 +193,52 @@ fn scope_only_takes_ancestors_up_to_min() { } #[test] -fn storage_add_candidate() { - let mut storage = CandidateStorage::new(); +fn scope_rejects_unordered_ancestors() { + let para_id = ParaId::from(5u32); + let relay_parent = RelayChainBlockInfo { + number: 5, + hash: Hash::repeat_byte(0), + storage_root: Hash::repeat_byte(69), + }; + + let ancestors = vec![ + RelayChainBlockInfo { + number: 4, + hash: Hash::repeat_byte(4), + storage_root: Hash::repeat_byte(69), + }, + RelayChainBlockInfo { + number: 2, + hash: Hash::repeat_byte(2), + storage_root: Hash::repeat_byte(69), + }, + RelayChainBlockInfo { + number: 3, + hash: Hash::repeat_byte(3), + storage_root: Hash::repeat_byte(69), + }, + ]; + + let max_depth = 2; + let base_constraints = make_constraints(0, vec![2], vec![1, 2, 3].into()); + let pending_availability = Vec::new(); + + assert_matches!( + Scope::with_ancestors( + para_id, + relay_parent, + base_constraints, + pending_availability, + max_depth, + ancestors, + ), + Err(UnexpectedAncestor { number: 2, prev: 4 }) + ); +} + +#[test] +fn candidate_storage_methods() { + let mut storage = CandidateStorage::default(); let relay_parent = Hash::repeat_byte(69); let (pvd, candidate) = make_committed_candidate( @@ -220,50 +253,105 @@ fn storage_add_candidate() { let candidate_hash = candidate.hash(); let parent_head_hash = pvd.parent_head.hash(); - storage.add_candidate(candidate, pvd).unwrap(); + // Invalid pvd hash + let mut wrong_pvd = pvd.clone(); + wrong_pvd.max_pov_size = 0; + assert_matches!( + storage.add_candidate(candidate.clone(), wrong_pvd, CandidateState::Seconded), + Err(CandidateStorageInsertionError::PersistedValidationDataMismatch) + ); + assert!(!storage.contains(&candidate_hash)); + assert_eq!(storage.possible_para_children(&parent_head_hash).count(), 0); + assert_eq!(storage.relay_parent_of_candidate(&candidate_hash), None); + assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head), None); + assert_eq!(storage.head_data_by_hash(&parent_head_hash), None); + assert_eq!(storage.is_backed(&candidate_hash), false); + + // Add a valid candidate + storage + .add_candidate(candidate.clone(), pvd.clone(), CandidateState::Seconded) + .unwrap(); assert!(storage.contains(&candidate_hash)); - assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1); - - assert_eq!(storage.relay_parent_by_candidate_hash(&candidate_hash), Some(relay_parent)); -} + assert_eq!(storage.possible_para_children(&parent_head_hash).count(), 1); + assert_eq!(storage.possible_para_children(&candidate.descriptor.para_head).count(), 0); + assert_eq!(storage.relay_parent_of_candidate(&candidate_hash), Some(relay_parent)); + assert_eq!( + storage.head_data_by_hash(&candidate.descriptor.para_head).unwrap(), + &candidate.commitments.head_data + ); + assert_eq!(storage.head_data_by_hash(&parent_head_hash).unwrap(), &pvd.parent_head); + assert_eq!(storage.is_backed(&candidate_hash), false); -#[test] -fn storage_retain() { - let mut storage = CandidateStorage::new(); + storage.mark_backed(&candidate_hash); + assert_eq!(storage.is_backed(&candidate_hash), true); - let (pvd, candidate) = make_committed_candidate( - ParaId::from(5u32), - Hash::repeat_byte(69), - 8, - vec![4, 5, 6].into(), - vec![1, 2, 3].into(), - 7, + // Re-adding a candidate fails. + assert_matches!( + storage.add_candidate(candidate.clone(), pvd.clone(), CandidateState::Seconded), + Err(CandidateStorageInsertionError::CandidateAlreadyKnown(hash)) if candidate_hash == hash ); - let candidate_hash = candidate.hash(); - let output_head_hash = candidate.commitments.head_data.hash(); - let parent_head_hash = pvd.parent_head.hash(); - - storage.add_candidate(candidate, pvd).unwrap(); + // Remove candidate and re-add it later in backed state. + storage.remove_candidate(&candidate_hash); + assert!(!storage.contains(&candidate_hash)); + assert_eq!(storage.possible_para_children(&parent_head_hash).count(), 0); + assert_eq!(storage.relay_parent_of_candidate(&candidate_hash), None); + assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head), None); + assert_eq!(storage.head_data_by_hash(&parent_head_hash), None); + assert_eq!(storage.is_backed(&candidate_hash), false); + + storage + .add_candidate(candidate.clone(), pvd.clone(), CandidateState::Backed) + .unwrap(); + assert_eq!(storage.is_backed(&candidate_hash), true); + + // Test retain storage.retain(|_| true); assert!(storage.contains(&candidate_hash)); - assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1); - assert!(storage.head_data_by_hash(&output_head_hash).is_some()); - storage.retain(|_| false); assert!(!storage.contains(&candidate_hash)); - assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 0); - assert!(storage.head_data_by_hash(&output_head_hash).is_none()); + assert_eq!(storage.possible_para_children(&parent_head_hash).count(), 0); + assert_eq!(storage.relay_parent_of_candidate(&candidate_hash), None); + assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head), None); + assert_eq!(storage.head_data_by_hash(&parent_head_hash), None); + assert_eq!(storage.is_backed(&candidate_hash), false); } -// [`FragmentTree::populate`] should pick up candidates that build on other candidates. #[test] -fn populate_works_recursively() { - let mut storage = CandidateStorage::new(); +fn populate_and_extend_from_storage_empty() { + // Empty chain and empty storage. + let storage = CandidateStorage::default(); + let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); + let pending_availability = Vec::new(); + + let scope = Scope::with_ancestors( + ParaId::from(2), + RelayChainBlockInfo { + number: 1, + hash: Hash::repeat_byte(1), + storage_root: Hash::repeat_byte(2), + }, + base_constraints, + pending_availability, + 4, + vec![], + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert!(chain.to_vec().is_empty()); + + chain.extend_from_storage(&storage); + assert!(chain.to_vec().is_empty()); +} + +#[test] +fn populate_and_extend_from_storage_with_existing_empty_to_vec() { + let mut storage = CandidateStorage::default(); let para_id = ParaId::from(5u32); let relay_parent_a = Hash::repeat_byte(1); let relay_parent_b = Hash::repeat_byte(2); + let relay_parent_c = Hash::repeat_byte(3); let (pvd_a, candidate_a) = make_committed_candidate( para_id, @@ -285,56 +373,623 @@ fn populate_works_recursively() { ); let candidate_b_hash = candidate_b.hash(); - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); + let (pvd_c, candidate_c) = make_committed_candidate( + para_id, + relay_parent_c, + 2, + vec![0x0c].into(), + vec![0x0d].into(), + 2, + ); + let candidate_c_hash = candidate_c.hash(); - let ancestors = vec![RelayChainBlockInfo { + let relay_parent_a_info = RelayChainBlockInfo { number: pvd_a.relay_parent_number, hash: relay_parent_a, storage_root: pvd_a.relay_parent_storage_root, - }]; - + }; let relay_parent_b_info = RelayChainBlockInfo { number: pvd_b.relay_parent_number, hash: relay_parent_b, storage_root: pvd_b.relay_parent_storage_root, }; + let relay_parent_c_info = RelayChainBlockInfo { + number: pvd_c.relay_parent_number, + hash: relay_parent_c, + storage_root: pvd_c.relay_parent_storage_root, + }; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_b_info, - base_constraints, - pending_availability, - 4, - ancestors, - ) - .unwrap(); - let tree = FragmentTree::populate(scope, &storage); + let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); + let pending_availability = Vec::new(); + + let ancestors = vec![ + // These need to be ordered in reverse. + relay_parent_b_info.clone(), + relay_parent_a_info.clone(), + ]; + + storage + .add_candidate(candidate_a.clone(), pvd_a.clone(), CandidateState::Seconded) + .unwrap(); + storage + .add_candidate(candidate_b.clone(), pvd_b.clone(), CandidateState::Backed) + .unwrap(); + storage + .add_candidate(candidate_c.clone(), pvd_c.clone(), CandidateState::Backed) + .unwrap(); + + // Candidate A doesn't adhere to the base constraints. + { + for wrong_constraints in [ + // Different required parent + make_constraints(0, vec![0], vec![0x0e].into()), + // Min relay parent number is wrong + make_constraints(1, vec![0], vec![0x0a].into()), + ] { + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + wrong_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + + assert!(chain.to_vec().is_empty()); + + chain.extend_from_storage(&storage); + assert!(chain.to_vec().is_empty()); + + // If the min relay parent number is wrong, candidate A can never become valid. + // Otherwise, if only the required parent doesn't match, candidate A is still a + // potential candidate. + if wrong_constraints.min_relay_parent_number == 1 { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate_a.hash(), + &candidate_a.descriptor.relay_parent, + pvd_a.parent_head.hash(), + Some(candidate_a.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } else { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate_a.hash(), + &candidate_a.descriptor.relay_parent, + pvd_a.parent_head.hash(), + Some(candidate_a.commitments.head_data.hash()), + ), + PotentialAddition::Anyhow + ); + } + + // All other candidates can always be potential candidates. + for (candidate, pvd) in + [(candidate_b.clone(), pvd_b.clone()), (candidate_c.clone(), pvd_c.clone())] + { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::Anyhow + ); + } + } + } + + // Various max depths. + { + // depth is 0, will only allow 1 candidate + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 0, + ancestors.clone(), + ) + .unwrap(); + // Before populating the chain, all candidates are potential candidates. However, they can + // only be added as connected candidates, because only one candidates is allowed by max + // depth + let chain = FragmentChain::populate(scope.clone(), &CandidateStorage::default()); + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + assert_eq!( + chain.can_add_candidate_as_potential( + &CandidateStorage::default(), + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::IfConnected + ); + } + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash]); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash]); + // since depth is maxed out, we can't add more potential candidates + // candidate A is no longer a potential candidate because it's already present. + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } + + // depth is 1, allows two candidates + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 1, + ancestors.clone(), + ) + .unwrap(); + // Before populating the chain, all candidates can be added as potential. + let mut modified_storage = CandidateStorage::default(); + let chain = FragmentChain::populate(scope.clone(), &modified_storage); + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::Anyhow + ); + } + // Add an unconnected candidate. We now should only allow a Connected candidate, because max + // depth only allows one more candidate. + modified_storage + .add_candidate(candidate_b.clone(), pvd_b.clone(), CandidateState::Seconded) + .unwrap(); + let chain = FragmentChain::populate(scope.clone(), &modified_storage); + for (candidate, pvd) in + [(candidate_a.clone(), pvd_a.clone()), (candidate_c.clone(), pvd_c.clone())] + { + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::IfConnected + ); + } + + // Now try populating from all candidates. + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + // since depth is maxed out, we can't add more potential candidates + // candidate A and B are no longer a potential candidate because they're already present. + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } + + // depths larger than 2, allows all candidates + for depth in 2..6 { + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + depth, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + // Candidates are no longer potential candidates because they're already part of the + // chain. + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } + } + } + + // Wrong relay parents + { + // Candidates A has relay parent out of scope. + let ancestors_without_a = vec![relay_parent_b_info.clone()]; + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors_without_a, + ) + .unwrap(); + + let mut chain = FragmentChain::populate(scope, &storage); + assert!(chain.to_vec().is_empty()); + + chain.extend_from_storage(&storage); + assert!(chain.to_vec().is_empty()); + + // Candidate A is not a potential candidate, but candidates B and C still are. + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate_a.hash(), + &candidate_a.descriptor.relay_parent, + pvd_a.parent_head.hash(), + Some(candidate_a.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + for (candidate, pvd) in + [(candidate_b.clone(), pvd_b.clone()), (candidate_c.clone(), pvd_c.clone())] + { + assert_eq!( + chain.can_add_candidate_as_potential( + &storage, + &candidate.hash(), + &candidate.descriptor.relay_parent, + pvd.parent_head.hash(), + Some(candidate.commitments.head_data.hash()), + ), + PotentialAddition::Anyhow + ); + } + + // Candidate C has the same relay parent as candidate A's parent. Relay parent not allowed + // to move backwards + let mut modified_storage = storage.clone(); + modified_storage.remove_candidate(&candidate_c_hash); + let (wrong_pvd_c, wrong_candidate_c) = make_committed_candidate( + para_id, + relay_parent_a, + 1, + vec![0x0c].into(), + vec![0x0d].into(), + 2, + ); + modified_storage + .add_candidate(wrong_candidate_c.clone(), wrong_pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + chain.extend_from_storage(&modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + + // Candidate C is not even a potential candidate. + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &wrong_candidate_c.hash(), + &wrong_candidate_c.descriptor.relay_parent, + wrong_pvd_c.parent_head.hash(), + Some(wrong_candidate_c.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } + + // Parachain fork and cycles are not allowed. + { + // Candidate C has the same parent as candidate B. + let mut modified_storage = storage.clone(); + modified_storage.remove_candidate(&candidate_c_hash); + let (wrong_pvd_c, wrong_candidate_c) = make_committed_candidate( + para_id, + relay_parent_c, + 2, + vec![0x0b].into(), + vec![0x0d].into(), + 2, + ); + modified_storage + .add_candidate(wrong_candidate_c.clone(), wrong_pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &modified_storage); + // We'll either have A->B or A->C. It's not deterministic because CandidateStorage uses + // HashSets and HashMaps. + if chain.to_vec() == vec![candidate_a_hash, candidate_b_hash] { + chain.extend_from_storage(&modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + // Candidate C is not even a potential candidate. + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &wrong_candidate_c.hash(), + &wrong_candidate_c.descriptor.relay_parent, + wrong_pvd_c.parent_head.hash(), + Some(wrong_candidate_c.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } else if chain.to_vec() == vec![candidate_a_hash, wrong_candidate_c.hash()] { + chain.extend_from_storage(&modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, wrong_candidate_c.hash()]); + // Candidate B is not even a potential candidate. + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &candidate_b.hash(), + &candidate_b.descriptor.relay_parent, + pvd_b.parent_head.hash(), + Some(candidate_b.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } else { + panic!("Unexpected chain: {:?}", chain.to_vec()); + } + + // Candidate C is a 0-length cycle. + // Candidate C has the same parent as candidate B. + let mut modified_storage = storage.clone(); + modified_storage.remove_candidate(&candidate_c_hash); + let (wrong_pvd_c, wrong_candidate_c) = make_committed_candidate( + para_id, + relay_parent_c, + 2, + vec![0x0c].into(), + vec![0x0c].into(), + 2, + ); + modified_storage + .add_candidate(wrong_candidate_c.clone(), wrong_pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + chain.extend_from_storage(&modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + // Candidate C is not even a potential candidate. + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &wrong_candidate_c.hash(), + &wrong_candidate_c.descriptor.relay_parent, + wrong_pvd_c.parent_head.hash(), + Some(wrong_candidate_c.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + + // Candidate C points back to the pre-state of candidate C. + let mut modified_storage = storage.clone(); + modified_storage.remove_candidate(&candidate_c_hash); + let (wrong_pvd_c, wrong_candidate_c) = make_committed_candidate( + para_id, + relay_parent_c, + 2, + vec![0x0c].into(), + vec![0x0b].into(), + 2, + ); + modified_storage + .add_candidate(wrong_candidate_c.clone(), wrong_pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + chain.extend_from_storage(&modified_storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + // Candidate C is not even a potential candidate. + assert_eq!( + chain.can_add_candidate_as_potential( + &modified_storage, + &wrong_candidate_c.hash(), + &wrong_candidate_c.descriptor.relay_parent, + wrong_pvd_c.parent_head.hash(), + Some(wrong_candidate_c.commitments.head_data.hash()), + ), + PotentialAddition::None + ); + } - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - assert!(candidates.contains(&candidate_a_hash)); - assert!(candidates.contains(&candidate_b_hash)); + // Test with candidates pending availability + { + // Valid options + for pending in [ + vec![PendingAvailability { + candidate_hash: candidate_a_hash, + relay_parent: relay_parent_a_info.clone(), + }], + vec![ + PendingAvailability { + candidate_hash: candidate_a_hash, + relay_parent: relay_parent_a_info.clone(), + }, + PendingAvailability { + candidate_hash: candidate_b_hash, + relay_parent: relay_parent_b_info.clone(), + }, + ], + vec![ + PendingAvailability { + candidate_hash: candidate_a_hash, + relay_parent: relay_parent_a_info.clone(), + }, + PendingAvailability { + candidate_hash: candidate_b_hash, + relay_parent: relay_parent_b_info.clone(), + }, + PendingAvailability { + candidate_hash: candidate_c_hash, + relay_parent: relay_parent_c_info.clone(), + }, + ], + ] { + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + pending, + 3, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + } - assert_eq!(tree.nodes.len(), 2); - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[0].depth, 0); + // Relay parents of pending availability candidates can be out of scope + // Relay parent of candidate A is out of scope. + let ancestors_without_a = vec![relay_parent_b_info.clone()]; + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + vec![PendingAvailability { + candidate_hash: candidate_a_hash, + relay_parent: relay_parent_a_info.clone(), + }], + 4, + ancestors_without_a, + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + + // Even relay parents of pending availability candidates which are out of scope cannot move + // backwards. + let scope = Scope::with_ancestors( + para_id, + relay_parent_c_info.clone(), + base_constraints.clone(), + vec![ + PendingAvailability { + candidate_hash: candidate_a_hash, + relay_parent: RelayChainBlockInfo { + hash: relay_parent_a_info.hash, + number: 1, + storage_root: relay_parent_a_info.storage_root, + }, + }, + PendingAvailability { + candidate_hash: candidate_b_hash, + relay_parent: RelayChainBlockInfo { + hash: relay_parent_b_info.hash, + number: 0, + storage_root: relay_parent_b_info.storage_root, + }, + }, + ], + 4, + vec![], + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert!(chain.to_vec().is_empty()); - assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0)); - assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash); - assert_eq!(tree.nodes[1].depth, 1); + chain.extend_from_storage(&storage); + assert!(chain.to_vec().is_empty()); + } } #[test] -fn children_of_root_are_contiguous() { - let mut storage = CandidateStorage::new(); - +fn extend_from_storage_with_existing_to_vec() { let para_id = ParaId::from(5u32); let relay_parent_a = Hash::repeat_byte(1); let relay_parent_b = Hash::repeat_byte(2); + let relay_parent_d = Hash::repeat_byte(3); let (pvd_a, candidate_a) = make_committed_candidate( para_id, @@ -344,6 +999,7 @@ fn children_of_root_are_contiguous() { vec![0x0b].into(), 0, ); + let candidate_a_hash = candidate_a.hash(); let (pvd_b, candidate_b) = make_committed_candidate( para_id, @@ -353,182 +1009,136 @@ fn children_of_root_are_contiguous() { vec![0x0c].into(), 1, ); + let candidate_b_hash = candidate_b.hash(); - let (pvd_a2, candidate_a2) = make_committed_candidate( + let (pvd_c, candidate_c) = make_committed_candidate( para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0b, 1].into(), - 0, + // Use the same relay parent number as B to test that it doesn't need to change between + // candidates. + relay_parent_b, + 1, + vec![0x0c].into(), + vec![0x0d].into(), + 1, ); - let candidate_a2_hash = candidate_a2.hash(); + let candidate_c_hash = candidate_c.hash(); - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); + // Candidate D will never be added to the chain. + let (pvd_d, candidate_d) = make_committed_candidate( + para_id, + relay_parent_d, + 2, + vec![0x0e].into(), + vec![0x0f].into(), + 1, + ); - let ancestors = vec![RelayChainBlockInfo { + let relay_parent_a_info = RelayChainBlockInfo { number: pvd_a.relay_parent_number, hash: relay_parent_a, storage_root: pvd_a.relay_parent_storage_root, - }]; - + }; let relay_parent_b_info = RelayChainBlockInfo { number: pvd_b.relay_parent_number, hash: relay_parent_b, storage_root: pvd_b.relay_parent_storage_root, }; + let relay_parent_d_info = RelayChainBlockInfo { + number: pvd_d.relay_parent_number, + hash: relay_parent_d, + storage_root: pvd_d.relay_parent_storage_root, + }; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_b_info, - base_constraints, - pending_availability, - 4, - ancestors, - ) - .unwrap(); - let mut tree = FragmentTree::populate(scope, &storage); + let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); + let pending_availability = Vec::new(); + + let ancestors = vec![ + // These need to be ordered in reverse. + relay_parent_b_info.clone(), + relay_parent_a_info.clone(), + ]; - storage.add_candidate(candidate_a2, pvd_a2).unwrap(); - tree.add_and_populate(candidate_a2_hash, &storage); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 3); + // Already had A and C in the storage. Introduce B, which should add both B and C to the chain + // now. + { + let mut storage = CandidateStorage::default(); + storage + .add_candidate(candidate_a.clone(), pvd_a.clone(), CandidateState::Seconded) + .unwrap(); + storage + .add_candidate(candidate_c.clone(), pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + storage + .add_candidate(candidate_d.clone(), pvd_d.clone(), CandidateState::Seconded) + .unwrap(); + + let scope = Scope::with_ancestors( + para_id, + relay_parent_d_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash]); + + storage + .add_candidate(candidate_b.clone(), pvd_b.clone(), CandidateState::Seconded) + .unwrap(); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + } - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[1].parent, NodePointer::Root); - assert_eq!(tree.nodes[2].parent, NodePointer::Storage(0)); + // Already had A and B in the chain. Introduce C. + { + let mut storage = CandidateStorage::default(); + storage + .add_candidate(candidate_a.clone(), pvd_a.clone(), CandidateState::Seconded) + .unwrap(); + storage + .add_candidate(candidate_b.clone(), pvd_b.clone(), CandidateState::Seconded) + .unwrap(); + storage + .add_candidate(candidate_d.clone(), pvd_d.clone(), CandidateState::Seconded) + .unwrap(); + + let scope = Scope::with_ancestors( + para_id, + relay_parent_d_info.clone(), + base_constraints.clone(), + pending_availability.clone(), + 4, + ancestors.clone(), + ) + .unwrap(); + let mut chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); + + storage + .add_candidate(candidate_c.clone(), pvd_c.clone(), CandidateState::Seconded) + .unwrap(); + chain.extend_from_storage(&storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash, candidate_c_hash]); + } } #[test] -fn add_candidate_child_of_root() { - let mut storage = CandidateStorage::new(); - +fn test_find_ancestor_path_and_find_backable_chain_empty_to_vec() { let para_id = ParaId::from(5u32); - let relay_parent_a = Hash::repeat_byte(1); + let relay_parent = Hash::repeat_byte(1); + let required_parent: HeadData = vec![0xff].into(); + let max_depth = 10; - let (pvd_a, candidate_a) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0b].into(), - 0, - ); - - let (pvd_b, candidate_b) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0c].into(), - 0, - ); - let candidate_b_hash = candidate_b.hash(); - - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); - - let relay_parent_a_info = RelayChainBlockInfo { - number: pvd_a.relay_parent_number, - hash: relay_parent_a, - storage_root: pvd_a.relay_parent_storage_root, - }; - - storage.add_candidate(candidate_a, pvd_a).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_a_info, - base_constraints, - pending_availability, - 4, - vec![], - ) - .unwrap(); - let mut tree = FragmentTree::populate(scope, &storage); - - storage.add_candidate(candidate_b, pvd_b).unwrap(); - tree.add_and_populate(candidate_b_hash, &storage); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[1].parent, NodePointer::Root); -} - -#[test] -fn add_candidate_child_of_non_root() { - let mut storage = CandidateStorage::new(); - - let para_id = ParaId::from(5u32); - let relay_parent_a = Hash::repeat_byte(1); - - let (pvd_a, candidate_a) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0b].into(), - 0, - ); - - let (pvd_b, candidate_b) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0b].into(), - vec![0x0c].into(), - 0, - ); - let candidate_b_hash = candidate_b.hash(); - - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); - - let relay_parent_a_info = RelayChainBlockInfo { - number: pvd_a.relay_parent_number, - hash: relay_parent_a, - storage_root: pvd_a.relay_parent_storage_root, - }; - - storage.add_candidate(candidate_a, pvd_a).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_a_info, - base_constraints, - pending_availability, - 4, - vec![], - ) - .unwrap(); - let mut tree = FragmentTree::populate(scope, &storage); - - storage.add_candidate(candidate_b, pvd_b).unwrap(); - tree.add_and_populate(candidate_b_hash, &storage); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0)); -} - -#[test] -fn test_find_ancestor_path_and_find_backable_chain_empty_tree() { - let para_id = ParaId::from(5u32); - let relay_parent = Hash::repeat_byte(1); - let required_parent: HeadData = vec![0xff].into(); - let max_depth = 10; - - // Empty tree - let storage = CandidateStorage::new(); - let base_constraints = make_constraints(0, vec![0], required_parent.clone()); - - let relay_parent_info = - RelayChainBlockInfo { number: 0, hash: relay_parent, storage_root: Hash::zero() }; - - let scope = Scope::with_ancestors( + // Empty chain + let storage = CandidateStorage::default(); + let base_constraints = make_constraints(0, vec![0], required_parent.clone()); + + let relay_parent_info = + RelayChainBlockInfo { number: 0, hash: relay_parent, storage_root: Hash::zero() }; + + let scope = Scope::with_ancestors( para_id, relay_parent_info, base_constraints, @@ -537,64 +1147,23 @@ fn test_find_ancestor_path_and_find_backable_chain_empty_tree() { vec![], ) .unwrap(); - let tree = FragmentTree::populate(scope, &storage); - assert_eq!(tree.candidates().collect::>().len(), 0); - assert_eq!(tree.nodes.len(), 0); + let chain = FragmentChain::populate(scope, &storage); + assert!(chain.to_vec().is_empty()); - assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root); - assert_eq!(tree.find_backable_chain(Ancestors::new(), 2, |_| true), vec![]); + assert_eq!(chain.find_ancestor_path(Ancestors::new()), 0); + assert_eq!(chain.find_backable_chain(Ancestors::new(), 2, |_| true), vec![]); // Invalid candidate. let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect(); - assert_eq!(tree.find_ancestor_path(ancestors.clone()), Some(NodePointer::Root)); - assert_eq!(tree.find_backable_chain(ancestors, 2, |_| true), vec![]); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 0); + assert_eq!(chain.find_backable_chain(ancestors, 2, |_| true), vec![]); } -#[rstest] -#[case(true, 13)] -#[case(false, 8)] -// The tree with no cycles looks like: -// Make a tree that looks like this (note that there's no cycle): -// +-(root)-+ -// | | -// +----0---+ 7 -// | | -// 1----+ 5 -// | | -// | | -// 2 6 -// | -// 3 -// | -// 4 -// -// The tree with cycles is the same as the first but has a cycle from 4 back to the state -// produced by 0 (It's bounded by the max_depth + 1). -// +-(root)-+ -// | | -// +----0---+ 7 -// | | -// 1----+ 5 -// | | -// | | -// 2 6 -// | -// 3 -// | -// 4---+ -// | | -// 1 5 -// | -// 2 -// | -// 3 -fn test_find_ancestor_path_and_find_backable_chain( - #[case] has_cycle: bool, - #[case] expected_node_count: usize, -) { +#[test] +fn test_find_ancestor_path_and_find_backable_to_vec() { let para_id = ParaId::from(5u32); let relay_parent = Hash::repeat_byte(1); let required_parent: HeadData = vec![0xff].into(); - let max_depth = 7; + let max_depth = 5; let relay_parent_number = 0; let relay_parent_storage_root = Hash::repeat_byte(69); @@ -650,42 +1219,13 @@ fn test_find_ancestor_path_and_find_backable_chain( para_id, relay_parent, 0, - vec![0].into(), + vec![4].into(), vec![5].into(), 0, )); - // Candidate 6 - candidates.push(make_committed_candidate( - para_id, - relay_parent, - 0, - vec![1].into(), - vec![6].into(), - 0, - )); - // Candidate 7 - candidates.push(make_committed_candidate( - para_id, - relay_parent, - 0, - required_parent.clone(), - vec![7].into(), - 0, - )); - - if has_cycle { - candidates[4] = make_committed_candidate( - para_id, - relay_parent, - 0, - vec![3].into(), - vec![0].into(), // put the cycle here back to the output state of 0. - 0, - ); - } let base_constraints = make_constraints(0, vec![0], required_parent.clone()); - let mut storage = CandidateStorage::new(); + let mut storage = CandidateStorage::default(); let relay_parent_info = RelayChainBlockInfo { number: relay_parent_number, @@ -694,265 +1234,175 @@ fn test_find_ancestor_path_and_find_backable_chain( }; for (pvd, candidate) in candidates.iter() { - storage.add_candidate(candidate.clone(), pvd.clone()).unwrap(); + storage + .add_candidate(candidate.clone(), pvd.clone(), CandidateState::Seconded) + .unwrap(); } let candidates = candidates.into_iter().map(|(_pvd, candidate)| candidate).collect::>(); let scope = Scope::with_ancestors( para_id, - relay_parent_info, - base_constraints, + relay_parent_info.clone(), + base_constraints.clone(), vec![], max_depth, vec![], ) .unwrap(); - let tree = FragmentTree::populate(scope, &storage); - - assert_eq!(tree.candidates().collect::>().len(), candidates.len()); - assert_eq!(tree.nodes.len(), expected_node_count); - - // Do some common tests on both trees. - { - // No ancestors supplied. - assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root); - assert_eq!( - tree.find_backable_chain(Ancestors::new(), 4, |_| true), - [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - // Ancestor which is not part of the tree. Will be ignored. - let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect(); - assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root); - assert_eq!( - tree.find_backable_chain(ancestors, 4, |_| true), - [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - // A chain fork. - let ancestors: Ancestors = - [(candidates[0].hash()), (candidates[7].hash())].into_iter().collect(); - assert_eq!(tree.find_ancestor_path(ancestors.clone()), None); - assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); + let chain = FragmentChain::populate(scope, &storage); - // Ancestors which are part of the tree but don't form a path. Will be ignored. - let ancestors: Ancestors = - [candidates[1].hash(), candidates[2].hash()].into_iter().collect(); - assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root); - assert_eq!( - tree.find_backable_chain(ancestors, 4, |_| true), - [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - - // Valid ancestors. - let ancestors: Ancestors = [candidates[7].hash()].into_iter().collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[7].hash()); - assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); - - let ancestors: Ancestors = - [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] - .into_iter() - .collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[2].hash()); - assert_eq!( - tree.find_backable_chain(ancestors.clone(), 2, |_| true), - [3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() - ); + assert_eq!(candidates.len(), 6); + assert_eq!(chain.to_vec().len(), 6); - // Valid ancestors with candidates which have been omitted due to timeouts - let ancestors: Ancestors = - [candidates[0].hash(), candidates[2].hash()].into_iter().collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[0].hash()); - assert_eq!( - tree.find_backable_chain(ancestors, 3, |_| true), - [1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - - let ancestors: Ancestors = - [candidates[0].hash(), candidates[1].hash(), candidates[3].hash()] - .into_iter() - .collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[1].hash()); - if has_cycle { - assert_eq!( - tree.find_backable_chain(ancestors, 2, |_| true), - [2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - } else { - assert_eq!( - tree.find_backable_chain(ancestors, 4, |_| true), - [2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - } + // No ancestors supplied. + assert_eq!(chain.find_ancestor_path(Ancestors::new()), 0); + assert_eq!(chain.find_backable_chain(Ancestors::new(), 0, |_| true), vec![]); + assert_eq!( + chain.find_backable_chain(Ancestors::new(), 1, |_| true), + [0].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + assert_eq!( + chain.find_backable_chain(Ancestors::new(), 2, |_| true), + [0, 1].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + assert_eq!( + chain.find_backable_chain(Ancestors::new(), 5, |_| true), + [0, 1, 2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); - let ancestors: Ancestors = - [candidates[1].hash(), candidates[2].hash()].into_iter().collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - assert_eq!(res, NodePointer::Root); + for count in 6..10 { assert_eq!( - tree.find_backable_chain(ancestors, 4, |_| true), - [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + chain.find_backable_chain(Ancestors::new(), count, |_| true), + [0, 1, 2, 3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() ); + } - // Requested count is 0. - assert_eq!(tree.find_backable_chain(Ancestors::new(), 0, |_| true), vec![]); + assert_eq!( + chain.find_backable_chain(Ancestors::new(), 7, |_| true), + [0, 1, 2, 3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + assert_eq!( + chain.find_backable_chain(Ancestors::new(), 10, |_| true), + [0, 1, 2, 3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() + ); - let ancestors: Ancestors = - [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] - .into_iter() - .collect(); - assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]); + // Ancestor which is not part of the chain. Will be ignored. + let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect(); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 0); + assert_eq!( + chain.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + let ancestors: Ancestors = + [candidates[1].hash(), CandidateHash::default()].into_iter().collect(); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 0); + assert_eq!( + chain.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + let ancestors: Ancestors = + [candidates[0].hash(), CandidateHash::default()].into_iter().collect(); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 1); + assert_eq!( + chain.find_backable_chain(ancestors, 4, |_| true), + [1, 2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); - let ancestors: Ancestors = - [candidates[2].hash(), candidates[0].hash()].into_iter().collect(); - assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]); - } + // Ancestors which are part of the chain but don't form a path from root. Will be ignored. + let ancestors: Ancestors = [candidates[1].hash(), candidates[2].hash()].into_iter().collect(); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 0); + assert_eq!( + chain.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); - // Now do some tests only on the tree with cycles - if has_cycle { - // Exceeds the maximum tree depth. 0-1-2-3-4-1-2-3-4, when the tree stops at - // 0-1-2-3-4-1-2-3. - let ancestors: Ancestors = [ - candidates[0].hash(), - candidates[1].hash(), - candidates[2].hash(), - candidates[3].hash(), - candidates[4].hash(), - ] + // Valid ancestors. + let ancestors: Ancestors = [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] .into_iter() .collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[4].hash()); - assert_eq!( - tree.find_backable_chain(ancestors, 4, |_| true), - [1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); - - // 0-1-2. - let ancestors: Ancestors = - [candidates[0].hash(), candidates[1].hash(), candidates[2].hash()] - .into_iter() - .collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[2].hash()); - assert_eq!( - tree.find_backable_chain(ancestors.clone(), 1, |_| true), - [3].into_iter().map(|i| candidates[i].hash()).collect::>() - ); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 3); + assert_eq!( + chain.find_backable_chain(ancestors.clone(), 2, |_| true), + [3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + for count in 3..10 { assert_eq!( - tree.find_backable_chain(ancestors, 5, |_| true), - [3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + chain.find_backable_chain(ancestors.clone(), count, |_| true), + [3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() ); + } - // 0-1 - let ancestors: Ancestors = - [candidates[0].hash(), candidates[1].hash()].into_iter().collect(); - let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); - let candidate = &tree.nodes[res.unwrap_idx()]; - assert_eq!(candidate.candidate_hash, candidates[1].hash()); + // Valid ancestors with candidates which have been omitted due to timeouts + let ancestors: Ancestors = [candidates[0].hash(), candidates[2].hash()].into_iter().collect(); + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 1); + assert_eq!( + chain.find_backable_chain(ancestors.clone(), 3, |_| true), + [1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + assert_eq!( + chain.find_backable_chain(ancestors.clone(), 4, |_| true), + [1, 2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + for count in 5..10 { assert_eq!( - tree.find_backable_chain(ancestors, 6, |_| true), - [2, 3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>(), + chain.find_backable_chain(ancestors.clone(), count, |_| true), + [1, 2, 3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() ); + } - // For 0-1-2-3-4-5, there's more than 1 way of finding this path in - // the tree. `None` should be returned. The runtime should not have accepted this. - let ancestors: Ancestors = [ - candidates[0].hash(), - candidates[1].hash(), - candidates[2].hash(), - candidates[3].hash(), - candidates[4].hash(), - candidates[5].hash(), - ] + let ancestors: Ancestors = [candidates[0].hash(), candidates[1].hash(), candidates[3].hash()] .into_iter() .collect(); - let res = tree.find_ancestor_path(ancestors.clone()); - assert_eq!(res, None); - assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); - } -} - -#[test] -fn graceful_cycle_of_0() { - let mut storage = CandidateStorage::new(); - - let para_id = ParaId::from(5u32); - let relay_parent_a = Hash::repeat_byte(1); - - let (pvd_a, candidate_a) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0a].into(), // input same as output - 0, + assert_eq!(chain.find_ancestor_path(ancestors.clone()), 2); + assert_eq!( + chain.find_backable_chain(ancestors.clone(), 4, |_| true), + [2, 3, 4, 5].into_iter().map(|i| candidates[i].hash()).collect::>() ); - let candidate_a_hash = candidate_a.hash(); - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); - let relay_parent_a_info = RelayChainBlockInfo { - number: pvd_a.relay_parent_number, - hash: relay_parent_a, - storage_root: pvd_a.relay_parent_storage_root, - }; - - let max_depth = 4; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_a_info, - base_constraints, - pending_availability, - max_depth, - vec![], - ) - .unwrap(); - let tree = FragmentTree::populate(scope, &storage); - - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 1); - assert_eq!(tree.nodes.len(), max_depth + 1); - - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0)); - assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1)); - assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2)); - assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3)); - - assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[1].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[3].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash); + // Requested count is 0. + assert_eq!(chain.find_backable_chain(ancestors, 0, |_| true), vec![]); + // Stop when we've found a candidate for which pred returns false. + let ancestors: Ancestors = [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] + .into_iter() + .collect(); for count in 1..10 { assert_eq!( - tree.find_backable_chain(Ancestors::new(), count, |_| true), - iter::repeat(candidate_a_hash) - .take(std::cmp::min(count as usize, max_depth + 1)) - .collect::>() + // Stop at 4. + chain.find_backable_chain(ancestors.clone(), count, |hash| hash != + &candidates[4].hash()), + [3].into_iter().map(|i| candidates[i].hash()).collect::>() ); + } + + // Stop when we've found a candidate which is pending availability + { + let scope = Scope::with_ancestors( + para_id, + relay_parent_info.clone(), + base_constraints, + // Mark the third candidate as pending availability + vec![PendingAvailability { + candidate_hash: candidates[3].hash(), + relay_parent: relay_parent_info, + }], + max_depth, + vec![], + ) + .unwrap(); + let chain = FragmentChain::populate(scope, &storage); + let ancestors: Ancestors = + [candidates[0].hash(), candidates[1].hash()].into_iter().collect(); assert_eq!( - tree.find_backable_chain([candidate_a_hash].into_iter().collect(), count - 1, |_| true), - iter::repeat(candidate_a_hash) - .take(std::cmp::min(count as usize - 1, max_depth)) - .collect::>() + // Stop at 4. + chain.find_backable_chain(ancestors.clone(), 3, |_| true), + [2].into_iter().map(|i| candidates[i].hash()).collect::>() ); } } #[test] -fn graceful_cycle_of_1() { - let mut storage = CandidateStorage::new(); +fn hypothetical_membership() { + let mut storage = CandidateStorage::default(); let para_id = ParaId::from(5u32); let relay_parent_a = Hash::repeat_byte(1); @@ -962,7 +1412,7 @@ fn graceful_cycle_of_1() { relay_parent_a, 0, vec![0x0a].into(), - vec![0x0b].into(), // input same as output + vec![0x0b].into(), 0, ); let candidate_a_hash = candidate_a.hash(); @@ -972,13 +1422,12 @@ fn graceful_cycle_of_1() { relay_parent_a, 0, vec![0x0b].into(), - vec![0x0a].into(), // input same as output + vec![0x0c].into(), 0, ); let candidate_b_hash = candidate_b.hash(); let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); let relay_parent_a_info = RelayChainBlockInfo { number: pvd_a.relay_parent_number, @@ -987,182 +1436,153 @@ fn graceful_cycle_of_1() { }; let max_depth = 4; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); + storage.add_candidate(candidate_a, pvd_a, CandidateState::Seconded).unwrap(); + storage.add_candidate(candidate_b, pvd_b, CandidateState::Seconded).unwrap(); let scope = Scope::with_ancestors( para_id, - relay_parent_a_info, - base_constraints, - pending_availability, + relay_parent_a_info.clone(), + base_constraints.clone(), + vec![], max_depth, vec![], ) .unwrap(); - let tree = FragmentTree::populate(scope, &storage); + let chain = FragmentChain::populate(scope, &storage); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - assert_eq!(tree.nodes.len(), max_depth + 1); + assert_eq!(chain.to_vec().len(), 2); - assert_eq!(tree.nodes[0].parent, NodePointer::Root); - assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0)); - assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1)); - assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2)); - assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3)); + // Check candidates which are already present + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: candidate_a_hash, + }, + &storage, + )); + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: candidate_b_hash, + }, + &storage, + )); - assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash); - assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash); - assert_eq!(tree.nodes[3].candidate_hash, candidate_b_hash); - assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash); + // Forks not allowed. + assert!(!chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: CandidateHash(Hash::repeat_byte(21)), + }, + &storage, + )); + assert!(!chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: CandidateHash(Hash::repeat_byte(22)), + }, + &storage, + )); - assert_eq!(tree.find_backable_chain(Ancestors::new(), 1, |_| true), vec![candidate_a_hash],); - assert_eq!( - tree.find_backable_chain(Ancestors::new(), 2, |_| true), - vec![candidate_a_hash, candidate_b_hash], - ); - assert_eq!( - tree.find_backable_chain(Ancestors::new(), 3, |_| true), - vec![candidate_a_hash, candidate_b_hash, candidate_a_hash], - ); - assert_eq!( - tree.find_backable_chain([candidate_a_hash].into_iter().collect(), 2, |_| true), - vec![candidate_b_hash, candidate_a_hash], - ); + // Unknown candidate which builds on top of the current chain. + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0c]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: CandidateHash(Hash::repeat_byte(23)), + }, + &storage, + )); - assert_eq!( - tree.find_backable_chain(Ancestors::new(), 6, |_| true), - vec![ - candidate_a_hash, - candidate_b_hash, - candidate_a_hash, - candidate_b_hash, - candidate_a_hash - ], - ); + // Unknown unconnected candidate which may be valid. + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0e]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: CandidateHash(Hash::repeat_byte(23)), + }, + &storage, + )); - for count in 3..7 { - assert_eq!( - tree.find_backable_chain( - [candidate_a_hash, candidate_b_hash].into_iter().collect(), - count, - |_| true - ), - vec![candidate_a_hash, candidate_b_hash, candidate_a_hash], + // The number of unconnected candidates is limited (chain.len() + unconnected) <= max_depth + { + // C will be an unconnected candidate. + let (pvd_c, candidate_c) = make_committed_candidate( + para_id, + relay_parent_a, + 0, + vec![0x0e].into(), + vec![0x0f].into(), + 0, ); - } -} + let candidate_c_hash = candidate_c.hash(); -#[test] -fn hypothetical_depths_known_and_unknown() { - let mut storage = CandidateStorage::new(); - - let para_id = ParaId::from(5u32); - let relay_parent_a = Hash::repeat_byte(1); - - let (pvd_a, candidate_a) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0b].into(), // input same as output - 0, - ); - let candidate_a_hash = candidate_a.hash(); - - let (pvd_b, candidate_b) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0b].into(), - vec![0x0a].into(), // input same as output - 0, - ); - let candidate_b_hash = candidate_b.hash(); - - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); - - let relay_parent_a_info = RelayChainBlockInfo { - number: pvd_a.relay_parent_number, - hash: relay_parent_a, - storage_root: pvd_a.relay_parent_storage_root, - }; - - let max_depth = 4; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); - let scope = Scope::with_ancestors( - para_id, - relay_parent_a_info, - base_constraints, - pending_availability, - max_depth, - vec![], - ) - .unwrap(); - let tree = FragmentTree::populate(scope, &storage); + // Add an invalid candidate in the storage. This would introduce a fork. Just to test that + // it's ignored. + let (invalid_pvd, invalid_candidate) = make_committed_candidate( + para_id, + relay_parent_a, + 1, + vec![0x0a].into(), + vec![0x0b].into(), + 0, + ); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - assert_eq!(tree.nodes.len(), max_depth + 1); + let scope = Scope::with_ancestors( + para_id, + relay_parent_a_info, + base_constraints, + vec![], + 2, + vec![], + ) + .unwrap(); + let mut storage = storage.clone(); + storage.add_candidate(candidate_c, pvd_c, CandidateState::Seconded).unwrap(); - assert_eq!( - tree.hypothetical_depths( - candidate_a_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - false, - ), - vec![0, 2, 4], - ); + let chain = FragmentChain::populate(scope, &storage); + assert_eq!(chain.to_vec(), vec![candidate_a_hash, candidate_b_hash]); - assert_eq!( - tree.hypothetical_depths( - candidate_b_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - false, - ), - vec![1, 3], - ); + storage + .add_candidate(invalid_candidate, invalid_pvd, CandidateState::Seconded) + .unwrap(); - assert_eq!( - tree.hypothetical_depths( - CandidateHash(Hash::repeat_byte(21)), + // Check that C is accepted as a potential unconnected candidate. + assert!(!chain.hypothetical_membership( HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), - relay_parent: relay_parent_a, + parent_head_data_hash: HeadData::from(vec![0x0e]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_hash: candidate_c_hash, + candidate_para: para_id }, &storage, - false, - ), - vec![0, 2, 4], - ); + )); - assert_eq!( - tree.hypothetical_depths( - CandidateHash(Hash::repeat_byte(22)), + // Since C is already an unconnected candidate in the storage. + assert!(!chain.hypothetical_membership( HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), - relay_parent: relay_parent_a, + parent_head_data_hash: HeadData::from(vec![0x0f]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: CandidateHash(Hash::repeat_byte(23)), }, &storage, - false, - ), - vec![1, 3] - ); + )); + } } #[test] -fn hypothetical_depths_stricter_on_complete() { - let storage = CandidateStorage::new(); +fn hypothetical_membership_stricter_on_complete_candidates() { + let storage = CandidateStorage::default(); let para_id = ParaId::from(5u32); let relay_parent_a = Hash::repeat_byte(1); @@ -1197,161 +1617,31 @@ fn hypothetical_depths_stricter_on_complete() { vec![], ) .unwrap(); - let tree = FragmentTree::populate(scope, &storage); - - assert_eq!( - tree.hypothetical_depths( - candidate_a_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - false, - ), - vec![0], - ); - - assert!(tree - .hypothetical_depths( - candidate_a_hash, - HypotheticalCandidate::Complete { - receipt: Cow::Owned(candidate_a), - persisted_validation_data: Cow::Owned(pvd_a), - }, - &storage, - false, - ) - .is_empty()); -} - -#[test] -fn hypothetical_depths_backed_in_path() { - let mut storage = CandidateStorage::new(); - - let para_id = ParaId::from(5u32); - let relay_parent_a = Hash::repeat_byte(1); - - let (pvd_a, candidate_a) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0a].into(), - vec![0x0b].into(), - 0, - ); - let candidate_a_hash = candidate_a.hash(); - - let (pvd_b, candidate_b) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0b].into(), - vec![0x0c].into(), - 0, - ); - let candidate_b_hash = candidate_b.hash(); - - let (pvd_c, candidate_c) = make_committed_candidate( - para_id, - relay_parent_a, - 0, - vec![0x0b].into(), - vec![0x0d].into(), - 0, - ); - - let base_constraints = make_constraints(0, vec![0], vec![0x0a].into()); - let pending_availability = Vec::new(); - - let relay_parent_a_info = RelayChainBlockInfo { - number: pvd_a.relay_parent_number, - hash: relay_parent_a, - storage_root: pvd_a.relay_parent_storage_root, - }; - - let max_depth = 4; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); - storage.add_candidate(candidate_c, pvd_c).unwrap(); - - // `A` and `B` are backed, `C` is not. - storage.mark_backed(&candidate_a_hash); - storage.mark_backed(&candidate_b_hash); - - let scope = Scope::with_ancestors( - para_id, - relay_parent_a_info, - base_constraints, - pending_availability, - max_depth, - vec![], - ) - .unwrap(); - let tree = FragmentTree::populate(scope, &storage); - - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 3); - assert_eq!(tree.nodes.len(), 3); - - let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA)); - - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - true, - ), - vec![0], - ); - - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0c]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - true, - ), - vec![2], - ); - - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0d]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - true, - ), - Vec::::new(), - ); + let chain = FragmentChain::populate(scope, &storage); + + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_para: para_id, + candidate_hash: candidate_a_hash, + }, + &storage, + )); - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0d]).hash(), - relay_parent: relay_parent_a, - }, - &storage, - false, - ), - vec![2], // non-empty if `false`. - ); + assert!(!chain.hypothetical_membership( + HypotheticalCandidate::Complete { + receipt: Arc::new(candidate_a), + persisted_validation_data: pvd_a, + candidate_hash: candidate_a_hash, + }, + &storage, + )); } #[test] -fn pending_availability_in_scope() { - let mut storage = CandidateStorage::new(); +fn hypothetical_membership_with_pending_availability_in_scope() { + let mut storage = CandidateStorage::default(); let para_id = ParaId::from(5u32); let relay_parent_a = Hash::repeat_byte(1); @@ -1402,8 +1692,8 @@ fn pending_availability_in_scope() { }; let max_depth = 4; - storage.add_candidate(candidate_a, pvd_a).unwrap(); - storage.add_candidate(candidate_b, pvd_b).unwrap(); + storage.add_candidate(candidate_a, pvd_a, CandidateState::Seconded).unwrap(); + storage.add_candidate(candidate_b, pvd_b, CandidateState::Backed).unwrap(); storage.mark_backed(&candidate_a_hash); let scope = Scope::with_ancestors( @@ -1415,37 +1705,49 @@ fn pending_availability_in_scope() { vec![relay_parent_b_info], ) .unwrap(); - let tree = FragmentTree::populate(scope, &storage); + let chain = FragmentChain::populate(scope, &storage); - let candidates: Vec<_> = tree.candidates().collect(); - assert_eq!(candidates.len(), 2); - assert_eq!(tree.nodes.len(), 2); + assert_eq!(chain.to_vec().len(), 2); let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA)); - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), - relay_parent: relay_parent_c, - }, - &storage, - false, - ), - vec![1], - ); + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), + candidate_relay_parent: relay_parent_a, + candidate_hash: candidate_a_hash, + candidate_para: para_id + }, + &storage, + )); - assert_eq!( - tree.hypothetical_depths( - candidate_d_hash, - HypotheticalCandidate::Incomplete { - parent_head_data_hash: HeadData::from(vec![0x0c]).hash(), - relay_parent: relay_parent_b, - }, - &storage, - false, - ), - vec![2], - ); + assert!(!chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0a]).hash(), + candidate_relay_parent: relay_parent_c, + candidate_para: para_id, + candidate_hash: candidate_d_hash, + }, + &storage, + )); + + assert!(!chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0b]).hash(), + candidate_relay_parent: relay_parent_c, + candidate_para: para_id, + candidate_hash: candidate_d_hash, + }, + &storage, + )); + + assert!(chain.hypothetical_membership( + HypotheticalCandidate::Incomplete { + parent_head_data_hash: HeadData::from(vec![0x0c]).hash(), + candidate_relay_parent: relay_parent_b, + candidate_para: para_id, + candidate_hash: candidate_d_hash, + }, + &storage, + )); } diff --git a/polkadot/node/core/prospective-parachains/src/lib.rs b/polkadot/node/core/prospective-parachains/src/lib.rs index 0b1a2e034a2893e6397b986405df28a91776d819..d5bb5ff76ba8e8e603f2ab6b915b6c8fdb2d5f3c 100644 --- a/polkadot/node/core/prospective-parachains/src/lib.rs +++ b/polkadot/node/core/prospective-parachains/src/lib.rs @@ -21,22 +21,20 @@ //! This is the main coordinator of work within the node for the collation and //! backing phases of parachain consensus. //! -//! This is primarily an implementation of "Fragment Trees", as described in +//! This is primarily an implementation of "Fragment Chains", as described in //! [`polkadot_node_subsystem_util::inclusion_emulator`]. //! //! This subsystem also handles concerns such as the relay-chain being forkful and session changes. -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, -}; +use std::collections::{HashMap, HashSet}; +use fragment_chain::{FragmentChain, PotentialAddition}; use futures::{channel::oneshot, prelude::*}; use polkadot_node_subsystem::{ messages::{ - Ancestors, ChainApiMessage, FragmentTreeMembership, HypotheticalCandidate, - HypotheticalFrontierRequest, IntroduceCandidateRequest, ParentHeadData, + Ancestors, ChainApiMessage, HypotheticalCandidate, HypotheticalMembership, + HypotheticalMembershipRequest, IntroduceSecondedCandidateRequest, ParentHeadData, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, RuntimeApiMessage, RuntimeApiRequest, }, @@ -56,7 +54,8 @@ use polkadot_primitives::{ use crate::{ error::{FatalError, FatalResult, JfyiError, JfyiErrorResult, Result}, fragment_chain::{ - CandidateStorage, CandidateStorageInsertionError, FragmentTree, Scope as TreeScope, + CandidateState, CandidateStorage, CandidateStorageInsertionError, + Scope as FragmentChainScope, }, }; @@ -72,7 +71,7 @@ const LOG_TARGET: &str = "parachain::prospective-parachains"; struct RelayBlockViewData { // Scheduling info for paras and upcoming paras. - fragment_trees: HashMap, + fragment_chains: HashMap, pending_availability: HashSet, } @@ -141,12 +140,10 @@ async fn run_iteration( }, FromOrchestra::Signal(OverseerSignal::BlockFinalized(..)) => {}, FromOrchestra::Communication { msg } => match msg { - ProspectiveParachainsMessage::IntroduceCandidate(request, tx) => - handle_candidate_introduced(&mut *ctx, view, request, tx).await?, - ProspectiveParachainsMessage::CandidateSeconded(para, candidate_hash) => - handle_candidate_seconded(view, para, candidate_hash), + ProspectiveParachainsMessage::IntroduceSecondedCandidate(request, tx) => + handle_introduce_seconded_candidate(&mut *ctx, view, request, tx, metrics).await, ProspectiveParachainsMessage::CandidateBacked(para, candidate_hash) => - handle_candidate_backed(&mut *ctx, view, para, candidate_hash).await?, + handle_candidate_backed(&mut *ctx, view, para, candidate_hash).await, ProspectiveParachainsMessage::GetBackableCandidates( relay_parent, para, @@ -154,10 +151,8 @@ async fn run_iteration( ancestors, tx, ) => answer_get_backable_candidates(&view, relay_parent, para, count, ancestors, tx), - ProspectiveParachainsMessage::GetHypotheticalFrontier(request, tx) => - answer_hypothetical_frontier_request(&view, request, tx), - ProspectiveParachainsMessage::GetTreeMembership(para, candidate, tx) => - answer_tree_membership_request(&view, para, candidate, tx), + ProspectiveParachainsMessage::GetHypotheticalMembership(request, tx) => + answer_hypothetical_membership_request(&view, request, tx, metrics), ProspectiveParachainsMessage::GetMinimumRelayParents(relay_parent, tx) => answer_minimum_relay_parents_request(&view, relay_parent, tx), ProspectiveParachainsMessage::GetProspectiveValidationData(request, tx) => @@ -175,8 +170,8 @@ async fn handle_active_leaves_update( metrics: &Metrics, ) -> JfyiErrorResult<()> { // 1. clean up inactive leaves - // 2. determine all scheduled para at new block - // 3. construct new fragment tree for each para for each new leaf + // 2. determine all scheduled paras at the new block + // 3. construct new fragment chain for each para for each new leaf // 4. prune candidate storage. for deactivated in &update.deactivated { @@ -203,9 +198,7 @@ async fn handle_active_leaves_update( return Ok(()) }; - let mut pending_availability = HashSet::new(); - let scheduled_paras = - fetch_upcoming_paras(&mut *ctx, hash, &mut pending_availability).await?; + let scheduled_paras = fetch_upcoming_paras(&mut *ctx, hash).await?; let block_info: RelayChainBlockInfo = match fetch_block_info(&mut *ctx, &mut temp_header_cache, hash).await? { @@ -227,30 +220,30 @@ async fn handle_active_leaves_update( let ancestry = fetch_ancestry(&mut *ctx, &mut temp_header_cache, hash, allowed_ancestry_len).await?; + let mut all_pending_availability = HashSet::new(); + // Find constraints. - let mut fragment_trees = HashMap::new(); + let mut fragment_chains = HashMap::new(); for para in scheduled_paras { let candidate_storage = - view.candidate_storage.entry(para).or_insert_with(CandidateStorage::new); + view.candidate_storage.entry(para).or_insert_with(CandidateStorage::default); let backing_state = fetch_backing_state(&mut *ctx, hash, para).await?; - let (constraints, pending_availability) = match backing_state { - Some(c) => c, - None => { - // This indicates a runtime conflict of some kind. - - gum::debug!( - target: LOG_TARGET, - para_id = ?para, - relay_parent = ?hash, - "Failed to get inclusion backing state." - ); + let Some((constraints, pending_availability)) = backing_state else { + // This indicates a runtime conflict of some kind. + gum::debug!( + target: LOG_TARGET, + para_id = ?para, + relay_parent = ?hash, + "Failed to get inclusion backing state." + ); - continue - }, + continue }; + all_pending_availability.extend(pending_availability.iter().map(|c| c.candidate_hash)); + let pending_availability = preprocess_candidates_pending_availability( ctx, &mut temp_header_cache, @@ -261,15 +254,15 @@ async fn handle_active_leaves_update( let mut compact_pending = Vec::with_capacity(pending_availability.len()); for c in pending_availability { - let res = candidate_storage.add_candidate(c.candidate, c.persisted_validation_data); + let res = candidate_storage.add_candidate( + c.candidate, + c.persisted_validation_data, + CandidateState::Backed, + ); let candidate_hash = c.compact.candidate_hash; - compact_pending.push(c.compact); match res { - Ok(_) | Err(CandidateStorageInsertionError::CandidateAlreadyKnown(_)) => { - // Anything on-chain is guaranteed to be backed. - candidate_storage.mark_backed(&candidate_hash); - }, + Ok(_) | Err(CandidateStorageInsertionError::CandidateAlreadyKnown(_)) => {}, Err(err) => { gum::warn!( target: LOG_TARGET, @@ -278,11 +271,15 @@ async fn handle_active_leaves_update( ?err, "Scraped invalid candidate pending availability", ); + + break }, } + + compact_pending.push(c.compact); } - let scope = TreeScope::with_ancestors( + let scope = FragmentChainScope::with_ancestors( para, block_info.clone(), constraints, @@ -297,16 +294,26 @@ async fn handle_active_leaves_update( relay_parent = ?hash, min_relay_parent = scope.earliest_relay_parent().number, para_id = ?para, - "Creating fragment tree" + "Creating fragment chain" ); - let tree = FragmentTree::populate(scope, &*candidate_storage); + let chain = FragmentChain::populate(scope, &*candidate_storage); + + gum::trace!( + target: LOG_TARGET, + relay_parent = ?hash, + para_id = ?para, + "Populated fragment chain with {} candidates", + chain.len() + ); - fragment_trees.insert(para, tree); + fragment_chains.insert(para, chain); } - view.active_leaves - .insert(hash, RelayBlockViewData { fragment_trees, pending_availability }); + view.active_leaves.insert( + hash, + RelayBlockViewData { fragment_chains, pending_availability: all_pending_availability }, + ); } if !update.deactivated.is_empty() { @@ -318,18 +325,39 @@ async fn handle_active_leaves_update( } fn prune_view_candidate_storage(view: &mut View, metrics: &Metrics) { - metrics.time_prune_view_candidate_storage(); + let _timer = metrics.time_prune_view_candidate_storage(); let active_leaves = &view.active_leaves; let mut live_candidates = HashSet::new(); let mut live_paras = HashSet::new(); for sub_view in active_leaves.values() { - for (para_id, fragment_tree) in &sub_view.fragment_trees { - live_candidates.extend(fragment_tree.candidates()); + live_candidates.extend(sub_view.pending_availability.iter().cloned()); + + for (para_id, fragment_chain) in &sub_view.fragment_chains { + live_candidates.extend(fragment_chain.to_vec()); live_paras.insert(*para_id); } + } - live_candidates.extend(sub_view.pending_availability.iter().cloned()); + let connected_candidates_count = live_candidates.len(); + for (leaf, sub_view) in active_leaves.iter() { + for (para_id, fragment_chain) in &sub_view.fragment_chains { + if let Some(storage) = view.candidate_storage.get(para_id) { + let unconnected_potential = + fragment_chain.find_unconnected_potential_candidates(storage, None); + if !unconnected_potential.is_empty() { + gum::trace!( + target: LOG_TARGET, + ?leaf, + "Keeping {} unconnected candidates for paraid {} in storage: {:?}", + unconnected_potential.len(), + para_id, + unconnected_potential + ); + } + live_candidates.extend(unconnected_potential); + } + } } view.candidate_storage.retain(|para_id, storage| { @@ -343,7 +371,21 @@ fn prune_view_candidate_storage(view: &mut View, metrics: &Metrics) { // This maintains a convenient invariant that para-id storage exists // as long as there's an active head which schedules the para. true - }) + }); + + for (para_id, storage) in view.candidate_storage.iter() { + gum::trace!( + target: LOG_TARGET, + "Keeping a total of {} connected candidates for paraid {} in storage", + storage.candidates().count(), + para_id, + ); + } + + metrics.record_candidate_storage_size( + connected_candidates_count as u64, + live_candidates.len().saturating_sub(connected_candidates_count) as u64, + ); } struct ImportablePendingAvailability { @@ -365,22 +407,20 @@ async fn preprocess_candidates_pending_availability( let expected_count = pending_availability.len(); for (i, pending) in pending_availability.into_iter().enumerate() { - let relay_parent = - match fetch_block_info(ctx, cache, pending.descriptor.relay_parent).await? { - None => { - gum::debug!( - target: LOG_TARGET, - ?pending.candidate_hash, - ?pending.descriptor.para_id, - index = ?i, - ?expected_count, - "Had to stop processing pending candidates early due to missing info.", - ); + let Some(relay_parent) = + fetch_block_info(ctx, cache, pending.descriptor.relay_parent).await? + else { + gum::debug!( + target: LOG_TARGET, + ?pending.candidate_hash, + ?pending.descriptor.para_id, + index = ?i, + ?expected_count, + "Had to stop processing pending candidates early due to missing info.", + ); - break - }, - Some(b) => b, - }; + break + }; let next_required_parent = pending.commitments.head_data.clone(); importable.push(ImportablePendingAvailability { @@ -407,104 +447,139 @@ async fn preprocess_candidates_pending_availability( } #[overseer::contextbounds(ProspectiveParachains, prefix = self::overseer)] -async fn handle_candidate_introduced( +async fn handle_introduce_seconded_candidate( _ctx: &mut Context, view: &mut View, - request: IntroduceCandidateRequest, - tx: oneshot::Sender, -) -> JfyiErrorResult<()> { - let IntroduceCandidateRequest { + request: IntroduceSecondedCandidateRequest, + tx: oneshot::Sender, + metrics: &Metrics, +) { + let _timer = metrics.time_introduce_seconded_candidate(); + + let IntroduceSecondedCandidateRequest { candidate_para: para, candidate_receipt: candidate, persisted_validation_data: pvd, } = request; - // Add the candidate to storage. - // Then attempt to add it to all trees. - let storage = match view.candidate_storage.get_mut(¶) { - None => { - gum::warn!( - target: LOG_TARGET, - para_id = ?para, - candidate_hash = ?candidate.hash(), - "Received seconded candidate for inactive para", - ); + let Some(storage) = view.candidate_storage.get_mut(¶) else { + gum::warn!( + target: LOG_TARGET, + para_id = ?para, + candidate_hash = ?candidate.hash(), + "Received seconded candidate for inactive para", + ); - let _ = tx.send(Vec::new()); - return Ok(()) - }, - Some(storage) => storage, + let _ = tx.send(false); + return }; - let candidate_hash = match storage.add_candidate(candidate, pvd) { - Ok(c) => c, - Err(CandidateStorageInsertionError::CandidateAlreadyKnown(c)) => { - // Candidate known - return existing fragment tree membership. - let _ = tx.send(fragment_tree_membership(&view.active_leaves, para, c)); - return Ok(()) - }, - Err(CandidateStorageInsertionError::PersistedValidationDataMismatch) => { - // We can't log the candidate hash without either doing more ~expensive - // hashing but this branch indicates something is seriously wrong elsewhere - // so it's doubtful that it would affect debugging. + let parent_head_hash = pvd.parent_head.hash(); + let output_head_hash = Some(candidate.commitments.head_data.hash()); + + // We first introduce the candidate in the storage and then try to extend the chain. + // If the candidate gets included in the chain, we can keep it in storage. + // If it doesn't, check that it's still a potential candidate in at least one fragment chain. + // If it's not, we can remove it. + + let candidate_hash = + match storage.add_candidate(candidate.clone(), pvd, CandidateState::Seconded) { + Ok(c) => c, + Err(CandidateStorageInsertionError::CandidateAlreadyKnown(_)) => { + gum::debug!( + target: LOG_TARGET, + para = ?para, + "Attempting to introduce an already known candidate: {:?}", + candidate.hash() + ); + // Candidate already known. + let _ = tx.send(true); + return + }, + Err(CandidateStorageInsertionError::PersistedValidationDataMismatch) => { + // We can't log the candidate hash without either doing more ~expensive + // hashing but this branch indicates something is seriously wrong elsewhere + // so it's doubtful that it would affect debugging. - gum::warn!( + gum::warn!( + target: LOG_TARGET, + para = ?para, + "Received seconded candidate had mismatching validation data", + ); + + let _ = tx.send(false); + return + }, + }; + + let mut keep_in_storage = false; + for (relay_parent, leaf_data) in view.active_leaves.iter_mut() { + if let Some(chain) = leaf_data.fragment_chains.get_mut(¶) { + gum::trace!( target: LOG_TARGET, para = ?para, - "Received seconded candidate had mismatching validation data", + ?relay_parent, + "Candidates in chain before trying to introduce a new one: {:?}", + chain.to_vec() ); + chain.extend_from_storage(&*storage); + if chain.contains_candidate(&candidate_hash) { + keep_in_storage = true; - let _ = tx.send(Vec::new()); - return Ok(()) - }, - }; + gum::trace!( + target: LOG_TARGET, + ?relay_parent, + para = ?para, + ?candidate_hash, + "Added candidate to chain.", + ); + } else { + match chain.can_add_candidate_as_potential( + &storage, + &candidate_hash, + &candidate.descriptor.relay_parent, + parent_head_hash, + output_head_hash, + ) { + PotentialAddition::Anyhow => { + gum::trace!( + target: LOG_TARGET, + para = ?para, + ?relay_parent, + ?candidate_hash, + "Kept candidate as unconnected potential.", + ); - let mut membership = Vec::new(); - for (relay_parent, leaf_data) in &mut view.active_leaves { - if let Some(tree) = leaf_data.fragment_trees.get_mut(¶) { - tree.add_and_populate(candidate_hash, &*storage); - if let Some(depths) = tree.candidate(&candidate_hash) { - membership.push((*relay_parent, depths)); + keep_in_storage = true; + }, + _ => { + gum::trace!( + target: LOG_TARGET, + para = ?para, + ?relay_parent, + "Not introducing a new candidate: {:?}", + candidate_hash + ); + }, + } } } } - if membership.is_empty() { + // If there is at least one leaf where this candidate can be added or potentially added in the + // future, keep it in storage. + if !keep_in_storage { storage.remove_candidate(&candidate_hash); - } - - let _ = tx.send(membership); - - Ok(()) -} - -fn handle_candidate_seconded(view: &mut View, para: ParaId, candidate_hash: CandidateHash) { - let storage = match view.candidate_storage.get_mut(¶) { - None => { - gum::warn!( - target: LOG_TARGET, - para_id = ?para, - ?candidate_hash, - "Received instruction to second unknown candidate", - ); - return - }, - Some(storage) => storage, - }; - - if !storage.contains(&candidate_hash) { - gum::warn!( + gum::debug!( target: LOG_TARGET, - para_id = ?para, - ?candidate_hash, - "Received instruction to second unknown candidate", + para = ?para, + candidate = ?candidate_hash, + "Newly-seconded candidate cannot be kept under any active leaf", ); - - return } - storage.mark_seconded(&candidate_hash); + let _ = tx.send(keep_in_storage); } #[overseer::contextbounds(ProspectiveParachains, prefix = self::overseer)] @@ -513,19 +588,16 @@ async fn handle_candidate_backed( view: &mut View, para: ParaId, candidate_hash: CandidateHash, -) -> JfyiErrorResult<()> { - let storage = match view.candidate_storage.get_mut(¶) { - None => { - gum::warn!( - target: LOG_TARGET, - para_id = ?para, - ?candidate_hash, - "Received instruction to back unknown candidate", - ); +) { + let Some(storage) = view.candidate_storage.get_mut(¶) else { + gum::warn!( + target: LOG_TARGET, + para_id = ?para, + ?candidate_hash, + "Received instruction to back a candidate for unscheduled para", + ); - return Ok(()) - }, - Some(storage) => storage, + return }; if !storage.contains(&candidate_hash) { @@ -536,7 +608,7 @@ async fn handle_candidate_backed( "Received instruction to back unknown candidate", ); - return Ok(()) + return } if storage.is_backed(&candidate_hash) { @@ -547,11 +619,10 @@ async fn handle_candidate_backed( "Received redundant instruction to mark candidate as backed", ); - return Ok(()) + return } storage.mark_backed(&candidate_hash); - Ok(()) } fn answer_get_backable_candidates( @@ -562,62 +633,71 @@ fn answer_get_backable_candidates( ancestors: Ancestors, tx: oneshot::Sender>, ) { - let data = match view.active_leaves.get(&relay_parent) { - None => { - gum::debug!( - target: LOG_TARGET, - ?relay_parent, - para_id = ?para, - "Requested backable candidate for inactive relay-parent." - ); + let Some(data) = view.active_leaves.get(&relay_parent) else { + gum::debug!( + target: LOG_TARGET, + ?relay_parent, + para_id = ?para, + "Requested backable candidate for inactive relay-parent." + ); - let _ = tx.send(vec![]); - return - }, - Some(d) => d, + let _ = tx.send(vec![]); + return }; - let tree = match data.fragment_trees.get(¶) { - None => { - gum::debug!( - target: LOG_TARGET, - ?relay_parent, - para_id = ?para, - "Requested backable candidate for inactive para." - ); + let Some(chain) = data.fragment_chains.get(¶) else { + gum::debug!( + target: LOG_TARGET, + ?relay_parent, + para_id = ?para, + "Requested backable candidate for inactive para." + ); - let _ = tx.send(vec![]); - return - }, - Some(tree) => tree, + let _ = tx.send(vec![]); + return }; - let storage = match view.candidate_storage.get(¶) { - None => { - gum::warn!( - target: LOG_TARGET, - ?relay_parent, - para_id = ?para, - "No candidate storage for active para", - ); + let Some(storage) = view.candidate_storage.get(¶) else { + gum::warn!( + target: LOG_TARGET, + ?relay_parent, + para_id = ?para, + "No candidate storage for active para", + ); - let _ = tx.send(vec![]); - return - }, - Some(s) => s, + let _ = tx.send(vec![]); + return }; - let backable_candidates: Vec<_> = tree + gum::trace!( + target: LOG_TARGET, + ?relay_parent, + para_id = ?para, + "Candidate storage for para: {:?}", + storage.candidates().map(|candidate| candidate.hash()).collect::>() + ); + + gum::trace!( + target: LOG_TARGET, + ?relay_parent, + para_id = ?para, + "Candidate chain for para: {:?}", + chain.to_vec() + ); + + let backable_candidates: Vec<_> = chain .find_backable_chain(ancestors.clone(), count, |candidate| storage.is_backed(candidate)) .into_iter() .filter_map(|child_hash| { - storage.relay_parent_by_candidate_hash(&child_hash).map_or_else( + storage.relay_parent_of_candidate(&child_hash).map_or_else( || { + // Here, we'd actually need to trim all of the candidates that follow. Or + // not, the runtime will do this. Impossible scenario anyway. gum::error!( target: LOG_TARGET, ?child_hash, para_id = ?para, - "Candidate is present in fragment tree but not in candidate's storage!", + "Candidate is present in fragment chain but not in candidate's storage!", ); None }, @@ -639,6 +719,7 @@ fn answer_get_backable_candidates( target: LOG_TARGET, ?relay_parent, ?backable_candidates, + ?ancestors, "Found backable candidates", ); } @@ -646,58 +727,32 @@ fn answer_get_backable_candidates( let _ = tx.send(backable_candidates); } -fn answer_hypothetical_frontier_request( +fn answer_hypothetical_membership_request( view: &View, - request: HypotheticalFrontierRequest, - tx: oneshot::Sender>, + request: HypotheticalMembershipRequest, + tx: oneshot::Sender>, + metrics: &Metrics, ) { + let _timer = metrics.time_hypothetical_membership_request(); + let mut response = Vec::with_capacity(request.candidates.len()); for candidate in request.candidates { - response.push((candidate, Vec::new())); + response.push((candidate, vec![])); } - let required_active_leaf = request.fragment_tree_relay_parent; + let required_active_leaf = request.fragment_chain_relay_parent; for (active_leaf, leaf_view) in view .active_leaves .iter() .filter(|(h, _)| required_active_leaf.as_ref().map_or(true, |x| h == &x)) { - for &mut (ref c, ref mut membership) in &mut response { - let fragment_tree = match leaf_view.fragment_trees.get(&c.candidate_para()) { - None => continue, - Some(f) => f, - }; - let candidate_storage = match view.candidate_storage.get(&c.candidate_para()) { - None => continue, - Some(storage) => storage, - }; - - let candidate_hash = c.candidate_hash(); - let hypothetical = match c { - HypotheticalCandidate::Complete { receipt, persisted_validation_data, .. } => - fragment_chain::HypotheticalCandidate::Complete { - receipt: Cow::Borrowed(receipt), - persisted_validation_data: Cow::Borrowed(persisted_validation_data), - }, - HypotheticalCandidate::Incomplete { - parent_head_data_hash, - candidate_relay_parent, - .. - } => fragment_chain::HypotheticalCandidate::Incomplete { - relay_parent: *candidate_relay_parent, - parent_head_data_hash: *parent_head_data_hash, - }, - }; - - let depths = fragment_tree.hypothetical_depths( - candidate_hash, - hypothetical, - candidate_storage, - request.backed_in_path_only, - ); + for &mut (ref candidate, ref mut membership) in &mut response { + let para_id = &candidate.candidate_para(); + let Some(fragment_chain) = leaf_view.fragment_chains.get(para_id) else { continue }; + let Some(candidate_storage) = view.candidate_storage.get(para_id) else { continue }; - if !depths.is_empty() { - membership.push((*active_leaf, depths)); + if fragment_chain.hypothetical_membership(candidate.clone(), candidate_storage) { + membership.push(*active_leaf); } } } @@ -705,31 +760,6 @@ fn answer_hypothetical_frontier_request( let _ = tx.send(response); } -fn fragment_tree_membership( - active_leaves: &HashMap, - para: ParaId, - candidate: CandidateHash, -) -> FragmentTreeMembership { - let mut membership = Vec::new(); - for (relay_parent, view_data) in active_leaves { - if let Some(tree) = view_data.fragment_trees.get(¶) { - if let Some(depths) = tree.candidate(&candidate) { - membership.push((*relay_parent, depths)); - } - } - } - membership -} - -fn answer_tree_membership_request( - view: &View, - para: ParaId, - candidate: CandidateHash, - tx: oneshot::Sender, -) { - let _ = tx.send(fragment_tree_membership(&view.active_leaves, para, candidate)); -} - fn answer_minimum_relay_parents_request( view: &View, relay_parent: Hash, @@ -737,8 +767,8 @@ fn answer_minimum_relay_parents_request( ) { let mut v = Vec::new(); if let Some(leaf_data) = view.active_leaves.get(&relay_parent) { - for (para_id, fragment_tree) in &leaf_data.fragment_trees { - v.push((*para_id, fragment_tree.scope().earliest_relay_parent().number)); + for (para_id, fragment_chain) in &leaf_data.fragment_chains { + v.push((*para_id, fragment_chain.scope().earliest_relay_parent().number)); } } @@ -752,9 +782,9 @@ fn answer_prospective_validation_data_request( ) { // 1. Try to get the head-data from the candidate store if known. // 2. Otherwise, it might exist as the base in some relay-parent and we can find it by iterating - // fragment trees. + // fragment chains. // 3. Otherwise, it is unknown. - // 4. Also try to find the relay parent block info by scanning fragment trees. + // 4. Also try to find the relay parent block info by scanning fragment chains. // 5. If head data and relay parent block info are found - success. Otherwise, failure. let storage = match view.candidate_storage.get(&request.para_id) { @@ -776,35 +806,32 @@ fn answer_prospective_validation_data_request( let mut relay_parent_info = None; let mut max_pov_size = None; - for fragment_tree in view + for fragment_chain in view .active_leaves .values() - .filter_map(|x| x.fragment_trees.get(&request.para_id)) + .filter_map(|x| x.fragment_chains.get(&request.para_id)) { if head_data.is_some() && relay_parent_info.is_some() && max_pov_size.is_some() { break } if relay_parent_info.is_none() { - relay_parent_info = - fragment_tree.scope().ancestor_by_hash(&request.candidate_relay_parent); + relay_parent_info = fragment_chain.scope().ancestor(&request.candidate_relay_parent); } if head_data.is_none() { - let required_parent = &fragment_tree.scope().base_constraints().required_parent; + let required_parent = &fragment_chain.scope().base_constraints().required_parent; if required_parent.hash() == parent_head_data_hash { head_data = Some(required_parent.clone()); } } if max_pov_size.is_none() { - let contains_ancestor = fragment_tree - .scope() - .ancestor_by_hash(&request.candidate_relay_parent) - .is_some(); + let contains_ancestor = + fragment_chain.scope().ancestor(&request.candidate_relay_parent).is_some(); if contains_ancestor { // We are leaning hard on two assumptions here. - // 1. That the fragment tree never contains allowed relay-parents whose session for + // 1. That the fragment chain never contains allowed relay-parents whose session for // children is different from that of the base block's. // 2. That the max_pov_size is only configurable per session. - max_pov_size = Some(fragment_tree.scope().base_constraints().max_pov_size); + max_pov_size = Some(fragment_chain.scope().base_constraints().max_pov_size); } } } @@ -843,7 +870,6 @@ async fn fetch_backing_state( async fn fetch_upcoming_paras( ctx: &mut Context, relay_parent: Hash, - pending_availability: &mut HashSet, ) -> JfyiErrorResult> { let (tx, rx) = oneshot::channel(); @@ -860,8 +886,6 @@ async fn fetch_upcoming_paras( for core in cores { match core { CoreState::Occupied(occupied) => { - pending_availability.insert(occupied.candidate_hash); - if let Some(next_up_on_available) = occupied.next_up_on_available { upcoming.insert(next_up_on_available.para_id); } diff --git a/polkadot/node/core/prospective-parachains/src/metrics.rs b/polkadot/node/core/prospective-parachains/src/metrics.rs index 57061497a1c0d2923dedeea341a4cf4cf2ed8807..5abd9f56f306cdad515b93c794a51de516417b88 100644 --- a/polkadot/node/core/prospective-parachains/src/metrics.rs +++ b/polkadot/node/core/prospective-parachains/src/metrics.rs @@ -14,11 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use polkadot_node_subsystem_util::metrics::{self, prometheus}; +use polkadot_node_subsystem::prometheus::Opts; +use polkadot_node_subsystem_util::metrics::{ + self, + prometheus::{self, GaugeVec, U64}, +}; #[derive(Clone)] pub(crate) struct MetricsInner { - pub(crate) prune_view_candidate_storage: prometheus::Histogram, + prune_view_candidate_storage: prometheus::Histogram, + introduce_seconded_candidate: prometheus::Histogram, + hypothetical_membership: prometheus::Histogram, + candidate_storage_count: prometheus::GaugeVec, } /// Candidate backing metrics. @@ -34,6 +41,40 @@ impl Metrics { .as_ref() .map(|metrics| metrics.prune_view_candidate_storage.start_timer()) } + + /// Provide a timer for handling `IntroduceSecondedCandidate` which observes on drop. + pub fn time_introduce_seconded_candidate( + &self, + ) -> Option { + self.0 + .as_ref() + .map(|metrics| metrics.introduce_seconded_candidate.start_timer()) + } + + /// Provide a timer for handling `GetHypotheticalMembership` which observes on drop. + pub fn time_hypothetical_membership_request( + &self, + ) -> Option { + self.0.as_ref().map(|metrics| metrics.hypothetical_membership.start_timer()) + } + + /// Record the size of the candidate storage. First param is the connected candidates count, + /// second param is the unconnected candidates count. + pub fn record_candidate_storage_size(&self, connected_count: u64, unconnected_count: u64) { + self.0.as_ref().map(|metrics| { + metrics + .candidate_storage_count + .with_label_values(&["connected"]) + .set(connected_count) + }); + + self.0.as_ref().map(|metrics| { + metrics + .candidate_storage_count + .with_label_values(&["unconnected"]) + .set(unconnected_count) + }); + } } impl metrics::Metrics for Metrics { @@ -46,6 +87,30 @@ impl metrics::Metrics for Metrics { ))?, registry, )?, + introduce_seconded_candidate: prometheus::register( + prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( + "polkadot_parachain_prospective_parachains_introduce_seconded_candidate", + "Time spent within `prospective_parachains::handle_introduce_seconded_candidate`", + ))?, + registry, + )?, + hypothetical_membership: prometheus::register( + prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( + "polkadot_parachain_prospective_parachains_hypothetical_membership", + "Time spent responding to `GetHypotheticalMembership`", + ))?, + registry, + )?, + candidate_storage_count: prometheus::register( + GaugeVec::new( + Opts::new( + "polkadot_parachain_prospective_parachains_candidate_storage_count", + "Number of candidates present in the candidate storage, split by connected and unconnected" + ), + &["type"], + )?, + registry, + )?, }; Ok(Metrics(Some(metrics))) } diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 8989911a33239d3b6f775bcf6271c6f40d9a0bac..4bc47367278864e6f5e7136fe07a4fe1d1be88a5 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -19,7 +19,7 @@ use assert_matches::assert_matches; use polkadot_node_subsystem::{ errors::RuntimeApiError, messages::{ - AllMessages, HypotheticalFrontierRequest, ParentHeadData, ProspectiveParachainsMessage, + AllMessages, HypotheticalMembershipRequest, ParentHeadData, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, }, }; @@ -340,36 +340,42 @@ async fn deactivate_leaf(virtual_overseer: &mut VirtualOverseer, hash: Hash) { .await; } -async fn introduce_candidate( +async fn introduce_seconded_candidate( virtual_overseer: &mut VirtualOverseer, candidate: CommittedCandidateReceipt, pvd: PersistedValidationData, ) { - let req = IntroduceCandidateRequest { + let req = IntroduceSecondedCandidateRequest { candidate_para: candidate.descriptor().para_id, candidate_receipt: candidate, persisted_validation_data: pvd, }; - let (tx, _) = oneshot::channel(); + let (tx, rx) = oneshot::channel(); virtual_overseer .send(overseer::FromOrchestra::Communication { - msg: ProspectiveParachainsMessage::IntroduceCandidate(req, tx), + msg: ProspectiveParachainsMessage::IntroduceSecondedCandidate(req, tx), }) .await; + assert!(rx.await.unwrap()); } -async fn second_candidate( +async fn introduce_seconded_candidate_failed( virtual_overseer: &mut VirtualOverseer, candidate: CommittedCandidateReceipt, + pvd: PersistedValidationData, ) { + let req = IntroduceSecondedCandidateRequest { + candidate_para: candidate.descriptor().para_id, + candidate_receipt: candidate, + persisted_validation_data: pvd, + }; + let (tx, rx) = oneshot::channel(); virtual_overseer .send(overseer::FromOrchestra::Communication { - msg: ProspectiveParachainsMessage::CandidateSeconded( - candidate.descriptor.para_id, - candidate.hash(), - ), + msg: ProspectiveParachainsMessage::IntroduceSecondedCandidate(req, tx), }) .await; + assert!(!rx.await.unwrap()); } async fn back_candidate( @@ -387,22 +393,6 @@ async fn back_candidate( .await; } -async fn get_membership( - virtual_overseer: &mut VirtualOverseer, - para_id: ParaId, - candidate_hash: CandidateHash, - expected_membership_response: Vec<(Hash, Vec)>, -) { - let (tx, rx) = oneshot::channel(); - virtual_overseer - .send(overseer::FromOrchestra::Communication { - msg: ProspectiveParachainsMessage::GetTreeMembership(para_id, candidate_hash, tx), - }) - .await; - let resp = rx.await.unwrap(); - assert_eq!(resp, expected_membership_response); -} - async fn get_backable_candidates( virtual_overseer: &mut VirtualOverseer, leaf: &TestLeaf, @@ -420,42 +410,39 @@ async fn get_backable_candidates( }) .await; let resp = rx.await.unwrap(); - assert_eq!(resp.len(), expected_result.len()); assert_eq!(resp, expected_result); } -async fn get_hypothetical_frontier( +async fn get_hypothetical_membership( virtual_overseer: &mut VirtualOverseer, candidate_hash: CandidateHash, receipt: CommittedCandidateReceipt, persisted_validation_data: PersistedValidationData, - fragment_tree_relay_parent: Hash, - backed_in_path_only: bool, - expected_depths: Vec, + expected_membership: Vec, ) { let hypothetical_candidate = HypotheticalCandidate::Complete { candidate_hash, receipt: Arc::new(receipt), persisted_validation_data, }; - let request = HypotheticalFrontierRequest { + let request = HypotheticalMembershipRequest { candidates: vec![hypothetical_candidate.clone()], - fragment_tree_relay_parent: Some(fragment_tree_relay_parent), - backed_in_path_only, + fragment_chain_relay_parent: None, }; let (tx, rx) = oneshot::channel(); virtual_overseer .send(overseer::FromOrchestra::Communication { - msg: ProspectiveParachainsMessage::GetHypotheticalFrontier(request, tx), + msg: ProspectiveParachainsMessage::GetHypotheticalMembership(request, tx), }) .await; - let resp = rx.await.unwrap(); - let expected_frontier = if expected_depths.is_empty() { - vec![(hypothetical_candidate, vec![])] - } else { - vec![(hypothetical_candidate, vec![(fragment_tree_relay_parent, expected_depths)])] - }; - assert_eq!(resp, expected_frontier); + let mut resp = rx.await.unwrap(); + assert_eq!(resp.len(), 1); + let (candidate, membership) = resp.remove(0); + assert_eq!(candidate, hypothetical_candidate); + assert_eq!( + membership.into_iter().collect::>(), + expected_membership.into_iter().collect::>() + ); } async fn get_pvd( @@ -513,11 +500,11 @@ fn should_do_no_work_if_async_backing_disabled_for_leaf() { } // Send some candidates and make sure all are found: -// - Two for the same leaf A +// - Two for the same leaf A (one for parachain 1 and one for parachain 2) // - One for leaf B on parachain 1 // - One for leaf C on parachain 2 #[test] -fn send_candidates_and_check_if_found() { +fn introduce_candidates_basic() { let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -563,7 +550,7 @@ fn send_candidates_and_check_if_found() { test_state.validation_code_hash, ); let candidate_hash_a1 = candidate_a1.hash(); - let response_a1 = vec![(leaf_a.hash, vec![0])]; + let response_a1 = vec![(candidate_hash_a1, leaf_a.hash)]; // Candidate A2 let (candidate_a2, pvd_a2) = make_candidate( @@ -575,7 +562,7 @@ fn send_candidates_and_check_if_found() { test_state.validation_code_hash, ); let candidate_hash_a2 = candidate_a2.hash(); - let response_a2 = vec![(leaf_a.hash, vec![0])]; + let response_a2 = vec![(candidate_hash_a2, leaf_a.hash)]; // Candidate B let (candidate_b, pvd_b) = make_candidate( @@ -587,7 +574,7 @@ fn send_candidates_and_check_if_found() { test_state.validation_code_hash, ); let candidate_hash_b = candidate_b.hash(); - let response_b = vec![(leaf_b.hash, vec![0])]; + let response_b = vec![(candidate_hash_b, leaf_b.hash)]; // Candidate C let (candidate_c, pvd_c) = make_candidate( @@ -599,25 +586,78 @@ fn send_candidates_and_check_if_found() { test_state.validation_code_hash, ); let candidate_hash_c = candidate_c.hash(); - let response_c = vec![(leaf_c.hash, vec![0])]; + let response_c = vec![(candidate_hash_c, leaf_c.hash)]; // Introduce candidates. - introduce_candidate(&mut virtual_overseer, candidate_a1, pvd_a1).await; - introduce_candidate(&mut virtual_overseer, candidate_a2, pvd_a2).await; - introduce_candidate(&mut virtual_overseer, candidate_b, pvd_b).await; - introduce_candidate(&mut virtual_overseer, candidate_c, pvd_c).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a1.clone(), pvd_a1).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a2.clone(), pvd_a2).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_c.clone(), pvd_c).await; + + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a1, candidate_hash_a1).await; + back_candidate(&mut virtual_overseer, &candidate_a2, candidate_hash_a2).await; + back_candidate(&mut virtual_overseer, &candidate_b, candidate_hash_b).await; + back_candidate(&mut virtual_overseer, &candidate_c, candidate_hash_c).await; // Check candidate tree membership. - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a1, response_a1).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_a2, response_a2).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_b, response_b).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_c, response_c).await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + response_a1, + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::default(), + 5, + response_a2, + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 1.into(), + Ancestors::default(), + 5, + response_b, + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_c, + 2.into(), + Ancestors::default(), + 5, + response_c, + ) + .await; + + // Check membership on other leaves. + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 2.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; - // The candidates should not be found on other parachains. - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_a1, vec![]).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a2, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_b, vec![]).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_c, vec![]).await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_c, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; virtual_overseer }); @@ -629,10 +669,8 @@ fn send_candidates_and_check_if_found() { assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (2, 2)); } -// Send some candidates, check if the candidate won't be found once its relay parent leaves the -// view. #[test] -fn check_candidate_parent_leaving_view() { +fn introduce_candidate_multiple_times() { let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -644,32 +682,11 @@ fn check_candidate_parent_leaving_view() { (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), ], }; - // Leaf B - let leaf_b = TestLeaf { - number: 101, - hash: Hash::from_low_u64_be(131), - para_data: vec![ - (1.into(), PerParaData::new(99, HeadData(vec![3, 4, 5]))), - (2.into(), PerParaData::new(101, HeadData(vec![4, 5, 6]))), - ], - }; - // Leaf C - let leaf_c = TestLeaf { - number: 102, - hash: Hash::from_low_u64_be(132), - para_data: vec![ - (1.into(), PerParaData::new(102, HeadData(vec![5, 6, 7]))), - (2.into(), PerParaData::new(98, HeadData(vec![6, 7, 8]))), - ], - }; - // Activate leaves. activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; - activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; - activate_leaf(&mut virtual_overseer, &leaf_c, &test_state).await; - // Candidate A1 - let (candidate_a1, pvd_a1) = make_candidate( + // Candidate A. + let (candidate_a, pvd_a) = make_candidate( leaf_a.hash, leaf_a.number, 1.into(), @@ -677,86 +694,45 @@ fn check_candidate_parent_leaving_view() { HeadData(vec![1]), test_state.validation_code_hash, ); - let candidate_hash_a1 = candidate_a1.hash(); - - // Candidate A2 - let (candidate_a2, pvd_a2) = make_candidate( - leaf_a.hash, - leaf_a.number, - 2.into(), - HeadData(vec![2, 3, 4]), - HeadData(vec![2]), - test_state.validation_code_hash, - ); - let candidate_hash_a2 = candidate_a2.hash(); - - // Candidate B - let (candidate_b, pvd_b) = make_candidate( - leaf_b.hash, - leaf_b.number, - 1.into(), - HeadData(vec![3, 4, 5]), - HeadData(vec![3]), - test_state.validation_code_hash, - ); - let candidate_hash_b = candidate_b.hash(); - let response_b = vec![(leaf_b.hash, vec![0])]; - - // Candidate C - let (candidate_c, pvd_c) = make_candidate( - leaf_c.hash, - leaf_c.number, - 2.into(), - HeadData(vec![6, 7, 8]), - HeadData(vec![4]), - test_state.validation_code_hash, - ); - let candidate_hash_c = candidate_c.hash(); - let response_c = vec![(leaf_c.hash, vec![0])]; + let candidate_hash_a = candidate_a.hash(); + let response_a = vec![(candidate_hash_a, leaf_a.hash)]; // Introduce candidates. - introduce_candidate(&mut virtual_overseer, candidate_a1, pvd_a1).await; - introduce_candidate(&mut virtual_overseer, candidate_a2, pvd_a2).await; - introduce_candidate(&mut virtual_overseer, candidate_b, pvd_b).await; - introduce_candidate(&mut virtual_overseer, candidate_c, pvd_c).await; - - // Deactivate leaf A. - deactivate_leaf(&mut virtual_overseer, leaf_a.hash).await; - - // Candidates A1 and A2 should be gone. Candidates B and C should remain. - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a1, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_a2, vec![]).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_b, response_b).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_c, response_c.clone()).await; - - // Deactivate leaf B. - deactivate_leaf(&mut virtual_overseer, leaf_b.hash).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; - // Candidate B should be gone, C should remain. - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a1, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_a2, vec![]).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_b, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_c, response_c).await; + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; - // Deactivate leaf C. - deactivate_leaf(&mut virtual_overseer, leaf_c.hash).await; + // Check candidate tree membership. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + response_a, + ) + .await; - // Candidate C should be gone. - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a1, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_a2, vec![]).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_b, vec![]).await; - get_membership(&mut virtual_overseer, 2.into(), candidate_hash_c, vec![]).await; + // Introduce the same candidate multiple times. It'll return true but it won't be added. + // We'll check below that the candidate count remains 1. + for _ in 0..5 { + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; + } virtual_overseer }); - assert_eq!(view.active_leaves.len(), 0); - assert_eq!(view.candidate_storage.len(), 0); + assert_eq!(view.active_leaves.len(), 1); + assert_eq!(view.candidate_storage.len(), 2); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (1, 1)); + assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); } -// Introduce a candidate to multiple forks, see how the membership is returned. #[test] -fn check_candidate_on_multiple_forks() { +fn fragment_chain_length_is_bounded() { let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -768,31 +744,16 @@ fn check_candidate_on_multiple_forks() { (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), ], }; - // Leaf B - let leaf_b = TestLeaf { - number: 101, - hash: Hash::from_low_u64_be(131), - para_data: vec![ - (1.into(), PerParaData::new(99, HeadData(vec![3, 4, 5]))), - (2.into(), PerParaData::new(101, HeadData(vec![4, 5, 6]))), - ], - }; - // Leaf C - let leaf_c = TestLeaf { - number: 102, - hash: Hash::from_low_u64_be(132), - para_data: vec![ - (1.into(), PerParaData::new(102, HeadData(vec![5, 6, 7]))), - (2.into(), PerParaData::new(98, HeadData(vec![6, 7, 8]))), - ], - }; - // Activate leaves. - activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; - activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; - activate_leaf(&mut virtual_overseer, &leaf_c, &test_state).await; + activate_leaf_with_params( + &mut virtual_overseer, + &leaf_a, + &test_state, + AsyncBackingParams { max_candidate_depth: 1, allowed_ancestry_len: 3 }, + ) + .await; - // Candidate on leaf A. + // Candidates A, B and C form a chain. let (candidate_a, pvd_a) = make_candidate( leaf_a.hash, leaf_a.number, @@ -801,56 +762,59 @@ fn check_candidate_on_multiple_forks() { HeadData(vec![1]), test_state.validation_code_hash, ); - let candidate_hash_a = candidate_a.hash(); - let response_a = vec![(leaf_a.hash, vec![0])]; - - // Candidate on leaf B. let (candidate_b, pvd_b) = make_candidate( - leaf_b.hash, - leaf_b.number, + leaf_a.hash, + leaf_a.number, 1.into(), - HeadData(vec![3, 4, 5]), HeadData(vec![1]), + HeadData(vec![2]), test_state.validation_code_hash, ); - let candidate_hash_b = candidate_b.hash(); - let response_b = vec![(leaf_b.hash, vec![0])]; - - // Candidate on leaf C. let (candidate_c, pvd_c) = make_candidate( - leaf_c.hash, - leaf_c.number, + leaf_a.hash, + leaf_a.number, 1.into(), - HeadData(vec![5, 6, 7]), - HeadData(vec![1]), + HeadData(vec![2]), + HeadData(vec![3]), test_state.validation_code_hash, ); - let candidate_hash_c = candidate_c.hash(); - let response_c = vec![(leaf_c.hash, vec![0])]; - // Introduce candidates on all three leaves. - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - introduce_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; - introduce_candidate(&mut virtual_overseer, candidate_c.clone(), pvd_c).await; + // Introduce candidates A and B. Since max depth is 1, only these two will be allowed. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b.clone()) + .await; + + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a, candidate_a.hash()).await; + back_candidate(&mut virtual_overseer, &candidate_b, candidate_b.hash()).await; // Check candidate tree membership. - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_a, response_a).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_b, response_b).await; - get_membership(&mut virtual_overseer, 1.into(), candidate_hash_c, response_c).await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![(candidate_a.hash(), leaf_a.hash), (candidate_b.hash(), leaf_a.hash)], + ) + .await; + + // Introducing C will fail. + introduce_seconded_candidate_failed(&mut virtual_overseer, candidate_c, pvd_c.clone()) + .await; virtual_overseer }); - assert_eq!(view.active_leaves.len(), 3); + assert_eq!(view.active_leaves.len(), 1); assert_eq!(view.candidate_storage.len(), 2); - // Three parents and three candidates on para 1. - assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (3, 3)); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (2, 2)); assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); } -// Backs some candidates and tests `GetBackableCandidates` when requesting a single candidate. #[test] -fn check_backable_query_single_candidate() { +fn unconnected_candidate_count_is_bounded() { let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -862,54 +826,534 @@ fn check_backable_query_single_candidate() { (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), ], }; - // Activate leaves. - activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + activate_leaf_with_params( + &mut virtual_overseer, + &leaf_a, + &test_state, + AsyncBackingParams { max_candidate_depth: 1, allowed_ancestry_len: 3 }, + ) + .await; - // Candidate A + // Candidates A, B and C are all potential candidates but don't form a chain. let (candidate_a, pvd_a) = make_candidate( leaf_a.hash, leaf_a.number, 1.into(), - HeadData(vec![1, 2, 3]), HeadData(vec![1]), + HeadData(vec![2]), test_state.validation_code_hash, ); - let candidate_hash_a = candidate_a.hash(); - - // Candidate B - let (mut candidate_b, pvd_b) = make_candidate( + let (candidate_b, pvd_b) = make_candidate( leaf_a.hash, leaf_a.number, 1.into(), - HeadData(vec![1]), - HeadData(vec![2]), + HeadData(vec![3]), + HeadData(vec![4]), + test_state.validation_code_hash, + ); + let (candidate_c, pvd_c) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![4]), + HeadData(vec![5]), test_state.validation_code_hash, ); - // Set a field to make this candidate unique. - candidate_b.descriptor.para_head = Hash::from_low_u64_le(1000); - let candidate_hash_b = candidate_b.hash(); - - // Introduce candidates. - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - introduce_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; - // Should not get any backable candidates. - get_backable_candidates( + // Introduce candidates A and B. Although max depth is 1 (which should allow for two + // candidates), only 1 is allowed, because the last candidate must be a connected candidate. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; + introduce_seconded_candidate_failed( &mut virtual_overseer, - &leaf_a, + candidate_b.clone(), + pvd_b.clone(), + ) + .await; + + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a, candidate_a.hash()).await; + + // Check candidate tree membership. Should be empty. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + + // Introducing C will also fail. + introduce_seconded_candidate_failed(&mut virtual_overseer, candidate_c, pvd_c.clone()) + .await; + + virtual_overseer + }); + + assert_eq!(view.active_leaves.len(), 1); + assert_eq!(view.candidate_storage.len(), 2); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (1, 1)); + assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); +} + +// Send some candidates, check if the candidate won't be found once its relay parent leaves the +// view. +#[test] +fn introduce_candidate_parent_leaving_view() { + let test_state = TestState::default(); + let view = test_harness(|mut virtual_overseer| async move { + // Leaf A + let leaf_a = TestLeaf { + number: 100, + hash: Hash::from_low_u64_be(130), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; + // Leaf B + let leaf_b = TestLeaf { + number: 101, + hash: Hash::from_low_u64_be(131), + para_data: vec![ + (1.into(), PerParaData::new(99, HeadData(vec![3, 4, 5]))), + (2.into(), PerParaData::new(101, HeadData(vec![4, 5, 6]))), + ], + }; + // Leaf C + let leaf_c = TestLeaf { + number: 102, + hash: Hash::from_low_u64_be(132), + para_data: vec![ + (1.into(), PerParaData::new(102, HeadData(vec![5, 6, 7]))), + (2.into(), PerParaData::new(98, HeadData(vec![6, 7, 8]))), + ], + }; + + // Activate leaves. + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; + activate_leaf(&mut virtual_overseer, &leaf_c, &test_state).await; + + // Candidate A1 + let (candidate_a1, pvd_a1) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1, 2, 3]), + HeadData(vec![1]), + test_state.validation_code_hash, + ); + let candidate_hash_a1 = candidate_a1.hash(); + + // Candidate A2 + let (candidate_a2, pvd_a2) = make_candidate( + leaf_a.hash, + leaf_a.number, + 2.into(), + HeadData(vec![2, 3, 4]), + HeadData(vec![2]), + test_state.validation_code_hash, + ); + let candidate_hash_a2 = candidate_a2.hash(); + + // Candidate B + let (candidate_b, pvd_b) = make_candidate( + leaf_b.hash, + leaf_b.number, + 1.into(), + HeadData(vec![3, 4, 5]), + HeadData(vec![3]), + test_state.validation_code_hash, + ); + let candidate_hash_b = candidate_b.hash(); + let response_b = vec![(candidate_hash_b, leaf_b.hash)]; + + // Candidate C + let (candidate_c, pvd_c) = make_candidate( + leaf_c.hash, + leaf_c.number, + 2.into(), + HeadData(vec![6, 7, 8]), + HeadData(vec![4]), + test_state.validation_code_hash, + ); + let candidate_hash_c = candidate_c.hash(); + let response_c = vec![(candidate_hash_c, leaf_c.hash)]; + + // Introduce candidates. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a1.clone(), pvd_a1).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a2.clone(), pvd_a2).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_c.clone(), pvd_c).await; + + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a1, candidate_hash_a1).await; + back_candidate(&mut virtual_overseer, &candidate_a2, candidate_hash_a2).await; + back_candidate(&mut virtual_overseer, &candidate_b, candidate_hash_b).await; + back_candidate(&mut virtual_overseer, &candidate_c, candidate_hash_c).await; + + // Deactivate leaf A. + deactivate_leaf(&mut virtual_overseer, leaf_a.hash).await; + + // Candidates A1 and A2 should be gone. Candidates B and C should remain. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 1.into(), + Ancestors::default(), + 5, + response_b, + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_c, + 2.into(), + Ancestors::default(), + 5, + response_c.clone(), + ) + .await; + + // Deactivate leaf B. + deactivate_leaf(&mut virtual_overseer, leaf_b.hash).await; + + // Candidate B should be gone, C should remain. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_c, + 2.into(), + Ancestors::default(), + 5, + response_c, + ) + .await; + + // Deactivate leaf C. + deactivate_leaf(&mut virtual_overseer, leaf_c.hash).await; + + // Candidate C should be gone. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 1.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_c, + 2.into(), + Ancestors::default(), + 5, + vec![], + ) + .await; + + virtual_overseer + }); + + assert_eq!(view.active_leaves.len(), 0); + assert_eq!(view.candidate_storage.len(), 0); +} + +// Introduce a candidate to multiple forks, see how the membership is returned. +#[test] +fn introduce_candidate_on_multiple_forks() { + let test_state = TestState::default(); + let view = test_harness(|mut virtual_overseer| async move { + // Leaf B + let leaf_b = TestLeaf { + number: 101, + hash: Hash::from_low_u64_be(131), + para_data: vec![ + (1.into(), PerParaData::new(99, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(101, HeadData(vec![4, 5, 6]))), + ], + }; + // Leaf A + let leaf_a = TestLeaf { + number: 100, + hash: get_parent_hash(leaf_b.hash), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; + + // Activate leaves. + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; + + // Candidate built on leaf A. + let (candidate_a, pvd_a) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1, 2, 3]), + HeadData(vec![1]), + test_state.validation_code_hash, + ); + let candidate_hash_a = candidate_a.hash(); + let response_a = vec![(candidate_hash_a, leaf_a.hash)]; + + // Introduce candidate. Should be present on leaves B and C. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; + back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; + + // Check candidate tree membership. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + response_a.clone(), + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + 1.into(), + Ancestors::default(), + 5, + response_a.clone(), + ) + .await; + + virtual_overseer + }); + + assert_eq!(view.active_leaves.len(), 2); + assert_eq!(view.candidate_storage.len(), 2); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (1, 1)); + assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); +} + +#[test] +fn unconnected_candidates_become_connected() { + let test_state = TestState::default(); + let view = test_harness(|mut virtual_overseer| async move { + // Leaf A + let leaf_a = TestLeaf { + number: 100, + hash: Hash::from_low_u64_be(130), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; + // Activate leaves. + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + + // Candidates A, B, C and D all form a chain, but we'll first introduce A, C and D. + let (candidate_a, pvd_a) = make_candidate( + leaf_a.hash, + leaf_a.number, 1.into(), - vec![candidate_hash_a].into_iter().collect(), - 1, - vec![], + HeadData(vec![1, 2, 3]), + HeadData(vec![1]), + test_state.validation_code_hash, + ); + let (candidate_b, pvd_b) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1]), + HeadData(vec![2]), + test_state.validation_code_hash, + ); + let (candidate_c, pvd_c) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![2]), + HeadData(vec![3]), + test_state.validation_code_hash, + ); + let (candidate_d, pvd_d) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![3]), + HeadData(vec![4]), + test_state.validation_code_hash, + ); + + // Introduce candidates A, C and D. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_c.clone(), pvd_c.clone()) + .await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_d.clone(), pvd_d.clone()) + .await; + + // Back candidates. Otherwise, we cannot check membership with GetBackableCandidates. + back_candidate(&mut virtual_overseer, &candidate_a, candidate_a.hash()).await; + back_candidate(&mut virtual_overseer, &candidate_c, candidate_c.hash()).await; + back_candidate(&mut virtual_overseer, &candidate_d, candidate_d.hash()).await; + + // Check candidate tree membership. Only A should be returned. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![(candidate_a.hash(), leaf_a.hash)], + ) + .await; + + // Introduce C and check membership. Full chain should be returned. + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b.clone()) + .await; + back_candidate(&mut virtual_overseer, &candidate_b, candidate_b.hash()).await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::default(), + 5, + vec![ + (candidate_a.hash(), leaf_a.hash), + (candidate_b.hash(), leaf_a.hash), + (candidate_c.hash(), leaf_a.hash), + (candidate_d.hash(), leaf_a.hash), + ], ) .await; + + virtual_overseer + }); + + assert_eq!(view.active_leaves.len(), 1); + assert_eq!(view.candidate_storage.len(), 2); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (4, 4)); + assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); +} + +// Backs some candidates and tests `GetBackableCandidates` when requesting a single candidate. +#[test] +fn check_backable_query_single_candidate() { + let test_state = TestState::default(); + let view = test_harness(|mut virtual_overseer| async move { + // Leaf A + let leaf_a = TestLeaf { + number: 100, + hash: Hash::from_low_u64_be(130), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; + + // Activate leaves. + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + + // Candidate A + let (candidate_a, pvd_a) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1, 2, 3]), + HeadData(vec![1]), + test_state.validation_code_hash, + ); + let candidate_hash_a = candidate_a.hash(); + + // Candidate B + let (mut candidate_b, pvd_b) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1]), + HeadData(vec![2]), + test_state.validation_code_hash, + ); + // Set a field to make this candidate unique. + candidate_b.descriptor.para_head = Hash::from_low_u64_le(1000); + let candidate_hash_b = candidate_b.hash(); + + // Introduce candidates. + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; + + // Should not get any backable candidates. get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), vec![candidate_hash_a].into_iter().collect(), - 0, + 1, vec![], ) .await; @@ -917,23 +1361,17 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - Ancestors::new(), + vec![candidate_hash_a].into_iter().collect(), 0, vec![], ) .await; - - // Second candidates. - second_candidate(&mut virtual_overseer, candidate_a.clone()).await; - second_candidate(&mut virtual_overseer, candidate_b.clone()).await; - - // Should not get any backable candidates. get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a].into_iter().collect(), - 1, + Ancestors::new(), + 0, vec![], ) .await; @@ -1019,392 +1457,327 @@ fn check_backable_query_multiple_candidates() { // Set a field to make this candidate unique. candidate.descriptor.para_head = Hash::from_low_u64_le($index); let candidate_hash = candidate.hash(); - introduce_candidate(&mut $virtual_overseer, candidate.clone(), pvd).await; - second_candidate(&mut $virtual_overseer, candidate.clone()).await; + introduce_seconded_candidate(&mut $virtual_overseer, candidate.clone(), pvd).await; back_candidate(&mut $virtual_overseer, &candidate, candidate_hash).await; (candidate, candidate_hash) }}; } - // Parachain 1 looks like this: - // +---A----+ - // | | - // +----B---+ C - // | | | | - // D E F H - // | | - // G I - // | - // J - { - let test_state = TestState::default(); - let view = test_harness(|mut virtual_overseer| async move { - // Leaf A - let leaf_a = TestLeaf { - number: 100, - hash: Hash::from_low_u64_be(130), - para_data: vec![ - (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), - (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), - ], - }; - - // Activate leaves. - activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; - - // Candidate A - let (candidate_a, pvd_a) = make_candidate( - leaf_a.hash, - leaf_a.number, - 1.into(), - HeadData(vec![1, 2, 3]), - HeadData(vec![1]), - test_state.validation_code_hash, - ); - let candidate_hash_a = candidate_a.hash(); - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - second_candidate(&mut virtual_overseer, candidate_a.clone()).await; - back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; - - let (candidate_b, candidate_hash_b) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_a, 2); - let (candidate_c, candidate_hash_c) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_a, 3); - let (_candidate_d, candidate_hash_d) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 4); - let (_candidate_e, candidate_hash_e) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 5); - let (candidate_f, candidate_hash_f) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 6); - let (_candidate_g, candidate_hash_g) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_f, 7); - let (candidate_h, candidate_hash_h) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_c, 8); - let (candidate_i, candidate_hash_i) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_h, 9); - let (_candidate_j, candidate_hash_j) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_i, 10); - - // Should not get any backable candidates for the other para. - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 2.into(), - Ancestors::new(), - 1, - vec![], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 2.into(), - Ancestors::new(), - 5, - vec![], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 2.into(), - vec![candidate_hash_a].into_iter().collect(), - 1, - vec![], - ) - .await; - - // Test various scenarios with various counts. - - // empty required_path - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - Ancestors::new(), - 1, - vec![(candidate_hash_a, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - Ancestors::new(), - 4, - vec![ - (candidate_hash_a, leaf_a.hash), - (candidate_hash_b, leaf_a.hash), - (candidate_hash_f, leaf_a.hash), - (candidate_hash_g, leaf_a.hash), - ], - ) - .await; - } - - // required path of 1 - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a].into_iter().collect(), - 1, - vec![(candidate_hash_b, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a].into_iter().collect(), - 3, - vec![ - (candidate_hash_b, leaf_a.hash), - (candidate_hash_f, leaf_a.hash), - (candidate_hash_g, leaf_a.hash), - ], - ) - .await; + let test_state = TestState::default(); + let view = test_harness(|mut virtual_overseer| async move { + // Leaf A + let leaf_a = TestLeaf { + number: 100, + hash: Hash::from_low_u64_be(130), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; - // If the requested count exceeds the largest chain, return the longest - // chain we can get. - for count in 5..10 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a].into_iter().collect(), - count, - vec![ - (candidate_hash_c, leaf_a.hash), - (candidate_hash_h, leaf_a.hash), - (candidate_hash_i, leaf_a.hash), - (candidate_hash_j, leaf_a.hash), - ], - ) - .await; - } - } + // Activate leaves. + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; - // required path of 2 and higher - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_i, candidate_hash_h, candidate_hash_c] - .into_iter() - .collect(), - 1, - vec![(candidate_hash_j, leaf_a.hash)], - ) - .await; + // Candidate A + let (candidate_a, pvd_a) = make_candidate( + leaf_a.hash, + leaf_a.number, + 1.into(), + HeadData(vec![1, 2, 3]), + HeadData(vec![1]), + test_state.validation_code_hash, + ); + let candidate_hash_a = candidate_a.hash(); + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; + back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), - 1, - vec![(candidate_hash_d, leaf_a.hash)], - ) - .await; + let (candidate_b, candidate_hash_b) = + make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_a, 2); + let (candidate_c, candidate_hash_c) = + make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 3); + let (_candidate_d, candidate_hash_d) = + make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_c, 4); - // If the requested count exceeds the largest chain, return the longest - // chain we can get. - for count in 4..10 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_c].into_iter().collect(), - count, - vec![ - (candidate_hash_h, leaf_a.hash), - (candidate_hash_i, leaf_a.hash), - (candidate_hash_j, leaf_a.hash), - ], - ) - .await; - } - } + // Should not get any backable candidates for the other para. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::new(), + 1, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::new(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + vec![candidate_hash_a].into_iter().collect(), + 1, + vec![], + ) + .await; - // No more candidates in any chain. - { - for count in 1..4 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_b, candidate_hash_e] - .into_iter() - .collect(), - count, - vec![], - ) - .await; - - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![ - candidate_hash_a, - candidate_hash_c, - candidate_hash_h, - candidate_hash_i, - candidate_hash_j, - ] - .into_iter() - .collect(), - count, - vec![], - ) - .await; - } - } + // Test various scenarios with various counts. - // Wrong paths. + // empty ancestors + { get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b].into_iter().collect(), + Ancestors::new(), 1, vec![(candidate_hash_a, leaf_a.hash)], ) .await; + for count in 4..10 { + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::new(), + count, + vec![ + (candidate_hash_a, leaf_a.hash), + (candidate_hash_b, leaf_a.hash), + (candidate_hash_c, leaf_a.hash), + (candidate_hash_d, leaf_a.hash), + ], + ) + .await; + } + } + + // ancestors of size 1 + { get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b, candidate_hash_f].into_iter().collect(), - 3, - vec![ - (candidate_hash_a, leaf_a.hash), - (candidate_hash_b, leaf_a.hash), - (candidate_hash_d, leaf_a.hash), - ], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_h].into_iter().collect(), - 4, - vec![ - (candidate_hash_c, leaf_a.hash), - (candidate_hash_h, leaf_a.hash), - (candidate_hash_i, leaf_a.hash), - (candidate_hash_j, leaf_a.hash), - ], + vec![candidate_hash_a].into_iter().collect(), + 1, + vec![(candidate_hash_b, leaf_a.hash)], ) .await; get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_e, candidate_hash_h].into_iter().collect(), + vec![candidate_hash_a].into_iter().collect(), 2, - vec![(candidate_hash_a, leaf_a.hash), (candidate_hash_b, leaf_a.hash)], + vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_c, leaf_a.hash)], ) .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_c, candidate_hash_d].into_iter().collect(), - 2, - vec![(candidate_hash_h, leaf_a.hash), (candidate_hash_i, leaf_a.hash)], - ) - .await; + // If the requested count exceeds the largest chain, return the longest + // chain we can get. + for count in 3..10 { + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a].into_iter().collect(), + count, + vec![ + (candidate_hash_b, leaf_a.hash), + (candidate_hash_c, leaf_a.hash), + (candidate_hash_d, leaf_a.hash), + ], + ) + .await; + } + } - // Parachain fork. + // ancestor count 2 and higher + { get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), vec![candidate_hash_a, candidate_hash_b, candidate_hash_c].into_iter().collect(), 1, - vec![], + vec![(candidate_hash_d, leaf_a.hash)], ) .await; - // Non-existent candidate. get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, CandidateHash(Hash::from_low_u64_be(100))] - .into_iter() - .collect(), - 2, - vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_d, leaf_a.hash)], + vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), + 1, + vec![(candidate_hash_c, leaf_a.hash)], ) .await; - // Requested count is zero. - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - Ancestors::new(), - 0, - vec![], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a].into_iter().collect(), - 0, - vec![], - ) - .await; + // If the requested count exceeds the largest chain, return the longest + // chain we can get. + for count in 3..10 { + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), + count, + vec![(candidate_hash_c, leaf_a.hash), (candidate_hash_d, leaf_a.hash)], + ) + .await; + } + } + + // No more candidates in the chain. + for count in 1..4 { get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), - 0, + vec![candidate_hash_a, candidate_hash_b, candidate_hash_c, candidate_hash_d] + .into_iter() + .collect(), + count, vec![], ) .await; + } + + // Wrong paths. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_b].into_iter().collect(), + 1, + vec![(candidate_hash_a, leaf_a.hash)], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_b, candidate_hash_c].into_iter().collect(), + 3, + vec![ + (candidate_hash_a, leaf_a.hash), + (candidate_hash_b, leaf_a.hash), + (candidate_hash_c, leaf_a.hash), + ], + ) + .await; + + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, candidate_hash_c, candidate_hash_d].into_iter().collect(), + 2, + vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_c, leaf_a.hash)], + ) + .await; - virtual_overseer - }); + // Non-existent candidate. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, CandidateHash(Hash::from_low_u64_be(100))] + .into_iter() + .collect(), + 2, + vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_c, leaf_a.hash)], + ) + .await; - assert_eq!(view.active_leaves.len(), 1); - assert_eq!(view.candidate_storage.len(), 2); - // 10 candidates and 7 parents on para 1. - assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (7, 10)); - assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); - } + // Requested count is zero. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::new(), + 0, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a].into_iter().collect(), + 0, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), + 0, + vec![], + ) + .await; + + virtual_overseer + }); + + assert_eq!(view.active_leaves.len(), 1); + assert_eq!(view.candidate_storage.len(), 2); + // 4 candidates on para 1. + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (4, 4)); + assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); } -// Test depth query. +// Test hypothetical membership query. #[test] -fn check_hypothetical_frontier_query() { +fn check_hypothetical_membership_query() { let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { + // Leaf B + let leaf_b = TestLeaf { + number: 101, + hash: Hash::from_low_u64_be(131), + para_data: vec![ + (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), + ], + }; // Leaf A let leaf_a = TestLeaf { number: 100, - hash: Hash::from_low_u64_be(130), + hash: get_parent_hash(leaf_b.hash), para_data: vec![ - (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), + (1.into(), PerParaData::new(98, HeadData(vec![1, 2, 3]))), (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), ], }; // Activate leaves. - activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + activate_leaf_with_params( + &mut virtual_overseer, + &leaf_a, + &test_state, + AsyncBackingParams { allowed_ancestry_len: 3, max_candidate_depth: 1 }, + ) + .await; + activate_leaf_with_params( + &mut virtual_overseer, + &leaf_b, + &test_state, + AsyncBackingParams { allowed_ancestry_len: 3, max_candidate_depth: 1 }, + ) + .await; + + // Candidates will be valid on both leaves. // Candidate A. let (candidate_a, pvd_a) = make_candidate( @@ -1415,7 +1788,6 @@ fn check_hypothetical_frontier_query() { HeadData(vec![1]), test_state.validation_code_hash, ); - let candidate_hash_a = candidate_a.hash(); // Candidate B. let (candidate_b, pvd_b) = make_candidate( @@ -1426,7 +1798,6 @@ fn check_hypothetical_frontier_query() { HeadData(vec![2]), test_state.validation_code_hash, ); - let candidate_hash_b = candidate_b.hash(); // Candidate C. let (candidate_c, pvd_c) = make_candidate( @@ -1437,127 +1808,99 @@ fn check_hypothetical_frontier_query() { HeadData(vec![3]), test_state.validation_code_hash, ); - let candidate_hash_c = candidate_c.hash(); - // Get hypothetical frontier of candidate A before adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_a, - candidate_a.clone(), - pvd_a.clone(), - leaf_a.hash, - false, - vec![0], - ) - .await; - // Should work with `backed_in_path_only: true`, too. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_a, - candidate_a.clone(), - pvd_a.clone(), - leaf_a.hash, - true, - vec![0], - ) - .await; + // Get hypothetical membership of candidates before adding candidate A. + // Candidate A can be added directly, candidates B and C are potential candidates. + for (candidate, pvd) in [ + (candidate_a.clone(), pvd_a.clone()), + (candidate_b.clone(), pvd_b.clone()), + (candidate_c.clone(), pvd_c.clone()), + ] { + get_hypothetical_membership( + &mut virtual_overseer, + candidate.hash(), + candidate, + pvd, + vec![leaf_a.hash, leaf_b.hash], + ) + .await; + } // Add candidate A. - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()).await; - - // Get frontier of candidate A after adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_a, - candidate_a.clone(), - pvd_a.clone(), - leaf_a.hash, - false, - vec![0], - ) - .await; - - // Get hypothetical frontier of candidate B before adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_b, - candidate_b.clone(), - pvd_b.clone(), - leaf_a.hash, - false, - vec![1], - ) - .await; - - // Add candidate B. - introduce_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; - // Get frontier of candidate B after adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_b, - candidate_b, - pvd_b.clone(), - leaf_a.hash, - false, - vec![1], - ) - .await; + // Get membership of candidates after adding A. C is not a potential candidate because we + // may only add one more candidate, which must be a connected candidate. + for (candidate, pvd) in + [(candidate_a.clone(), pvd_a.clone()), (candidate_b.clone(), pvd_b.clone())] + { + get_hypothetical_membership( + &mut virtual_overseer, + candidate.hash(), + candidate, + pvd, + vec![leaf_a.hash, leaf_b.hash], + ) + .await; + } - // Get hypothetical frontier of candidate C before adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_c, - candidate_c.clone(), - pvd_c.clone(), - leaf_a.hash, - false, - vec![2], - ) - .await; - // Should be empty with `backed_in_path_only` because we haven't backed anything. - get_hypothetical_frontier( + get_hypothetical_membership( &mut virtual_overseer, - candidate_hash_c, + candidate_c.hash(), candidate_c.clone(), pvd_c.clone(), - leaf_a.hash, - true, vec![], ) .await; - // Add candidate C. - introduce_candidate(&mut virtual_overseer, candidate_c.clone(), pvd_c.clone()).await; + // Candidate D has invalid relay parent. + let (candidate_d, pvd_d) = make_candidate( + Hash::from_low_u64_be(200), + leaf_a.number, + 1.into(), + HeadData(vec![1]), + HeadData(vec![2]), + test_state.validation_code_hash, + ); + introduce_seconded_candidate_failed(&mut virtual_overseer, candidate_d, pvd_d).await; - // Get frontier of candidate C after adding it. - get_hypothetical_frontier( - &mut virtual_overseer, - candidate_hash_c, - candidate_c.clone(), - pvd_c.clone(), - leaf_a.hash, - false, - vec![2], - ) - .await; - // Should be empty with `backed_in_path_only` because we haven't backed anything. - get_hypothetical_frontier( + // Add candidate B. + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b.clone()) + .await; + + // Get membership of candidates after adding B. + for (candidate, pvd) in + [(candidate_a.clone(), pvd_a.clone()), (candidate_b.clone(), pvd_b.clone())] + { + get_hypothetical_membership( + &mut virtual_overseer, + candidate.hash(), + candidate, + pvd, + vec![leaf_a.hash, leaf_b.hash], + ) + .await; + } + + get_hypothetical_membership( &mut virtual_overseer, - candidate_hash_c, + candidate_c.hash(), candidate_c.clone(), pvd_c.clone(), - leaf_a.hash, - true, vec![], ) .await; + // Add candidate C. It will fail because we have enough candidates for the configured depth. + introduce_seconded_candidate_failed(&mut virtual_overseer, candidate_c, pvd_c).await; + virtual_overseer }); - assert_eq!(view.active_leaves.len(), 1); + assert_eq!(view.active_leaves.len(), 2); assert_eq!(view.candidate_storage.len(), 2); + assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (2, 2)); } #[test] @@ -1618,7 +1961,8 @@ fn check_pvd_query() { .await; // Add candidate A. - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a.clone()) + .await; back_candidate(&mut virtual_overseer, &candidate_a, candidate_a.hash()).await; // Get pvd of candidate A after adding it. @@ -1642,7 +1986,7 @@ fn check_pvd_query() { .await; // Add candidate B. - introduce_candidate(&mut virtual_overseer, candidate_b, pvd_b.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b, pvd_b.clone()).await; // Get pvd of candidate B after adding it. get_pvd( @@ -1665,7 +2009,7 @@ fn check_pvd_query() { .await; // Add candidate C. - introduce_candidate(&mut virtual_overseer, candidate_c, pvd_c.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_c, pvd_c.clone()).await; // Get pvd of candidate C after adding it. get_pvd( @@ -1849,8 +2193,7 @@ fn persists_pending_availability_candidate() { ); let candidate_hash_b = candidate_b.hash(); - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - second_candidate(&mut virtual_overseer, candidate_a.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; let candidate_a_pending_av = CandidatePendingAvailability { @@ -1874,8 +2217,7 @@ fn persists_pending_availability_candidate() { }; activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; - introduce_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; - second_candidate(&mut virtual_overseer, candidate_b.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; back_candidate(&mut virtual_overseer, &candidate_b, candidate_hash_b).await; get_backable_candidates( @@ -1942,8 +2284,7 @@ fn backwards_compatible() { ); let candidate_hash_a = candidate_a.hash(); - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - second_candidate(&mut virtual_overseer, candidate_a.clone()).await; + introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; get_backable_candidates( diff --git a/polkadot/node/core/provisioner/Cargo.toml b/polkadot/node/core/provisioner/Cargo.toml index ec1a4abb3ece0a3dc8a01e090f9bf3302dde3294..d197832126442cd7bf67236395cfcc5800f00153 100644 --- a/polkadot/node/core/provisioner/Cargo.toml +++ b/polkadot/node/core/provisioner/Cargo.toml @@ -19,7 +19,7 @@ polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } futures-timer = "3.0.2" -fatality = "0.0.6" +fatality = "0.1.1" schnellru = "0.2.1" [dev-dependencies] diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index 5cfcb96dc2bc710c42400fa49fa888195c79aa48..fa16b38d28bda4e364c5b6d8b74bb85ca727036d 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -877,7 +877,7 @@ async fn get_block_number_under_construction( } /// Requests backable candidates from Prospective Parachains based on -/// the given ancestors in the fragment tree. The ancestors may not be ordered. +/// the given ancestors in the fragment chain. The ancestors may not be ordered. async fn get_backable_candidates( relay_parent: Hash, para_id: ParaId, diff --git a/polkadot/node/core/pvf/Cargo.toml b/polkadot/node/core/pvf/Cargo.toml index 8bfe2baa42fd8baafbf435fab244b2f27252d544..ba9954a10668e154ee44cccc9888a6e3d3c5ed09 100644 --- a/polkadot/node/core/pvf/Cargo.toml +++ b/polkadot/node/core/pvf/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] always-assert = "0.1" -array-bytes = "6.1" +array-bytes = "6.2.2" blake3 = "1.5" cfg-if = "1.0" futures = "0.3.30" @@ -25,7 +25,7 @@ tempfile = "3.3.0" thiserror = { workspace = true } tokio = { version = "1.24.2", features = ["fs", "process"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = [ +parity-scale-codec = { version = "3.6.12", default-features = false, features = [ "derive", ] } @@ -44,7 +44,7 @@ polkadot-node-core-pvf-execute-worker = { path = "execute-worker", optional = tr [dev-dependencies] assert_matches = "1.4.0" -criterion = { version = "0.4.0", default-features = false, features = [ +criterion = { version = "0.5.1", default-features = false, features = [ "async_tokio", "cargo_bench_support", ] } diff --git a/polkadot/node/core/pvf/common/Cargo.toml b/polkadot/node/core/pvf/common/Cargo.toml index e1ce6e79cb99038bcdd183c32096432e8e8428be..5ad7409cc6c78d16cf292c1bf1c1542417abeb5d 100644 --- a/polkadot/node/core/pvf/common/Cargo.toml +++ b/polkadot/node/core/pvf/common/Cargo.toml @@ -14,10 +14,10 @@ cpu-time = "1.0.0" futures = "0.3.30" gum = { package = "tracing-gum", path = "../../../gum" } libc = "0.2.152" -nix = { version = "0.27.1", features = ["resource", "sched"] } +nix = { version = "0.28.0", features = ["resource", "sched"] } thiserror = { workspace = true } -parity-scale-codec = { version = "3.6.1", default-features = false, features = [ +parity-scale-codec = { version = "3.6.12", default-features = false, features = [ "derive", ] } diff --git a/polkadot/node/core/pvf/execute-worker/Cargo.toml b/polkadot/node/core/pvf/execute-worker/Cargo.toml index 04a620573b2eceb311bdce67006e282778442191..ac90fac4d57ad69db5bcf00df1fb9af15cdbd2e2 100644 --- a/polkadot/node/core/pvf/execute-worker/Cargo.toml +++ b/polkadot/node/core/pvf/execute-worker/Cargo.toml @@ -13,10 +13,10 @@ workspace = true cpu-time = "1.0.0" gum = { package = "tracing-gum", path = "../../../gum" } cfg-if = "1.0" -nix = { version = "0.27.1", features = ["process", "resource", "sched"] } +nix = { version = "0.28.0", features = ["process", "resource", "sched"] } libc = "0.2.152" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } polkadot-node-core-pvf-common = { path = "../common" } polkadot-parachain-primitives = { path = "../../../../parachain" } diff --git a/polkadot/node/core/pvf/prepare-worker/Cargo.toml b/polkadot/node/core/pvf/prepare-worker/Cargo.toml index 24efbec4be7d0552abdf9e7a9324636820347950..1850a204890720e697b9e505d8656597dd946844 100644 --- a/polkadot/node/core/pvf/prepare-worker/Cargo.toml +++ b/polkadot/node/core/pvf/prepare-worker/Cargo.toml @@ -18,9 +18,9 @@ rayon = "1.5.1" tracking-allocator = { package = "staging-tracking-allocator", path = "../../../tracking-allocator" } tikv-jemalloc-ctl = { version = "0.5.0", optional = true } tikv-jemallocator = { version = "0.5.0", optional = true } -nix = { version = "0.27.1", features = ["process", "resource", "sched"] } +nix = { version = "0.28.0", features = ["process", "resource", "sched"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } polkadot-node-core-pvf-common = { path = "../common" } polkadot-primitives = { path = "../../../../primitives" } @@ -41,7 +41,7 @@ jemalloc-allocator = [ ] [dev-dependencies] -criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support"] } +criterion = { version = "0.5.1", default-features = false, features = ["cargo_bench_support"] } rococo-runtime = { path = "../../../../runtime/rococo" } sp-maybe-compressed-blob = { path = "../../../../../substrate/primitives/maybe-compressed-blob" } diff --git a/polkadot/node/gum/src/lib.rs b/polkadot/node/gum/src/lib.rs index dad5887af224382ec384b4d354fd74fb2d9c31f5..f78e20cdecfca214b4d936d55cfc8ea5bdd60e15 100644 --- a/polkadot/node/gum/src/lib.rs +++ b/polkadot/node/gum/src/lib.rs @@ -40,7 +40,7 @@ //! //! ### Log levels //! -//! All of the the [`tracing` macros](https://docs.rs/tracing/latest/tracing/index.html#macros) are available. +//! All of the [`tracing` macros](https://docs.rs/tracing/latest/tracing/index.html#macros) are available. //! In decreasing order of priority they are: //! //! - `error!` diff --git a/polkadot/node/jaeger/Cargo.toml b/polkadot/node/jaeger/Cargo.toml index bee725c0876f0cd57692d754738219dd731f8d62..f879f9550d014c0571558f5238f13ce9dad5fe4e 100644 --- a/polkadot/node/jaeger/Cargo.toml +++ b/polkadot/node/jaeger/Cargo.toml @@ -21,4 +21,4 @@ sp-core = { path = "../../../substrate/primitives/core" } thiserror = { workspace = true } tokio = "1.37" log = { workspace = true, default-features = true } -parity-scale-codec = { version = "3.6.1", default-features = false } +parity-scale-codec = { version = "3.6.12", default-features = false } diff --git a/polkadot/node/jaeger/src/spans.rs b/polkadot/node/jaeger/src/spans.rs index 68fa57e2ca14f859b7bcfcf02884deaa34d7d156..fcee8be9a50f504b666ea796c5ac9a63509da0d8 100644 --- a/polkadot/node/jaeger/src/spans.rs +++ b/polkadot/node/jaeger/src/spans.rs @@ -85,7 +85,9 @@ use parity_scale_codec::Encode; use polkadot_node_primitives::PoV; -use polkadot_primitives::{BlakeTwo256, CandidateHash, Hash, HashT, Id as ParaId, ValidatorIndex}; +use polkadot_primitives::{ + BlakeTwo256, CandidateHash, ChunkIndex, Hash, HashT, Id as ParaId, ValidatorIndex, +}; use sc_network_types::PeerId; use std::{fmt, sync::Arc}; @@ -338,8 +340,8 @@ impl Span { } #[inline(always)] - pub fn with_chunk_index(self, chunk_index: u32) -> Self { - self.with_string_tag("chunk-index", chunk_index) + pub fn with_chunk_index(self, chunk_index: ChunkIndex) -> Self { + self.with_string_tag("chunk-index", &chunk_index.0) } #[inline(always)] diff --git a/polkadot/node/malus/Cargo.toml b/polkadot/node/malus/Cargo.toml index 2f63c2f0938d72bea717ac5aff0b2faace47808b..750074fa9b3cb6209d640b75189768fd94faccf2 100644 --- a/polkadot/node/malus/Cargo.toml +++ b/polkadot/node/malus/Cargo.toml @@ -37,6 +37,7 @@ polkadot-node-core-dispute-coordinator = { path = "../core/dispute-coordinator" polkadot-node-core-candidate-validation = { path = "../core/candidate-validation" } polkadot-node-core-backing = { path = "../core/backing" } polkadot-node-primitives = { path = "../primitives" } +polkadot-node-network-protocol = { path = "../network/protocol" } polkadot-primitives = { path = "../../primitives" } color-eyre = { version = "0.6.1", default-features = false } assert_matches = "1.5" diff --git a/polkadot/node/malus/src/malus.rs b/polkadot/node/malus/src/malus.rs index 7a9e320e27368e51da0508910fea5b7c54f2d6c7..6257201537c8d417fc9abf972951340b144d110d 100644 --- a/polkadot/node/malus/src/malus.rs +++ b/polkadot/node/malus/src/malus.rs @@ -40,6 +40,8 @@ enum NemesisVariant { DisputeAncestor(DisputeAncestorOptions), /// Delayed disputing of finalized candidates. DisputeFinalizedCandidates(DisputeFinalizedCandidatesOptions), + /// Spam many request statements instead of sending a single one. + SpamStatementRequests(SpamStatementRequestsOptions), } #[derive(Debug, Parser)] @@ -98,6 +100,11 @@ impl MalusCli { finality_delay, )? }, + NemesisVariant::SpamStatementRequests(opts) => { + let SpamStatementRequestsOptions { spam_factor, cli } = opts; + + polkadot_cli::run_node(cli, SpamStatementRequests { spam_factor }, finality_delay)? + }, } Ok(()) } diff --git a/polkadot/node/malus/src/variants/mod.rs b/polkadot/node/malus/src/variants/mod.rs index 3ca1bf4b4696843476c3de2b6dc441224b0ea9bd..ec945ae1945735b368b173647a4135ac408ca392 100644 --- a/polkadot/node/malus/src/variants/mod.rs +++ b/polkadot/node/malus/src/variants/mod.rs @@ -20,6 +20,7 @@ mod back_garbage_candidate; mod common; mod dispute_finalized_candidates; mod dispute_valid_candidates; +mod spam_statement_requests; mod suggest_garbage_candidate; mod support_disabled; @@ -27,6 +28,7 @@ pub(crate) use self::{ back_garbage_candidate::{BackGarbageCandidateOptions, BackGarbageCandidates}, dispute_finalized_candidates::{DisputeFinalizedCandidates, DisputeFinalizedCandidatesOptions}, dispute_valid_candidates::{DisputeAncestorOptions, DisputeValidCandidates}, + spam_statement_requests::{SpamStatementRequests, SpamStatementRequestsOptions}, suggest_garbage_candidate::{SuggestGarbageCandidateOptions, SuggestGarbageCandidates}, support_disabled::{SupportDisabled, SupportDisabledOptions}, }; diff --git a/polkadot/node/malus/src/variants/spam_statement_requests.rs b/polkadot/node/malus/src/variants/spam_statement_requests.rs new file mode 100644 index 0000000000000000000000000000000000000000..c5970c988ac2a3417ba7a9974e6e44f32cf9b854 --- /dev/null +++ b/polkadot/node/malus/src/variants/spam_statement_requests.rs @@ -0,0 +1,155 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! A malicious node variant that attempts spam statement requests. +//! +//! This malus variant behaves honestly in everything except when propagating statement distribution +//! requests through the network bridge subsystem. Instead of sending a single request when it needs +//! something it attempts to spam the peer with multiple requests. +//! +//! Attention: For usage with `zombienet` only! + +#![allow(missing_docs)] + +use polkadot_cli::{ + service::{ + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, + }, + validator_overseer_builder, Cli, +}; +use polkadot_node_network_protocol::request_response::{outgoing::Requests, OutgoingRequest}; +use polkadot_node_subsystem::{messages::NetworkBridgeTxMessage, SpawnGlue}; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; +use sp_core::traits::SpawnNamed; + +// Filter wrapping related types. +use crate::{interceptor::*, shared::MALUS}; + +use std::sync::Arc; + +/// Wraps around network bridge and replaces it. +#[derive(Clone)] +struct RequestSpammer { + spam_factor: u32, // How many statement distribution requests to send. +} + +impl MessageInterceptor for RequestSpammer +where + Sender: overseer::NetworkBridgeTxSenderTrait + Clone + Send + 'static, +{ + type Message = NetworkBridgeTxMessage; + + /// Intercept NetworkBridgeTxMessage::SendRequests with Requests::AttestedCandidateV2 inside and + /// duplicate that request + fn intercept_incoming( + &self, + _subsystem_sender: &mut Sender, + msg: FromOrchestra, + ) -> Option> { + match msg { + FromOrchestra::Communication { + msg: NetworkBridgeTxMessage::SendRequests(requests, if_disconnected), + } => { + let mut new_requests = Vec::new(); + + for request in requests { + match request { + Requests::AttestedCandidateV2(ref req) => { + // Temporarily store peer and payload for duplication + let peer_to_duplicate = req.peer.clone(); + let payload_to_duplicate = req.payload.clone(); + // Push the original request + new_requests.push(request); + + // Duplicate for spam purposes + gum::info!( + target: MALUS, + "😈 Duplicating AttestedCandidateV2 request extra {:?} times to peer: {:?}.", self.spam_factor, peer_to_duplicate, + ); + new_requests.extend((0..self.spam_factor - 1).map(|_| { + let (new_outgoing_request, _) = OutgoingRequest::new( + peer_to_duplicate.clone(), + payload_to_duplicate.clone(), + ); + Requests::AttestedCandidateV2(new_outgoing_request) + })); + }, + _ => { + new_requests.push(request); + }, + } + } + + // Passthrough the message with a potentially modified number of requests + Some(FromOrchestra::Communication { + msg: NetworkBridgeTxMessage::SendRequests(new_requests, if_disconnected), + }) + }, + FromOrchestra::Communication { msg } => Some(FromOrchestra::Communication { msg }), + FromOrchestra::Signal(signal) => Some(FromOrchestra::Signal(signal)), + } + } +} + +//---------------------------------------------------------------------------------- + +#[derive(Debug, clap::Parser)] +#[clap(rename_all = "kebab-case")] +#[allow(missing_docs)] +pub struct SpamStatementRequestsOptions { + /// How many statement distribution requests to send. + #[clap(long, ignore_case = true, default_value_t = 1000, value_parser = clap::value_parser!(u32).range(0..=10000000))] + pub spam_factor: u32, + + #[clap(flatten)] + pub cli: Cli, +} + +/// SpamStatementRequests implementation wrapper which implements `OverseerGen` glue. +pub(crate) struct SpamStatementRequests { + /// How many statement distribution requests to send. + pub spam_factor: u32, +} + +impl OverseerGen for SpamStatementRequests { + fn generate( + &self, + connector: OverseerConnector, + args: OverseerGenArgs<'_, Spawner, RuntimeClient>, + ext_args: Option, + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> + where + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, + Spawner: 'static + SpawnNamed + Clone + Unpin, + { + gum::info!( + target: MALUS, + "😈 Started Malus node that duplicates each statement distribution request spam_factor = {:?} times.", + &self.spam_factor, + ); + + let request_spammer = RequestSpammer { spam_factor: self.spam_factor }; + + validator_overseer_builder( + args, + ext_args.expect("Extended arguments required to build validator overseer are provided"), + )? + .replace_network_bridge_tx(move |cb| InterceptedSubsystem::new(cb, request_spammer)) + .build_with_connector(connector) + .map_err(|e| e.into()) + } +} diff --git a/polkadot/node/metrics/Cargo.toml b/polkadot/node/metrics/Cargo.toml index fbf0abf829e136a139f3de0db3aef216b2e49679..e3a53cc6df1b435d3e2361d388624252c2df9d3d 100644 --- a/polkadot/node/metrics/Cargo.toml +++ b/polkadot/node/metrics/Cargo.toml @@ -21,7 +21,7 @@ sc-cli = { path = "../../../substrate/client/cli" } substrate-prometheus-endpoint = { path = "../../../substrate/utils/prometheus" } sc-tracing = { path = "../../../substrate/client/tracing" } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } primitives = { package = "polkadot-primitives", path = "../../primitives" } bs58 = { version = "0.5.0", features = ["alloc"] } log = { workspace = true, default-features = true } diff --git a/polkadot/node/network/approval-distribution/Cargo.toml b/polkadot/node/network/approval-distribution/Cargo.toml index 4c04ad83f84f3c75e69ac8771670816b7ea7b4fa..d80519b9e2e95aa4d958bff5b9a08e3bddb2cf3c 100644 --- a/polkadot/node/network/approval-distribution/Cargo.toml +++ b/polkadot/node/network/approval-distribution/Cargo.toml @@ -18,7 +18,7 @@ polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-jaeger = { path = "../../jaeger" } rand = "0.8" -itertools = "0.10.5" +itertools = "0.11" futures = "0.3.30" futures-timer = "3.0.2" diff --git a/polkadot/node/network/availability-distribution/Cargo.toml b/polkadot/node/network/availability-distribution/Cargo.toml index b5636203f166efdbc2d871df778d148c0f9ce3e4..01b208421d793965422b76bd9d6e2a77221838ab 100644 --- a/polkadot/node/network/availability-distribution/Cargo.toml +++ b/polkadot/node/network/availability-distribution/Cargo.toml @@ -12,20 +12,21 @@ workspace = true [dependencies] futures = "0.3.30" gum = { package = "tracing-gum", path = "../../gum" } -parity-scale-codec = { version = "3.6.1", features = ["std"] } +parity-scale-codec = { version = "3.6.12", features = ["std"] } polkadot-primitives = { path = "../../../primitives" } polkadot-erasure-coding = { path = "../../../erasure-coding" } polkadot-node-network-protocol = { path = "../protocol" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-primitives = { path = "../../primitives" } +sc-network = { path = "../../../../substrate/client/network" } sp-core = { path = "../../../../substrate/primitives/core", features = ["std"] } sp-keystore = { path = "../../../../substrate/primitives/keystore" } thiserror = { workspace = true } rand = "0.8.5" derive_more = "0.99.17" schnellru = "0.2.1" -fatality = "0.0.6" +fatality = "0.1.1" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } @@ -36,6 +37,7 @@ sc-network = { path = "../../../../substrate/client/network" } futures-timer = "3.0.2" assert_matches = "1.4.0" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } +rstest = "0.18.2" polkadot-subsystem-bench = { path = "../../subsystem-bench" } diff --git a/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs index 5e3072be3a8c13d08bfec7fc5840320fcc33c6c5..6083a90e48126bbf5747880835f6753176be4559 100644 --- a/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs +++ b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs @@ -53,11 +53,7 @@ fn main() -> Result<(), String> { polkadot_subsystem_bench::availability::TestDataAvailability::Write, false, ); - env.runtime().block_on(benchmark_availability_write( - "data_availability_write", - &mut env, - &state, - )) + env.runtime().block_on(benchmark_availability_write(&mut env, &state)) }) .collect(); println!("\rDone!{}", " ".repeat(BENCH_COUNT)); @@ -77,9 +73,9 @@ fn main() -> Result<(), String> { ("Sent to peers", 18479.9000, 0.001), ])); messages.extend(average_usage.check_cpu_usage(&[ - ("availability-distribution", 0.0123, 0.1), - ("availability-store", 0.1597, 0.1), - ("bitfield-distribution", 0.0223, 0.1), + ("availability-distribution", 0.0127, 0.1), + ("availability-store", 0.1626, 0.1), + ("bitfield-distribution", 0.0224, 0.1), ])); if messages.is_empty() { diff --git a/polkadot/node/network/availability-distribution/src/error.rs b/polkadot/node/network/availability-distribution/src/error.rs index c547a1abbc27604862cebef2790223a0b54fac37..72a809dd114080f185c8aee45f87ff8655c236a4 100644 --- a/polkadot/node/network/availability-distribution/src/error.rs +++ b/polkadot/node/network/availability-distribution/src/error.rs @@ -49,7 +49,7 @@ pub enum Error { #[fatal] #[error("Oneshot for receiving response from Chain API got cancelled")] - ChainApiSenderDropped(#[source] oneshot::Canceled), + ChainApiSenderDropped(#[from] oneshot::Canceled), #[fatal] #[error("Retrieving response from Chain API unexpectedly failed with error: {0}")] @@ -82,6 +82,9 @@ pub enum Error { #[error("Given validator index could not be found in current session")] InvalidValidatorIndex, + + #[error("Erasure coding error: {0}")] + ErasureCoding(#[from] polkadot_erasure_coding::Error), } /// General result abbreviation type alias. @@ -104,7 +107,8 @@ pub fn log_error( JfyiError::InvalidValidatorIndex | JfyiError::NoSuchCachedSession { .. } | JfyiError::QueryAvailableDataResponseChannel(_) | - JfyiError::QueryChunkResponseChannel(_) => gum::warn!(target: LOG_TARGET, error = %jfyi, ctx), + JfyiError::QueryChunkResponseChannel(_) | + JfyiError::ErasureCoding(_) => gum::warn!(target: LOG_TARGET, error = %jfyi, ctx), JfyiError::FetchPoV(_) | JfyiError::SendResponse | JfyiError::NoSuchPoV | diff --git a/polkadot/node/network/availability-distribution/src/lib.rs b/polkadot/node/network/availability-distribution/src/lib.rs index c62ce1dd981a9ce8c4fe6e2b7c451a401e609b25..ec2c01f99b0186f80a42ad635426ace626139ffc 100644 --- a/polkadot/node/network/availability-distribution/src/lib.rs +++ b/polkadot/node/network/availability-distribution/src/lib.rs @@ -18,7 +18,9 @@ use futures::{future::Either, FutureExt, StreamExt, TryFutureExt}; use sp_keystore::KeystorePtr; -use polkadot_node_network_protocol::request_response::{v1, IncomingRequestReceiver}; +use polkadot_node_network_protocol::request_response::{ + v1, v2, IncomingRequestReceiver, ReqProtocolNames, +}; use polkadot_node_subsystem::{ jaeger, messages::AvailabilityDistributionMessage, overseer, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, @@ -41,7 +43,7 @@ mod pov_requester; /// Responding to erasure chunk requests: mod responder; -use responder::{run_chunk_receiver, run_pov_receiver}; +use responder::{run_chunk_receivers, run_pov_receiver}; mod metrics; /// Prometheus `Metrics` for availability distribution. @@ -58,6 +60,8 @@ pub struct AvailabilityDistributionSubsystem { runtime: RuntimeInfo, /// Receivers to receive messages from. recvs: IncomingRequestReceivers, + /// Mapping of the req-response protocols to the full protocol names. + req_protocol_names: ReqProtocolNames, /// Prometheus metrics. metrics: Metrics, } @@ -66,8 +70,10 @@ pub struct AvailabilityDistributionSubsystem { pub struct IncomingRequestReceivers { /// Receiver for incoming PoV requests. pub pov_req_receiver: IncomingRequestReceiver, - /// Receiver for incoming availability chunk requests. - pub chunk_req_receiver: IncomingRequestReceiver, + /// Receiver for incoming v1 availability chunk requests. + pub chunk_req_v1_receiver: IncomingRequestReceiver, + /// Receiver for incoming v2 availability chunk requests. + pub chunk_req_v2_receiver: IncomingRequestReceiver, } #[overseer::subsystem(AvailabilityDistribution, error=SubsystemError, prefix=self::overseer)] @@ -85,18 +91,27 @@ impl AvailabilityDistributionSubsystem { #[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)] impl AvailabilityDistributionSubsystem { /// Create a new instance of the availability distribution. - pub fn new(keystore: KeystorePtr, recvs: IncomingRequestReceivers, metrics: Metrics) -> Self { + pub fn new( + keystore: KeystorePtr, + recvs: IncomingRequestReceivers, + req_protocol_names: ReqProtocolNames, + metrics: Metrics, + ) -> Self { let runtime = RuntimeInfo::new(Some(keystore)); - Self { runtime, recvs, metrics } + Self { runtime, recvs, req_protocol_names, metrics } } /// Start processing work as passed on from the Overseer. async fn run(self, mut ctx: Context) -> std::result::Result<(), FatalError> { - let Self { mut runtime, recvs, metrics } = self; + let Self { mut runtime, recvs, metrics, req_protocol_names } = self; let mut spans: HashMap = HashMap::new(); - let IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver } = recvs; - let mut requester = Requester::new(metrics.clone()).fuse(); + let IncomingRequestReceivers { + pov_req_receiver, + chunk_req_v1_receiver, + chunk_req_v2_receiver, + } = recvs; + let mut requester = Requester::new(req_protocol_names, metrics.clone()).fuse(); let mut warn_freq = gum::Freq::new(); { @@ -109,7 +124,13 @@ impl AvailabilityDistributionSubsystem { ctx.spawn( "chunk-receiver", - run_chunk_receiver(sender, chunk_req_receiver, metrics.clone()).boxed(), + run_chunk_receivers( + sender, + chunk_req_v1_receiver, + chunk_req_v2_receiver, + metrics.clone(), + ) + .boxed(), ) .map_err(FatalError::SpawnTask)?; } diff --git a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs index f478defcaa96530d695eace0acad11057609d8e9..7bd36709bc5f3265a8e3c6f88f3ad913766a2000 100644 --- a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs +++ b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs @@ -22,10 +22,12 @@ use futures::{ FutureExt, SinkExt, }; +use parity_scale_codec::Decode; use polkadot_erasure_coding::branch_hash; use polkadot_node_network_protocol::request_response::{ outgoing::{OutgoingRequest, Recipient, RequestError, Requests}, - v1::{ChunkFetchingRequest, ChunkFetchingResponse}, + v1::{self, ChunkResponse}, + v2, }; use polkadot_node_primitives::ErasureChunk; use polkadot_node_subsystem::{ @@ -34,9 +36,10 @@ use polkadot_node_subsystem::{ overseer, }; use polkadot_primitives::{ - AuthorityDiscoveryId, BlakeTwo256, CandidateHash, GroupIndex, Hash, HashT, OccupiedCore, - SessionIndex, + AuthorityDiscoveryId, BlakeTwo256, CandidateHash, ChunkIndex, GroupIndex, Hash, HashT, + OccupiedCore, SessionIndex, }; +use sc_network::ProtocolName; use crate::{ error::{FatalError, Result}, @@ -111,8 +114,8 @@ struct RunningTask { /// This vector gets drained during execution of the task (it will be empty afterwards). group: Vec, - /// The request to send. - request: ChunkFetchingRequest, + /// The request to send. We can store it as either v1 or v2, they have the same payload. + request: v2::ChunkFetchingRequest, /// Root hash, for verifying the chunks validity. erasure_root: Hash, @@ -128,6 +131,16 @@ struct RunningTask { /// Span tracking the fetching of this chunk. span: jaeger::Span, + + /// Expected chunk index. We'll validate that the remote did send us the correct chunk (only + /// important for v2 requests). + chunk_index: ChunkIndex, + + /// Full protocol name for ChunkFetchingV1. + req_v1_protocol_name: ProtocolName, + + /// Full protocol name for ChunkFetchingV2. + req_v2_protocol_name: ProtocolName, } impl FetchTaskConfig { @@ -140,13 +153,17 @@ impl FetchTaskConfig { sender: mpsc::Sender, metrics: Metrics, session_info: &SessionInfo, + chunk_index: ChunkIndex, span: jaeger::Span, + req_v1_protocol_name: ProtocolName, + req_v2_protocol_name: ProtocolName, ) -> Self { let span = span .child("fetch-task-config") .with_trace_id(core.candidate_hash) .with_string_tag("leaf", format!("{:?}", leaf)) .with_validator_index(session_info.our_index) + .with_chunk_index(chunk_index) .with_uint_tag("group-index", core.group_responsible.0 as u64) .with_relay_parent(core.candidate_descriptor.relay_parent) .with_string_tag("pov-hash", format!("{:?}", core.candidate_descriptor.pov_hash)) @@ -165,7 +182,7 @@ impl FetchTaskConfig { group: session_info.validator_groups.get(core.group_responsible.0 as usize) .expect("The responsible group of a candidate should be available in the corresponding session. qed.") .clone(), - request: ChunkFetchingRequest { + request: v2::ChunkFetchingRequest { candidate_hash: core.candidate_hash, index: session_info.our_index, }, @@ -174,6 +191,9 @@ impl FetchTaskConfig { metrics, sender, span, + chunk_index, + req_v1_protocol_name, + req_v2_protocol_name }; FetchTaskConfig { live_in, prepared_running: Some(prepared_running) } } @@ -271,7 +291,8 @@ impl RunningTask { count += 1; let _chunk_fetch_span = span .child("fetch-chunk-request") - .with_chunk_index(self.request.index.0) + .with_validator_index(self.request.index) + .with_chunk_index(self.chunk_index) .with_stage(jaeger::Stage::AvailabilityDistribution); // Send request: let resp = match self @@ -296,11 +317,12 @@ impl RunningTask { drop(_chunk_fetch_span); let _chunk_recombine_span = span .child("recombine-chunk") - .with_chunk_index(self.request.index.0) + .with_validator_index(self.request.index) + .with_chunk_index(self.chunk_index) .with_stage(jaeger::Stage::AvailabilityDistribution); let chunk = match resp { - ChunkFetchingResponse::Chunk(resp) => resp.recombine_into_chunk(&self.request), - ChunkFetchingResponse::NoSuchChunk => { + Some(chunk) => chunk, + None => { gum::debug!( target: LOG_TARGET, validator = ?validator, @@ -320,11 +342,12 @@ impl RunningTask { drop(_chunk_recombine_span); let _chunk_validate_and_store_span = span .child("validate-and-store-chunk") - .with_chunk_index(self.request.index.0) + .with_validator_index(self.request.index) + .with_chunk_index(self.chunk_index) .with_stage(jaeger::Stage::AvailabilityDistribution); // Data genuine? - if !self.validate_chunk(&validator, &chunk) { + if !self.validate_chunk(&validator, &chunk, self.chunk_index) { bad_validators.push(validator); continue } @@ -350,7 +373,7 @@ impl RunningTask { validator: &AuthorityDiscoveryId, network_error_freq: &mut gum::Freq, canceled_freq: &mut gum::Freq, - ) -> std::result::Result { + ) -> std::result::Result, TaskError> { gum::trace!( target: LOG_TARGET, origin = ?validator, @@ -362,9 +385,13 @@ impl RunningTask { "Starting chunk request", ); - let (full_request, response_recv) = - OutgoingRequest::new(Recipient::Authority(validator.clone()), self.request); - let requests = Requests::ChunkFetchingV1(full_request); + let (full_request, response_recv) = OutgoingRequest::new_with_fallback( + Recipient::Authority(validator.clone()), + self.request, + // Fallback to v1, for backwards compatibility. + v1::ChunkFetchingRequest::from(self.request), + ); + let requests = Requests::ChunkFetching(full_request); self.sender .send(FromFetchTask::Message( @@ -378,7 +405,58 @@ impl RunningTask { .map_err(|_| TaskError::ShuttingDown)?; match response_recv.await { - Ok(resp) => Ok(resp), + Ok((bytes, protocol)) => match protocol { + _ if protocol == self.req_v2_protocol_name => + match v2::ChunkFetchingResponse::decode(&mut &bytes[..]) { + Ok(chunk_response) => Ok(Option::::from(chunk_response)), + Err(e) => { + gum::warn!( + target: LOG_TARGET, + origin = ?validator, + relay_parent = ?self.relay_parent, + group_index = ?self.group_index, + session_index = ?self.session_index, + chunk_index = ?self.request.index, + candidate_hash = ?self.request.candidate_hash, + err = ?e, + "Peer sent us invalid erasure chunk data (v2)" + ); + Err(TaskError::PeerError) + }, + }, + _ if protocol == self.req_v1_protocol_name => + match v1::ChunkFetchingResponse::decode(&mut &bytes[..]) { + Ok(chunk_response) => Ok(Option::::from(chunk_response) + .map(|c| c.recombine_into_chunk(&self.request.into()))), + Err(e) => { + gum::warn!( + target: LOG_TARGET, + origin = ?validator, + relay_parent = ?self.relay_parent, + group_index = ?self.group_index, + session_index = ?self.session_index, + chunk_index = ?self.request.index, + candidate_hash = ?self.request.candidate_hash, + err = ?e, + "Peer sent us invalid erasure chunk data" + ); + Err(TaskError::PeerError) + }, + }, + _ => { + gum::warn!( + target: LOG_TARGET, + origin = ?validator, + relay_parent = ?self.relay_parent, + group_index = ?self.group_index, + session_index = ?self.session_index, + chunk_index = ?self.request.index, + candidate_hash = ?self.request.candidate_hash, + "Peer sent us invalid erasure chunk data - unknown protocol" + ); + Err(TaskError::PeerError) + }, + }, Err(RequestError::InvalidResponse(err)) => { gum::warn!( target: LOG_TARGET, @@ -427,7 +505,23 @@ impl RunningTask { } } - fn validate_chunk(&self, validator: &AuthorityDiscoveryId, chunk: &ErasureChunk) -> bool { + fn validate_chunk( + &self, + validator: &AuthorityDiscoveryId, + chunk: &ErasureChunk, + expected_chunk_index: ChunkIndex, + ) -> bool { + if chunk.index != expected_chunk_index { + gum::warn!( + target: LOG_TARGET, + candidate_hash = ?self.request.candidate_hash, + origin = ?validator, + chunk_index = ?chunk.index, + expected_chunk_index = ?expected_chunk_index, + "Validator sent the wrong chunk", + ); + return false + } let anticipated_hash = match branch_hash(&self.erasure_root, chunk.proof(), chunk.index.0 as usize) { Ok(hash) => hash, @@ -459,6 +553,7 @@ impl RunningTask { AvailabilityStoreMessage::StoreChunk { candidate_hash: self.request.candidate_hash, chunk, + validator_index: self.request.index, tx, } .into(), diff --git a/polkadot/node/network/availability-distribution/src/requester/fetch_task/tests.rs b/polkadot/node/network/availability-distribution/src/requester/fetch_task/tests.rs index a5a81082e39ad8897845363960120956b1599a95..25fae37f725aaa5a89f6c4ac9d8d019d929c362b 100644 --- a/polkadot/node/network/availability-distribution/src/requester/fetch_task/tests.rs +++ b/polkadot/node/network/availability-distribution/src/requester/fetch_task/tests.rs @@ -24,21 +24,26 @@ use futures::{ task::{noop_waker, Context, Poll}, Future, FutureExt, StreamExt, }; +use rstest::rstest; use sc_network::{self as network, ProtocolName}; use sp_keyring::Sr25519Keyring; -use polkadot_node_network_protocol::request_response::{v1, Recipient}; +use polkadot_node_network_protocol::request_response::{ + v1::{self, ChunkResponse}, + Protocol, Recipient, ReqProtocolNames, +}; use polkadot_node_primitives::{BlockData, PoV, Proof}; use polkadot_node_subsystem::messages::AllMessages; -use polkadot_primitives::{CandidateHash, ValidatorIndex}; +use polkadot_primitives::{CandidateHash, ChunkIndex, ValidatorIndex}; use super::*; use crate::{metrics::Metrics, tests::mock::get_valid_chunk_data}; #[test] fn task_can_be_canceled() { - let (task, _rx) = get_test_running_task(); + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + let (task, _rx) = get_test_running_task(&req_protocol_names, 0.into(), 0.into()); let (handle, kill) = oneshot::channel(); std::mem::drop(handle); let running_task = task.run(kill); @@ -49,96 +54,130 @@ fn task_can_be_canceled() { } /// Make sure task won't accept a chunk that has is invalid. -#[test] -fn task_does_not_accept_invalid_chunk() { - let (mut task, rx) = get_test_running_task(); +#[rstest] +#[case(Protocol::ChunkFetchingV1)] +#[case(Protocol::ChunkFetchingV2)] +fn task_does_not_accept_invalid_chunk(#[case] protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + let chunk_index = ChunkIndex(1); + let validator_index = ValidatorIndex(0); + let (mut task, rx) = get_test_running_task(&req_protocol_names, validator_index, chunk_index); let validators = vec![Sr25519Keyring::Alice.public().into()]; task.group = validators; + let protocol_name = req_protocol_names.get_name(protocol); let test = TestRun { chunk_responses: { - let mut m = HashMap::new(); - m.insert( + [( Recipient::Authority(Sr25519Keyring::Alice.public().into()), - ChunkFetchingResponse::Chunk(v1::ChunkResponse { - chunk: vec![1, 2, 3], - proof: Proof::try_from(vec![vec![9, 8, 2], vec![2, 3, 4]]).unwrap(), - }), - ); - m + get_response( + protocol, + protocol_name.clone(), + Some(( + vec![1, 2, 3], + Proof::try_from(vec![vec![9, 8, 2], vec![2, 3, 4]]).unwrap(), + chunk_index, + )), + ), + )] + .into_iter() + .collect() }, valid_chunks: HashSet::new(), + req_protocol_names, }; test.run(task, rx); } -#[test] -fn task_stores_valid_chunk() { - let (mut task, rx) = get_test_running_task(); +#[rstest] +#[case(Protocol::ChunkFetchingV1)] +#[case(Protocol::ChunkFetchingV2)] +fn task_stores_valid_chunk(#[case] protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + // In order for protocol version 1 to work, the chunk index needs to be equal to the validator + // index. + let chunk_index = ChunkIndex(0); + let validator_index = + if protocol == Protocol::ChunkFetchingV1 { ValidatorIndex(0) } else { ValidatorIndex(1) }; + let (mut task, rx) = get_test_running_task(&req_protocol_names, validator_index, chunk_index); + let validators = vec![Sr25519Keyring::Alice.public().into()]; let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; - let (root_hash, chunk) = get_valid_chunk_data(pov); + let (root_hash, chunk) = get_valid_chunk_data(pov, 10, chunk_index); task.erasure_root = root_hash; - task.request.index = chunk.index; - - let validators = vec![Sr25519Keyring::Alice.public().into()]; task.group = validators; + let protocol_name = req_protocol_names.get_name(protocol); let test = TestRun { chunk_responses: { - let mut m = HashMap::new(); - m.insert( + [( Recipient::Authority(Sr25519Keyring::Alice.public().into()), - ChunkFetchingResponse::Chunk(v1::ChunkResponse { - chunk: chunk.chunk.clone(), - proof: chunk.proof, - }), - ); - m - }, - valid_chunks: { - let mut s = HashSet::new(); - s.insert(chunk.chunk); - s + get_response( + protocol, + protocol_name.clone(), + Some((chunk.chunk.clone(), chunk.proof, chunk_index)), + ), + )] + .into_iter() + .collect() }, + valid_chunks: [(chunk.chunk)].into_iter().collect(), + req_protocol_names, }; test.run(task, rx); } -#[test] -fn task_does_not_accept_wrongly_indexed_chunk() { - let (mut task, rx) = get_test_running_task(); - let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; - let (root_hash, chunk) = get_valid_chunk_data(pov); - task.erasure_root = root_hash; - task.request.index = ValidatorIndex(chunk.index.0 + 1); +#[rstest] +#[case(Protocol::ChunkFetchingV1)] +#[case(Protocol::ChunkFetchingV2)] +fn task_does_not_accept_wrongly_indexed_chunk(#[case] protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + // In order for protocol version 1 to work, the chunk index needs to be equal to the validator + // index. + let chunk_index = ChunkIndex(0); + let validator_index = + if protocol == Protocol::ChunkFetchingV1 { ValidatorIndex(0) } else { ValidatorIndex(1) }; + let (mut task, rx) = get_test_running_task(&req_protocol_names, validator_index, chunk_index); let validators = vec![Sr25519Keyring::Alice.public().into()]; + let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; + let (_, other_chunk) = get_valid_chunk_data(pov.clone(), 10, ChunkIndex(3)); + let (root_hash, chunk) = get_valid_chunk_data(pov, 10, ChunkIndex(0)); + task.erasure_root = root_hash; + task.request.index = chunk.index.into(); task.group = validators; + let protocol_name = req_protocol_names.get_name(protocol); let test = TestRun { chunk_responses: { - let mut m = HashMap::new(); - m.insert( + [( Recipient::Authority(Sr25519Keyring::Alice.public().into()), - ChunkFetchingResponse::Chunk(v1::ChunkResponse { - chunk: chunk.chunk.clone(), - proof: chunk.proof, - }), - ); - m + get_response( + protocol, + protocol_name.clone(), + Some((other_chunk.chunk.clone(), chunk.proof, other_chunk.index)), + ), + )] + .into_iter() + .collect() }, valid_chunks: HashSet::new(), + req_protocol_names, }; test.run(task, rx); } /// Task stores chunk, if there is at least one validator having a valid chunk. -#[test] -fn task_stores_valid_chunk_if_there_is_one() { - let (mut task, rx) = get_test_running_task(); +#[rstest] +#[case(Protocol::ChunkFetchingV1)] +#[case(Protocol::ChunkFetchingV2)] +fn task_stores_valid_chunk_if_there_is_one(#[case] protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + // In order for protocol version 1 to work, the chunk index needs to be equal to the validator + // index. + let chunk_index = ChunkIndex(1); + let validator_index = + if protocol == Protocol::ChunkFetchingV1 { ValidatorIndex(1) } else { ValidatorIndex(2) }; + let (mut task, rx) = get_test_running_task(&req_protocol_names, validator_index, chunk_index); let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; - let (root_hash, chunk) = get_valid_chunk_data(pov); - task.erasure_root = root_hash; - task.request.index = chunk.index; let validators = [ // Only Alice has valid chunk - should succeed, even though she is tried last. @@ -151,37 +190,45 @@ fn task_stores_valid_chunk_if_there_is_one() { .iter() .map(|v| v.public().into()) .collect::>(); + + let (root_hash, chunk) = get_valid_chunk_data(pov, 10, chunk_index); + task.erasure_root = root_hash; task.group = validators; + let protocol_name = req_protocol_names.get_name(protocol); let test = TestRun { chunk_responses: { - let mut m = HashMap::new(); - m.insert( - Recipient::Authority(Sr25519Keyring::Alice.public().into()), - ChunkFetchingResponse::Chunk(v1::ChunkResponse { - chunk: chunk.chunk.clone(), - proof: chunk.proof, - }), - ); - m.insert( - Recipient::Authority(Sr25519Keyring::Bob.public().into()), - ChunkFetchingResponse::NoSuchChunk, - ); - m.insert( - Recipient::Authority(Sr25519Keyring::Charlie.public().into()), - ChunkFetchingResponse::Chunk(v1::ChunkResponse { - chunk: vec![1, 2, 3], - proof: Proof::try_from(vec![vec![9, 8, 2], vec![2, 3, 4]]).unwrap(), - }), - ); - - m - }, - valid_chunks: { - let mut s = HashSet::new(); - s.insert(chunk.chunk); - s + [ + ( + Recipient::Authority(Sr25519Keyring::Alice.public().into()), + get_response( + protocol, + protocol_name.clone(), + Some((chunk.chunk.clone(), chunk.proof, chunk_index)), + ), + ), + ( + Recipient::Authority(Sr25519Keyring::Bob.public().into()), + get_response(protocol, protocol_name.clone(), None), + ), + ( + Recipient::Authority(Sr25519Keyring::Charlie.public().into()), + get_response( + protocol, + protocol_name.clone(), + Some(( + vec![1, 2, 3], + Proof::try_from(vec![vec![9, 8, 2], vec![2, 3, 4]]).unwrap(), + chunk_index, + )), + ), + ), + ] + .into_iter() + .collect() }, + valid_chunks: [(chunk.chunk)].into_iter().collect(), + req_protocol_names, }; test.run(task, rx); } @@ -189,14 +236,16 @@ fn task_stores_valid_chunk_if_there_is_one() { struct TestRun { /// Response to deliver for a given validator index. /// None means, answer with `NetworkError`. - chunk_responses: HashMap, + chunk_responses: HashMap, ProtocolName)>, /// Set of chunks that should be considered valid: valid_chunks: HashSet>, + /// Request protocol names + req_protocol_names: ReqProtocolNames, } impl TestRun { fn run(self, task: RunningTask, rx: mpsc::Receiver) { - sp_tracing::try_init_simple(); + sp_tracing::init_for_tests(); let mut rx = rx.fuse(); let task = task.run_inner().fuse(); futures::pin_mut!(task); @@ -240,20 +289,41 @@ impl TestRun { let mut valid_responses = 0; for req in reqs { let req = match req { - Requests::ChunkFetchingV1(req) => req, + Requests::ChunkFetching(req) => req, _ => panic!("Unexpected request"), }; let response = self.chunk_responses.get(&req.peer).ok_or(network::RequestFailure::Refused); - if let Ok(ChunkFetchingResponse::Chunk(resp)) = &response { - if self.valid_chunks.contains(&resp.chunk) { - valid_responses += 1; + if let Ok((resp, protocol)) = response { + let chunk = if protocol == + &self.req_protocol_names.get_name(Protocol::ChunkFetchingV1) + { + Into::>::into( + v1::ChunkFetchingResponse::decode(&mut &resp[..]).unwrap(), + ) + .map(|c| c.chunk) + } else if protocol == + &self.req_protocol_names.get_name(Protocol::ChunkFetchingV2) + { + Into::>::into( + v2::ChunkFetchingResponse::decode(&mut &resp[..]).unwrap(), + ) + .map(|c| c.chunk) + } else { + unreachable!() + }; + + if let Some(chunk) = chunk { + if self.valid_chunks.contains(&chunk) { + valid_responses += 1; + } } + + req.pending_response + .send(response.cloned()) + .expect("Sending response should succeed"); } - req.pending_response - .send(response.map(|r| (r.encode(), ProtocolName::from("")))) - .expect("Sending response should succeed"); } return (valid_responses == 0) && self.valid_chunks.is_empty() }, @@ -274,8 +344,12 @@ impl TestRun { } } -/// Get a `RunningTask` filled with dummy values. -fn get_test_running_task() -> (RunningTask, mpsc::Receiver) { +/// Get a `RunningTask` filled with (mostly) dummy values. +fn get_test_running_task( + req_protocol_names: &ReqProtocolNames, + validator_index: ValidatorIndex, + chunk_index: ChunkIndex, +) -> (RunningTask, mpsc::Receiver) { let (tx, rx) = mpsc::channel(0); ( @@ -283,16 +357,45 @@ fn get_test_running_task() -> (RunningTask, mpsc::Receiver) { session_index: 0, group_index: GroupIndex(0), group: Vec::new(), - request: ChunkFetchingRequest { + request: v2::ChunkFetchingRequest { candidate_hash: CandidateHash([43u8; 32].into()), - index: ValidatorIndex(0), + index: validator_index, }, erasure_root: Hash::repeat_byte(99), relay_parent: Hash::repeat_byte(71), sender: tx, metrics: Metrics::new_dummy(), span: jaeger::Span::Disabled, + req_v1_protocol_name: req_protocol_names.get_name(Protocol::ChunkFetchingV1), + req_v2_protocol_name: req_protocol_names.get_name(Protocol::ChunkFetchingV2), + chunk_index, }, rx, ) } + +/// Make a versioned ChunkFetchingResponse. +fn get_response( + protocol: Protocol, + protocol_name: ProtocolName, + chunk: Option<(Vec, Proof, ChunkIndex)>, +) -> (Vec, ProtocolName) { + ( + match protocol { + Protocol::ChunkFetchingV1 => if let Some((chunk, proof, _)) = chunk { + v1::ChunkFetchingResponse::Chunk(ChunkResponse { chunk, proof }) + } else { + v1::ChunkFetchingResponse::NoSuchChunk + } + .encode(), + Protocol::ChunkFetchingV2 => if let Some((chunk, proof, index)) = chunk { + v2::ChunkFetchingResponse::Chunk(ErasureChunk { chunk, index, proof }) + } else { + v2::ChunkFetchingResponse::NoSuchChunk + } + .encode(), + _ => unreachable!(), + }, + protocol_name, + ) +} diff --git a/polkadot/node/network/availability-distribution/src/requester/mod.rs b/polkadot/node/network/availability-distribution/src/requester/mod.rs index 97e80d696e7ef2adabdbc24dda76172603e462f0..efbdceb43bddc6c9501fb5ed6dc3c2e42100df7b 100644 --- a/polkadot/node/network/availability-distribution/src/requester/mod.rs +++ b/polkadot/node/network/availability-distribution/src/requester/mod.rs @@ -18,10 +18,7 @@ //! availability. use std::{ - collections::{ - hash_map::{Entry, HashMap}, - hash_set::HashSet, - }, + collections::{hash_map::HashMap, hash_set::HashSet}, iter::IntoIterator, pin::Pin, }; @@ -32,13 +29,17 @@ use futures::{ Stream, }; +use polkadot_node_network_protocol::request_response::{v1, v2, IsRequest, ReqProtocolNames}; use polkadot_node_subsystem::{ jaeger, messages::{ChainApiMessage, RuntimeApiMessage}, overseer, ActivatedLeaf, ActiveLeavesUpdate, }; -use polkadot_node_subsystem_util::runtime::{get_occupied_cores, RuntimeInfo}; -use polkadot_primitives::{CandidateHash, Hash, OccupiedCore, SessionIndex}; +use polkadot_node_subsystem_util::{ + availability_chunks::availability_chunk_index, + runtime::{get_occupied_cores, RuntimeInfo}, +}; +use polkadot_primitives::{CandidateHash, CoreIndex, Hash, OccupiedCore, SessionIndex}; use super::{FatalError, Metrics, Result, LOG_TARGET}; @@ -77,6 +78,9 @@ pub struct Requester { /// Prometheus Metrics metrics: Metrics, + + /// Mapping of the req-response protocols to the full protocol names. + req_protocol_names: ReqProtocolNames, } #[overseer::contextbounds(AvailabilityDistribution, prefix = self::overseer)] @@ -88,9 +92,16 @@ impl Requester { /// /// You must feed it with `ActiveLeavesUpdate` via `update_fetching_heads` and make it progress /// by advancing the stream. - pub fn new(metrics: Metrics) -> Self { + pub fn new(req_protocol_names: ReqProtocolNames, metrics: Metrics) -> Self { let (tx, rx) = mpsc::channel(1); - Requester { fetches: HashMap::new(), session_cache: SessionCache::new(), tx, rx, metrics } + Requester { + fetches: HashMap::new(), + session_cache: SessionCache::new(), + tx, + rx, + metrics, + req_protocol_names, + } } /// Update heads that need availability distribution. @@ -197,56 +208,76 @@ impl Requester { runtime: &mut RuntimeInfo, leaf: Hash, leaf_session_index: SessionIndex, - cores: impl IntoIterator, + cores: impl IntoIterator, span: jaeger::Span, ) -> Result<()> { - for core in cores { + for (core_index, core) in cores { let mut span = span .child("check-fetch-candidate") .with_trace_id(core.candidate_hash) .with_string_tag("leaf", format!("{:?}", leaf)) .with_candidate(core.candidate_hash) .with_stage(jaeger::Stage::AvailabilityDistribution); - match self.fetches.entry(core.candidate_hash) { - Entry::Occupied(mut e) => + + if let Some(e) = self.fetches.get_mut(&core.candidate_hash) { // Just book keeping - we are already requesting that chunk: - { - span.add_string_tag("already-requested-chunk", "true"); - e.get_mut().add_leaf(leaf); - }, - Entry::Vacant(e) => { - span.add_string_tag("already-requested-chunk", "false"); - let tx = self.tx.clone(); - let metrics = self.metrics.clone(); - - let task_cfg = self - .session_cache - .with_session_info( - context, - runtime, - // We use leaf here, the relay_parent must be in the same session as - // the leaf. This is guaranteed by runtime which ensures that cores are - // cleared at session boundaries. At the same time, only leaves are - // guaranteed to be fetchable by the state trie. - leaf, - leaf_session_index, - |info| FetchTaskConfig::new(leaf, &core, tx, metrics, info, span), - ) - .await - .map_err(|err| { - gum::warn!( - target: LOG_TARGET, - error = ?err, - "Failed to spawn a fetch task" - ); - err + span.add_string_tag("already-requested-chunk", "true"); + e.add_leaf(leaf); + } else { + span.add_string_tag("already-requested-chunk", "false"); + let tx = self.tx.clone(); + let metrics = self.metrics.clone(); + + let session_info = self + .session_cache + .get_session_info( + context, + runtime, + // We use leaf here, the relay_parent must be in the same session as + // the leaf. This is guaranteed by runtime which ensures that cores are + // cleared at session boundaries. At the same time, only leaves are + // guaranteed to be fetchable by the state trie. + leaf, + leaf_session_index, + ) + .await + .map_err(|err| { + gum::warn!( + target: LOG_TARGET, + error = ?err, + "Failed to spawn a fetch task" + ); + err + })?; + + if let Some(session_info) = session_info { + let n_validators = + session_info.validator_groups.iter().fold(0usize, |mut acc, group| { + acc = acc.saturating_add(group.len()); + acc }); - - if let Ok(Some(task_cfg)) = task_cfg { - e.insert(FetchTask::start(task_cfg, context).await?); - } - // Not a validator, nothing to do. - }, + let chunk_index = availability_chunk_index( + session_info.node_features.as_ref(), + n_validators, + core_index, + session_info.our_index, + )?; + + let task_cfg = FetchTaskConfig::new( + leaf, + &core, + tx, + metrics, + session_info, + chunk_index, + span, + self.req_protocol_names.get_name(v1::ChunkFetchingRequest::PROTOCOL), + self.req_protocol_names.get_name(v2::ChunkFetchingRequest::PROTOCOL), + ); + + self.fetches + .insert(core.candidate_hash, FetchTask::start(task_cfg, context).await?); + } } } Ok(()) diff --git a/polkadot/node/network/availability-distribution/src/requester/session_cache.rs b/polkadot/node/network/availability-distribution/src/requester/session_cache.rs index 8a48e19c2827d13fe2d15ea4cc5ded50f058ca03..a762c262dba3ec1df0c7609017b704d867f11141 100644 --- a/polkadot/node/network/availability-distribution/src/requester/session_cache.rs +++ b/polkadot/node/network/availability-distribution/src/requester/session_cache.rs @@ -20,8 +20,10 @@ use rand::{seq::SliceRandom, thread_rng}; use schnellru::{ByLength, LruMap}; use polkadot_node_subsystem::overseer; -use polkadot_node_subsystem_util::runtime::RuntimeInfo; -use polkadot_primitives::{AuthorityDiscoveryId, GroupIndex, Hash, SessionIndex, ValidatorIndex}; +use polkadot_node_subsystem_util::runtime::{request_node_features, RuntimeInfo}; +use polkadot_primitives::{ + AuthorityDiscoveryId, GroupIndex, Hash, NodeFeatures, SessionIndex, ValidatorIndex, +}; use crate::{ error::{Error, Result}, @@ -62,6 +64,9 @@ pub struct SessionInfo { /// /// `None`, if we are not in fact part of any group. pub our_group: Option, + + /// Node features. + pub node_features: Option, } /// Report of bad validators. @@ -87,39 +92,29 @@ impl SessionCache { } } - /// Tries to retrieve `SessionInfo` and calls `with_info` if successful. - /// + /// Tries to retrieve `SessionInfo`. /// If this node is not a validator, the function will return `None`. - /// - /// Use this function over any `fetch_session_info` if all you need is a reference to - /// `SessionInfo`, as it avoids an expensive clone. - pub async fn with_session_info( - &mut self, + pub async fn get_session_info<'a, Context>( + &'a mut self, ctx: &mut Context, runtime: &mut RuntimeInfo, parent: Hash, session_index: SessionIndex, - with_info: F, - ) -> Result> - where - F: FnOnce(&SessionInfo) -> R, - { - if let Some(o_info) = self.session_info_cache.get(&session_index) { - gum::trace!(target: LOG_TARGET, session_index, "Got session from lru"); - return Ok(Some(with_info(o_info))) + ) -> Result> { + gum::trace!(target: LOG_TARGET, session_index, "Calling `get_session_info`"); + + if self.session_info_cache.get(&session_index).is_none() { + if let Some(info) = + Self::query_info_from_runtime(ctx, runtime, parent, session_index).await? + { + gum::trace!(target: LOG_TARGET, session_index, "Storing session info in lru!"); + self.session_info_cache.insert(session_index, info); + } else { + return Ok(None) + } } - if let Some(info) = - self.query_info_from_runtime(ctx, runtime, parent, session_index).await? - { - gum::trace!(target: LOG_TARGET, session_index, "Calling `with_info`"); - let r = with_info(&info); - gum::trace!(target: LOG_TARGET, session_index, "Storing session info in lru!"); - self.session_info_cache.insert(session_index, info); - Ok(Some(r)) - } else { - Ok(None) - } + Ok(self.session_info_cache.get(&session_index).map(|i| &*i)) } /// Variant of `report_bad` that never fails, but just logs errors. @@ -171,7 +166,6 @@ impl SessionCache { /// /// Returns: `None` if not a validator. async fn query_info_from_runtime( - &self, ctx: &mut Context, runtime: &mut RuntimeInfo, relay_parent: Hash, @@ -181,6 +175,9 @@ impl SessionCache { .get_session_info_by_index(ctx.sender(), relay_parent, session_index) .await?; + let node_features = + request_node_features(relay_parent, session_index, ctx.sender()).await?; + let discovery_keys = info.session_info.discovery_keys.clone(); let mut validator_groups = info.session_info.validator_groups.clone(); @@ -208,7 +205,13 @@ impl SessionCache { }) .collect(); - let info = SessionInfo { validator_groups, our_index, session_index, our_group }; + let info = SessionInfo { + validator_groups, + our_index, + session_index, + our_group, + node_features, + }; return Ok(Some(info)) } return Ok(None) diff --git a/polkadot/node/network/availability-distribution/src/requester/tests.rs b/polkadot/node/network/availability-distribution/src/requester/tests.rs index 0dedd4f091acd692c5b319f5669c1356bf335e2b..09567a8f87d322f4befca53c14712b72b9b0e0fc 100644 --- a/polkadot/node/network/availability-distribution/src/requester/tests.rs +++ b/polkadot/node/network/availability-distribution/src/requester/tests.rs @@ -14,21 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::collections::HashMap; - -use std::future::Future; - use futures::FutureExt; +use std::{collections::HashMap, future::Future}; -use polkadot_node_network_protocol::jaeger; +use polkadot_node_network_protocol::{jaeger, request_response::ReqProtocolNames}; use polkadot_node_primitives::{BlockData, ErasureChunk, PoV}; -use polkadot_node_subsystem_test_helpers::mock::new_leaf; use polkadot_node_subsystem_util::runtime::RuntimeInfo; use polkadot_primitives::{ - BlockNumber, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, NodeFeatures, + BlockNumber, ChunkIndex, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, ScheduledCore, SessionIndex, SessionInfo, }; -use sp_core::traits::SpawnNamed; +use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; use polkadot_node_subsystem::{ messages::{ @@ -38,19 +34,21 @@ use polkadot_node_subsystem::{ ActiveLeavesUpdate, SpawnGlue, }; use polkadot_node_subsystem_test_helpers::{ - make_subsystem_context, mock::make_ferdie_keystore, TestSubsystemContext, - TestSubsystemContextHandle, + make_subsystem_context, + mock::{make_ferdie_keystore, new_leaf}, + TestSubsystemContext, TestSubsystemContextHandle, }; -use sp_core::testing::TaskExecutor; - -use crate::tests::mock::{get_valid_chunk_data, make_session_info, OccupiedCoreBuilder}; +use crate::tests::{ + mock::{get_valid_chunk_data, make_session_info, OccupiedCoreBuilder}, + node_features_with_mapping_enabled, +}; use super::Requester; fn get_erasure_chunk() -> ErasureChunk { let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; - get_valid_chunk_data(pov).1 + get_valid_chunk_data(pov, 10, ChunkIndex(0)).1 } #[derive(Clone)] @@ -126,7 +124,7 @@ fn spawn_virtual_overseer( .expect("Receiver should be alive."); }, RuntimeApiRequest::NodeFeatures(_, tx) => { - tx.send(Ok(NodeFeatures::EMPTY)) + tx.send(Ok(node_features_with_mapping_enabled())) .expect("Receiver should be alive."); }, RuntimeApiRequest::AvailabilityCores(tx) => { @@ -146,6 +144,8 @@ fn spawn_virtual_overseer( group_responsible: GroupIndex(1), para_id, relay_parent: hash, + n_validators: 10, + chunk_index: ChunkIndex(0), } .build() .0, @@ -201,7 +201,8 @@ fn test_harness>( #[test] fn check_ancestry_lookup_in_same_session() { let test_state = TestState::new(); - let mut requester = Requester::new(Default::default()); + let mut requester = + Requester::new(ReqProtocolNames::new(&Hash::repeat_byte(0xff), None), Default::default()); let keystore = make_ferdie_keystore(); let mut runtime = RuntimeInfo::new(Some(keystore)); @@ -268,7 +269,8 @@ fn check_ancestry_lookup_in_same_session() { #[test] fn check_ancestry_lookup_in_different_sessions() { let mut test_state = TestState::new(); - let mut requester = Requester::new(Default::default()); + let mut requester = + Requester::new(ReqProtocolNames::new(&Hash::repeat_byte(0xff), None), Default::default()); let keystore = make_ferdie_keystore(); let mut runtime = RuntimeInfo::new(Some(keystore)); diff --git a/polkadot/node/network/availability-distribution/src/responder.rs b/polkadot/node/network/availability-distribution/src/responder.rs index 54b188f7f01fc7e22b4ea7679be0a67f8d9d0d37..2c1885d277275c56772147d4ddd4cb29ccdb4cdc 100644 --- a/polkadot/node/network/availability-distribution/src/responder.rs +++ b/polkadot/node/network/availability-distribution/src/responder.rs @@ -18,11 +18,12 @@ use std::sync::Arc; -use futures::channel::oneshot; +use futures::{channel::oneshot, select, FutureExt}; use fatality::Nested; +use parity_scale_codec::{Decode, Encode}; use polkadot_node_network_protocol::{ - request_response::{v1, IncomingRequest, IncomingRequestReceiver}, + request_response::{v1, v2, IncomingRequest, IncomingRequestReceiver, IsRequest}, UnifiedReputationChange as Rep, }; use polkadot_node_primitives::{AvailableData, ErasureChunk}; @@ -66,33 +67,66 @@ pub async fn run_pov_receiver( } /// Receiver task to be forked as a separate task to handle chunk requests. -pub async fn run_chunk_receiver( +pub async fn run_chunk_receivers( mut sender: Sender, - mut receiver: IncomingRequestReceiver, + mut receiver_v1: IncomingRequestReceiver, + mut receiver_v2: IncomingRequestReceiver, metrics: Metrics, ) where Sender: SubsystemSender, { + let make_resp_v1 = |chunk: Option| match chunk { + None => v1::ChunkFetchingResponse::NoSuchChunk, + Some(chunk) => v1::ChunkFetchingResponse::Chunk(chunk.into()), + }; + + let make_resp_v2 = |chunk: Option| match chunk { + None => v2::ChunkFetchingResponse::NoSuchChunk, + Some(chunk) => v2::ChunkFetchingResponse::Chunk(chunk.into()), + }; + loop { - match receiver.recv(|| vec![COST_INVALID_REQUEST]).await.into_nested() { - Ok(Ok(msg)) => { - answer_chunk_request_log(&mut sender, msg, &metrics).await; - }, - Err(fatal) => { - gum::debug!( - target: LOG_TARGET, - error = ?fatal, - "Shutting down chunk receiver." - ); - return - }, - Ok(Err(jfyi)) => { - gum::debug!( - target: LOG_TARGET, - error = ?jfyi, - "Error decoding incoming chunk request." - ); + select! { + res = receiver_v1.recv(|| vec![COST_INVALID_REQUEST]).fuse() => match res.into_nested() { + Ok(Ok(msg)) => { + answer_chunk_request_log(&mut sender, msg, make_resp_v1, &metrics).await; + }, + Err(fatal) => { + gum::debug!( + target: LOG_TARGET, + error = ?fatal, + "Shutting down chunk receiver." + ); + return + }, + Ok(Err(jfyi)) => { + gum::debug!( + target: LOG_TARGET, + error = ?jfyi, + "Error decoding incoming chunk request." + ); + } }, + res = receiver_v2.recv(|| vec![COST_INVALID_REQUEST]).fuse() => match res.into_nested() { + Ok(Ok(msg)) => { + answer_chunk_request_log(&mut sender, msg.into(), make_resp_v2, &metrics).await; + }, + Err(fatal) => { + gum::debug!( + target: LOG_TARGET, + error = ?fatal, + "Shutting down chunk receiver." + ); + return + }, + Ok(Err(jfyi)) => { + gum::debug!( + target: LOG_TARGET, + error = ?jfyi, + "Error decoding incoming chunk request." + ); + } + } } } } @@ -124,15 +158,18 @@ pub async fn answer_pov_request_log( /// Variant of `answer_chunk_request` that does Prometheus metric and logging on errors. /// /// Any errors of `answer_request` will simply be logged. -pub async fn answer_chunk_request_log( +pub async fn answer_chunk_request_log( sender: &mut Sender, - req: IncomingRequest, + req: IncomingRequest, + make_response: MakeResp, metrics: &Metrics, -) -> () -where +) where + Req: IsRequest + Decode + Encode + Into, + Req::Response: Encode, Sender: SubsystemSender, + MakeResp: Fn(Option) -> Req::Response, { - let res = answer_chunk_request(sender, req).await; + let res = answer_chunk_request(sender, req, make_response).await; match res { Ok(result) => metrics.on_served_chunk(if result { SUCCEEDED } else { NOT_FOUND }), Err(err) => { @@ -177,39 +214,46 @@ where /// Answer an incoming chunk request by querying the av store. /// /// Returns: `Ok(true)` if chunk was found and served. -pub async fn answer_chunk_request( +pub async fn answer_chunk_request( sender: &mut Sender, - req: IncomingRequest, + req: IncomingRequest, + make_response: MakeResp, ) -> Result where Sender: SubsystemSender, + Req: IsRequest + Decode + Encode + Into, + Req::Response: Encode, + MakeResp: Fn(Option) -> Req::Response, { - let span = jaeger::Span::new(req.payload.candidate_hash, "answer-chunk-request"); + // V1 and V2 requests have the same payload, so decoding into either one will work. It's the + // responses that differ, hence the `MakeResp` generic. + let payload: v1::ChunkFetchingRequest = req.payload.into(); + let span = jaeger::Span::new(payload.candidate_hash, "answer-chunk-request"); let _child_span = span .child("answer-chunk-request") - .with_trace_id(req.payload.candidate_hash) - .with_chunk_index(req.payload.index.0); + .with_trace_id(payload.candidate_hash) + .with_validator_index(payload.index); - let chunk = query_chunk(sender, req.payload.candidate_hash, req.payload.index).await?; + let chunk = query_chunk(sender, payload.candidate_hash, payload.index).await?; let result = chunk.is_some(); gum::trace!( target: LOG_TARGET, - hash = ?req.payload.candidate_hash, - index = ?req.payload.index, + hash = ?payload.candidate_hash, + index = ?payload.index, peer = ?req.peer, has_data = ?chunk.is_some(), "Serving chunk", ); - let response = match chunk { - None => v1::ChunkFetchingResponse::NoSuchChunk, - Some(chunk) => v1::ChunkFetchingResponse::Chunk(chunk.into()), - }; + let response = make_response(chunk); + + req.pending_response + .send_response(response) + .map_err(|_| JfyiError::SendResponse)?; - req.send_response(response).map_err(|_| JfyiError::SendResponse)?; Ok(result) } diff --git a/polkadot/node/network/availability-distribution/src/tests/mock.rs b/polkadot/node/network/availability-distribution/src/tests/mock.rs index 3df662fe546c07f7a7f58d02d0ceafd98a7e1b6c..b41c493a10721bbdd988125d1c355ad9e4cc4824 100644 --- a/polkadot/node/network/availability-distribution/src/tests/mock.rs +++ b/polkadot/node/network/availability-distribution/src/tests/mock.rs @@ -23,9 +23,9 @@ use sp_keyring::Sr25519Keyring; use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks}; use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV, Proof}; use polkadot_primitives::{ - CandidateCommitments, CandidateDescriptor, CandidateHash, CommittedCandidateReceipt, - GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, OccupiedCore, PersistedValidationData, - SessionInfo, ValidatorIndex, + CandidateCommitments, CandidateDescriptor, CandidateHash, ChunkIndex, + CommittedCandidateReceipt, GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, OccupiedCore, + PersistedValidationData, SessionInfo, ValidatorIndex, }; use polkadot_primitives_test_helpers::{ dummy_collator, dummy_collator_signature, dummy_hash, dummy_validation_code, @@ -75,13 +75,16 @@ pub struct OccupiedCoreBuilder { pub group_responsible: GroupIndex, pub para_id: ParaId, pub relay_parent: Hash, + pub n_validators: usize, + pub chunk_index: ChunkIndex, } impl OccupiedCoreBuilder { pub fn build(self) -> (OccupiedCore, (CandidateHash, ErasureChunk)) { let pov = PoV { block_data: BlockData(vec![45, 46, 47]) }; let pov_hash = pov.hash(); - let (erasure_root, chunk) = get_valid_chunk_data(pov.clone()); + let (erasure_root, chunk) = + get_valid_chunk_data(pov.clone(), self.n_validators, self.chunk_index); let candidate_receipt = TestCandidateBuilder { para_id: self.para_id, pov_hash, @@ -133,8 +136,11 @@ impl TestCandidateBuilder { } // Get chunk for index 0 -pub fn get_valid_chunk_data(pov: PoV) -> (Hash, ErasureChunk) { - let fake_validator_count = 10; +pub fn get_valid_chunk_data( + pov: PoV, + n_validators: usize, + chunk_index: ChunkIndex, +) -> (Hash, ErasureChunk) { let persisted = PersistedValidationData { parent_head: HeadData(vec![7, 8, 9]), relay_parent_number: Default::default(), @@ -142,17 +148,17 @@ pub fn get_valid_chunk_data(pov: PoV) -> (Hash, ErasureChunk) { relay_parent_storage_root: Default::default(), }; let available_data = AvailableData { validation_data: persisted, pov: Arc::new(pov) }; - let chunks = obtain_chunks(fake_validator_count, &available_data).unwrap(); + let chunks = obtain_chunks(n_validators, &available_data).unwrap(); let branches = branches(chunks.as_ref()); let root = branches.root(); let chunk = branches .enumerate() .map(|(index, (proof, chunk))| ErasureChunk { chunk: chunk.to_vec(), - index: ValidatorIndex(index as _), + index: ChunkIndex(index as _), proof: Proof::try_from(proof).unwrap(), }) - .next() - .expect("There really should be 10 chunks."); + .nth(chunk_index.0 as usize) + .expect("There really should be enough chunks."); (root, chunk) } diff --git a/polkadot/node/network/availability-distribution/src/tests/mod.rs b/polkadot/node/network/availability-distribution/src/tests/mod.rs index 214498979fb68307ce45705e396a7e306d53da87..b30e11a293c8d54c6b275c8759d3502ffa0323f0 100644 --- a/polkadot/node/network/availability-distribution/src/tests/mod.rs +++ b/polkadot/node/network/availability-distribution/src/tests/mod.rs @@ -17,9 +17,12 @@ use std::collections::HashSet; use futures::{executor, future, Future}; +use rstest::rstest; -use polkadot_node_network_protocol::request_response::{IncomingRequest, ReqProtocolNames}; -use polkadot_primitives::{Block, CoreState, Hash}; +use polkadot_node_network_protocol::request_response::{ + IncomingRequest, Protocol, ReqProtocolNames, +}; +use polkadot_primitives::{node_features, Block, CoreState, Hash, NodeFeatures}; use sp_keystore::KeystorePtr; use polkadot_node_subsystem_test_helpers as test_helpers; @@ -35,67 +38,129 @@ pub(crate) mod mock; fn test_harness>( keystore: KeystorePtr, + req_protocol_names: ReqProtocolNames, test_fx: impl FnOnce(TestHarness) -> T, -) { - sp_tracing::try_init_simple(); +) -> std::result::Result<(), FatalError> { + sp_tracing::init_for_tests(); let pool = sp_core::testing::TaskExecutor::new(); let (context, virtual_overseer) = test_helpers::make_subsystem_context(pool.clone()); - let genesis_hash = Hash::repeat_byte(0xff); - let req_protocol_names = ReqProtocolNames::new(&genesis_hash, None); let (pov_req_receiver, pov_req_cfg) = IncomingRequest::get_config_receiver::< Block, sc_network::NetworkWorker, >(&req_protocol_names); - let (chunk_req_receiver, chunk_req_cfg) = IncomingRequest::get_config_receiver::< + let (chunk_req_v1_receiver, chunk_req_v1_cfg) = IncomingRequest::get_config_receiver::< + Block, + sc_network::NetworkWorker, + >(&req_protocol_names); + let (chunk_req_v2_receiver, chunk_req_v2_cfg) = IncomingRequest::get_config_receiver::< Block, sc_network::NetworkWorker, >(&req_protocol_names); let subsystem = AvailabilityDistributionSubsystem::new( keystore, - IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, + IncomingRequestReceivers { pov_req_receiver, chunk_req_v1_receiver, chunk_req_v2_receiver }, + req_protocol_names, Default::default(), ); let subsystem = subsystem.run(context); - let test_fut = test_fx(TestHarness { virtual_overseer, pov_req_cfg, chunk_req_cfg, pool }); + let test_fut = test_fx(TestHarness { + virtual_overseer, + pov_req_cfg, + chunk_req_v1_cfg, + chunk_req_v2_cfg, + pool, + }); futures::pin_mut!(test_fut); futures::pin_mut!(subsystem); - executor::block_on(future::join(test_fut, subsystem)).1.unwrap(); + executor::block_on(future::join(test_fut, subsystem)).1 +} + +pub fn node_features_with_mapping_enabled() -> NodeFeatures { + let mut node_features = NodeFeatures::new(); + node_features.resize(node_features::FeatureIndex::AvailabilityChunkMapping as usize + 1, false); + node_features.set(node_features::FeatureIndex::AvailabilityChunkMapping as u8 as usize, true); + node_features } /// Simple basic check, whether the subsystem works as expected. /// /// Exceptional cases are tested as unit tests in `fetch_task`. -#[test] -fn check_basic() { - let state = TestState::default(); - test_harness(state.keystore.clone(), move |harness| state.run(harness)); +#[rstest] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV1)] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV2)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV1)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV2)] +fn check_basic(#[case] node_features: NodeFeatures, #[case] chunk_resp_protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + let state = + TestState::new(node_features.clone(), req_protocol_names.clone(), chunk_resp_protocol); + + if node_features == node_features_with_mapping_enabled() && + chunk_resp_protocol == Protocol::ChunkFetchingV1 + { + // For this specific case, chunk fetching is not possible, because the ValidatorIndex is not + // equal to the ChunkIndex and the peer does not send back the actual ChunkIndex. + let _ = test_harness(state.keystore.clone(), req_protocol_names, move |harness| { + state.run_assert_timeout(harness) + }); + } else { + test_harness(state.keystore.clone(), req_protocol_names, move |harness| state.run(harness)) + .unwrap(); + } } /// Check whether requester tries all validators in group. -#[test] -fn check_fetch_tries_all() { - let mut state = TestState::default(); +#[rstest] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV1)] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV2)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV1)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV2)] +fn check_fetch_tries_all( + #[case] node_features: NodeFeatures, + #[case] chunk_resp_protocol: Protocol, +) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + let mut state = + TestState::new(node_features.clone(), req_protocol_names.clone(), chunk_resp_protocol); for (_, v) in state.chunks.iter_mut() { // 4 validators in group, so this should still succeed: v.push(None); v.push(None); v.push(None); } - test_harness(state.keystore.clone(), move |harness| state.run(harness)); + + if node_features == node_features_with_mapping_enabled() && + chunk_resp_protocol == Protocol::ChunkFetchingV1 + { + // For this specific case, chunk fetching is not possible, because the ValidatorIndex is not + // equal to the ChunkIndex and the peer does not send back the actual ChunkIndex. + let _ = test_harness(state.keystore.clone(), req_protocol_names, move |harness| { + state.run_assert_timeout(harness) + }); + } else { + test_harness(state.keystore.clone(), req_protocol_names, move |harness| state.run(harness)) + .unwrap(); + } } /// Check whether requester tries all validators in group /// /// Check that requester will retry the fetch on error on the next block still pending /// availability. -#[test] -fn check_fetch_retry() { - let mut state = TestState::default(); +#[rstest] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV1)] +#[case(NodeFeatures::EMPTY, Protocol::ChunkFetchingV2)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV1)] +#[case(node_features_with_mapping_enabled(), Protocol::ChunkFetchingV2)] +fn check_fetch_retry(#[case] node_features: NodeFeatures, #[case] chunk_resp_protocol: Protocol) { + let req_protocol_names = ReqProtocolNames::new(&Hash::repeat_byte(0xff), None); + let mut state = + TestState::new(node_features.clone(), req_protocol_names.clone(), chunk_resp_protocol); state .cores .insert(state.relay_chain[2], state.cores.get(&state.relay_chain[1]).unwrap().clone()); @@ -126,5 +191,17 @@ fn check_fetch_retry() { v.push(None); v.push(None); } - test_harness(state.keystore.clone(), move |harness| state.run(harness)); + + if node_features == node_features_with_mapping_enabled() && + chunk_resp_protocol == Protocol::ChunkFetchingV1 + { + // For this specific case, chunk fetching is not possible, because the ValidatorIndex is not + // equal to the ChunkIndex and the peer does not send back the actual ChunkIndex. + let _ = test_harness(state.keystore.clone(), req_protocol_names, move |harness| { + state.run_assert_timeout(harness) + }); + } else { + test_harness(state.keystore.clone(), req_protocol_names, move |harness| state.run(harness)) + .unwrap(); + } } diff --git a/polkadot/node/network/availability-distribution/src/tests/state.rs b/polkadot/node/network/availability-distribution/src/tests/state.rs index 93411511e763af437d7813c9e5d83bac4609959e..ecc3eefbf3da30e0bfd5275be30318ddaa2192ba 100644 --- a/polkadot/node/network/availability-distribution/src/tests/state.rs +++ b/polkadot/node/network/availability-distribution/src/tests/state.rs @@ -19,9 +19,9 @@ use std::{ time::Duration, }; -use network::ProtocolName; +use network::{request_responses::OutgoingResponse, ProtocolName, RequestFailure}; use polkadot_node_subsystem_test_helpers::TestSubsystemContextHandle; -use polkadot_node_subsystem_util::TimeoutExt; +use polkadot_node_subsystem_util::{availability_chunks::availability_chunk_index, TimeoutExt}; use futures::{ channel::{mpsc, oneshot}, @@ -35,7 +35,7 @@ use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; use sp_keystore::KeystorePtr; use polkadot_node_network_protocol::request_response::{ - v1, IncomingRequest, OutgoingRequest, Requests, + v1, v2, IncomingRequest, OutgoingRequest, Protocol, ReqProtocolNames, Requests, }; use polkadot_node_primitives::ErasureChunk; use polkadot_node_subsystem::{ @@ -47,8 +47,8 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - CandidateHash, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, NodeFeatures, - ScheduledCore, SessionInfo, ValidatorIndex, + CandidateHash, ChunkIndex, CoreIndex, CoreState, ExecutorParams, GroupIndex, Hash, + Id as ParaId, NodeFeatures, ScheduledCore, SessionInfo, ValidatorIndex, }; use test_helpers::mock::{make_ferdie_keystore, new_leaf}; @@ -59,7 +59,8 @@ type VirtualOverseer = test_helpers::TestSubsystemContextHandle>, pub keystore: KeystorePtr, + pub node_features: NodeFeatures, + pub chunk_response_protocol: Protocol, + pub req_protocol_names: ReqProtocolNames, + pub our_chunk_index: ChunkIndex, } -impl Default for TestState { - fn default() -> Self { +impl TestState { + /// Initialize a default test state. + pub fn new( + node_features: NodeFeatures, + req_protocol_names: ReqProtocolNames, + chunk_response_protocol: Protocol, + ) -> Self { let relay_chain: Vec<_> = (1u8..10).map(Hash::repeat_byte).collect(); let chain_a = ParaId::from(1); let chain_b = ParaId::from(2); @@ -97,6 +107,14 @@ impl Default for TestState { let session_info = make_session_info(); + let our_chunk_index = availability_chunk_index( + Some(&node_features), + session_info.validators.len(), + CoreIndex(1), + ValidatorIndex(0), + ) + .unwrap(); + let (cores, chunks) = { let mut cores = HashMap::new(); let mut chunks = HashMap::new(); @@ -123,6 +141,8 @@ impl Default for TestState { group_responsible: GroupIndex(i as _), para_id: *para_id, relay_parent: *relay_parent, + n_validators: session_info.validators.len(), + chunk_index: our_chunk_index, } .build(); (CoreState::Occupied(core), chunk) @@ -132,8 +152,8 @@ impl Default for TestState { // Skip chunks for our own group (won't get fetched): let mut chunks_other_groups = p_chunks.into_iter(); chunks_other_groups.next(); - for (validator_index, chunk) in chunks_other_groups { - chunks.insert((validator_index, chunk.index), vec![Some(chunk)]); + for (candidate, chunk) in chunks_other_groups { + chunks.insert((candidate, ValidatorIndex(0)), vec![Some(chunk)]); } } (cores, chunks) @@ -145,18 +165,27 @@ impl Default for TestState { session_info, cores, keystore, + node_features, + chunk_response_protocol, + req_protocol_names, + our_chunk_index, } } -} -impl TestState { /// Run, but fail after some timeout. pub async fn run(self, harness: TestHarness) { // Make sure test won't run forever. - let f = self.run_inner(harness).timeout(Duration::from_secs(10)); + let f = self.run_inner(harness).timeout(Duration::from_secs(5)); assert!(f.await.is_some(), "Test ran into timeout"); } + /// Run, and assert an expected timeout. + pub async fn run_assert_timeout(self, harness: TestHarness) { + // Make sure test won't run forever. + let f = self.run_inner(harness).timeout(Duration::from_secs(5)); + assert!(f.await.is_none(), "Test should have run into timeout"); + } + /// Run tests with the given mock values in `TestState`. /// /// This will simply advance through the simulated chain and examines whether the subsystem @@ -214,15 +243,41 @@ impl TestState { )) => { for req in reqs { // Forward requests: - let in_req = to_incoming_req(&harness.pool, req); - harness - .chunk_req_cfg - .inbound_queue - .as_mut() - .unwrap() - .send(in_req.into_raw()) - .await - .unwrap(); + match self.chunk_response_protocol { + Protocol::ChunkFetchingV1 => { + let in_req = to_incoming_req_v1( + &harness.pool, + req, + self.req_protocol_names.get_name(Protocol::ChunkFetchingV1), + ); + + harness + .chunk_req_v1_cfg + .inbound_queue + .as_mut() + .unwrap() + .send(in_req.into_raw()) + .await + .unwrap(); + }, + Protocol::ChunkFetchingV2 => { + let in_req = to_incoming_req_v2( + &harness.pool, + req, + self.req_protocol_names.get_name(Protocol::ChunkFetchingV2), + ); + + harness + .chunk_req_v2_cfg + .inbound_queue + .as_mut() + .unwrap() + .send(in_req.into_raw()) + .await + .unwrap(); + }, + _ => panic!("Unexpected protocol"), + } } }, AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryChunk( @@ -240,13 +295,16 @@ impl TestState { AllMessages::AvailabilityStore(AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk, + validator_index, tx, .. }) => { assert!( - self.valid_chunks.contains(&(candidate_hash, chunk.index)), + self.valid_chunks.contains(&(candidate_hash, validator_index)), "Only valid chunks should ever get stored." ); + assert_eq!(self.our_chunk_index, chunk.index); + tx.send(Ok(())).expect("Receiver is expected to be alive"); gum::trace!(target: LOG_TARGET, "'Stored' fetched chunk."); remaining_stores -= 1; @@ -265,14 +323,15 @@ impl TestState { tx.send(Ok(Some(ExecutorParams::default()))) .expect("Receiver should be alive."); }, - RuntimeApiRequest::NodeFeatures(_, si_tx) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).expect("Receiver should be alive."); - }, RuntimeApiRequest::AvailabilityCores(tx) => { gum::trace!(target: LOG_TARGET, cores= ?self.cores[&hash], hash = ?hash, "Sending out cores for hash"); tx.send(Ok(self.cores[&hash].clone())) .expect("Receiver should still be alive"); }, + RuntimeApiRequest::NodeFeatures(_, tx) => { + tx.send(Ok(self.node_features.clone())) + .expect("Receiver should still be alive"); + }, _ => { panic!("Unexpected runtime request: {:?}", req); }, @@ -286,7 +345,10 @@ impl TestState { .unwrap_or_default(); response_channel.send(Ok(ancestors)).expect("Receiver is expected to be alive"); }, - _ => {}, + + _ => { + panic!("Received unexpected message") + }, } } @@ -310,30 +372,47 @@ async fn overseer_recv(rx: &mut mpsc::UnboundedReceiver) -> AllMess rx.next().await.expect("Test subsystem no longer live") } -fn to_incoming_req( +fn to_incoming_req_v1( executor: &TaskExecutor, outgoing: Requests, + protocol_name: ProtocolName, ) -> IncomingRequest { match outgoing { - Requests::ChunkFetchingV1(OutgoingRequest { payload, pending_response, .. }) => { - let (tx, rx): (oneshot::Sender, oneshot::Receiver<_>) = - oneshot::channel(); - executor.spawn( - "message-forwarding", - None, - async { - let response = rx.await; - let payload = response.expect("Unexpected canceled request").result; - pending_response - .send( - payload - .map_err(|_| network::RequestFailure::Refused) - .map(|r| (r, ProtocolName::from(""))), - ) - .expect("Sending response is expected to work"); - } - .boxed(), - ); + Requests::ChunkFetching(OutgoingRequest { + pending_response, + fallback_request: Some((fallback_request, fallback_protocol)), + .. + }) => { + assert_eq!(fallback_protocol, Protocol::ChunkFetchingV1); + + let tx = spawn_message_forwarding(executor, protocol_name, pending_response); + + IncomingRequest::new( + // We don't really care: + network::PeerId::random().into(), + fallback_request, + tx, + ) + }, + _ => panic!("Unexpected request!"), + } +} + +fn to_incoming_req_v2( + executor: &TaskExecutor, + outgoing: Requests, + protocol_name: ProtocolName, +) -> IncomingRequest { + match outgoing { + Requests::ChunkFetching(OutgoingRequest { + payload, + pending_response, + fallback_request: Some((_, fallback_protocol)), + .. + }) => { + assert_eq!(fallback_protocol, Protocol::ChunkFetchingV1); + + let tx = spawn_message_forwarding(executor, protocol_name, pending_response); IncomingRequest::new( // We don't really care: @@ -345,3 +424,26 @@ fn to_incoming_req( _ => panic!("Unexpected request!"), } } + +fn spawn_message_forwarding( + executor: &TaskExecutor, + protocol_name: ProtocolName, + pending_response: oneshot::Sender, ProtocolName), RequestFailure>>, +) -> oneshot::Sender { + let (tx, rx): (oneshot::Sender, oneshot::Receiver<_>) = + oneshot::channel(); + executor.spawn( + "message-forwarding", + None, + async { + let response = rx.await; + let payload = response.expect("Unexpected canceled request").result; + pending_response + .send(payload.map_err(|_| RequestFailure::Refused).map(|r| (r, protocol_name))) + .expect("Sending response is expected to work"); + } + .boxed(), + ); + + tx +} diff --git a/polkadot/node/network/availability-recovery/Cargo.toml b/polkadot/node/network/availability-recovery/Cargo.toml index dd0e0c432345ed7006fa4a18fbb05bc9efca8538..1c2b5f4968ad2e52776aff5c992895d026836eda 100644 --- a/polkadot/node/network/availability-recovery/Cargo.toml +++ b/polkadot/node/network/availability-recovery/Cargo.toml @@ -14,7 +14,7 @@ futures = "0.3.30" tokio = "1.37" schnellru = "0.2.1" rand = "0.8.5" -fatality = "0.0.6" +fatality = "0.1.1" thiserror = { workspace = true } async-trait = "0.1.79" gum = { package = "tracing-gum", path = "../../gum" } @@ -25,15 +25,16 @@ polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-network-protocol = { path = "../protocol" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sc-network = { path = "../../../../substrate/client/network" } [dev-dependencies] assert_matches = "1.4.0" -env_logger = "0.11" futures-timer = "3.0.2" +rstest = "0.18.2" log = { workspace = true, default-features = true } +sp-tracing = { path = "../../../../substrate/primitives/tracing" } sp-core = { path = "../../../../substrate/primitives/core" } sp-keyring = { path = "../../../../substrate/primitives/keyring" } sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto" } diff --git a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs index d9bdc1a2d944d71231d0679fd5e5ef79a52cc782..c734ac99e870df128c5443e9cb3b83371bc1156f 100644 --- a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs +++ b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs @@ -23,7 +23,7 @@ use polkadot_subsystem_bench::{ availability::{ - benchmark_availability_read, prepare_test, DataAvailabilityReadOptions, + benchmark_availability_read, prepare_test, DataAvailabilityReadOptions, Strategy, TestDataAvailability, TestState, }, configuration::TestConfiguration, @@ -37,7 +37,7 @@ const BENCH_COUNT: usize = 10; fn main() -> Result<(), String> { let mut messages = vec![]; - let options = DataAvailabilityReadOptions { fetch_from_backers: true }; + let options = DataAvailabilityReadOptions { strategy: Strategy::FullFromBackers }; let mut config = TestConfiguration::default(); config.num_blocks = 3; config.generate_pov_sizes(); @@ -51,11 +51,7 @@ fn main() -> Result<(), String> { std::io::stdout().flush().unwrap(); let (mut env, _cfgs) = prepare_test(&state, TestDataAvailability::Read(options.clone()), false); - env.runtime().block_on(benchmark_availability_read( - "data_availability_read", - &mut env, - &state, - )) + env.runtime().block_on(benchmark_availability_read(&mut env, &state)) }) .collect(); println!("\rDone!{}", " ".repeat(BENCH_COUNT)); @@ -74,7 +70,7 @@ fn main() -> Result<(), String> { ("Received from peers", 307203.0000, 0.001), ("Sent to peers", 1.6667, 0.001), ])); - messages.extend(average_usage.check_cpu_usage(&[("availability-recovery", 12.8338, 0.1)])); + messages.extend(average_usage.check_cpu_usage(&[("availability-recovery", 12.8412, 0.1)])); if messages.is_empty() { Ok(()) diff --git a/polkadot/node/network/availability-recovery/src/error.rs b/polkadot/node/network/availability-recovery/src/error.rs index 47277a521b81ee72261ab8d71ff9f0cf97bf56ad..eaec4cbc9d9426fce260a4fdc2744506bf34c830 100644 --- a/polkadot/node/network/availability-recovery/src/error.rs +++ b/polkadot/node/network/availability-recovery/src/error.rs @@ -16,20 +16,34 @@ //! The `Error` and `Result` types used by the subsystem. +use crate::LOG_TARGET; +use fatality::{fatality, Nested}; use futures::channel::oneshot; -use thiserror::Error; +use polkadot_node_network_protocol::request_response::incoming; +use polkadot_node_subsystem::{RecoveryError, SubsystemError}; +use polkadot_primitives::Hash; /// Error type used by the Availability Recovery subsystem. -#[derive(Debug, Error)] +#[fatality(splitable)] pub enum Error { - #[error(transparent)] - Subsystem(#[from] polkadot_node_subsystem::SubsystemError), + #[fatal] + #[error("Spawning subsystem task failed: {0}")] + SpawnTask(#[source] SubsystemError), + + /// Receiving subsystem message from overseer failed. + #[fatal] + #[error("Receiving message from overseer failed: {0}")] + SubsystemReceive(#[source] SubsystemError), + #[fatal] #[error("failed to query full data from store")] CanceledQueryFullData(#[source] oneshot::Canceled), - #[error("failed to query session info")] - CanceledSessionInfo(#[source] oneshot::Canceled), + #[error("`SessionInfo` is `None` at {0}")] + SessionInfoUnavailable(Hash), + + #[error("failed to query node features from runtime")] + RequestNodeFeatures(#[source] polkadot_node_subsystem_util::runtime::Error), #[error("failed to send response")] CanceledResponseSender, @@ -40,8 +54,38 @@ pub enum Error { #[error(transparent)] Erasure(#[from] polkadot_erasure_coding::Error), + #[fatal] #[error(transparent)] - Util(#[from] polkadot_node_subsystem_util::Error), + Oneshot(#[from] oneshot::Canceled), + + #[fatal(forward)] + #[error("Error during recovery: {0}")] + Recovery(#[from] RecoveryError), + + #[fatal(forward)] + #[error("Retrieving next incoming request failed: {0}")] + IncomingRequest(#[from] incoming::Error), } pub type Result = std::result::Result; + +/// Utility for eating top level errors and log them. +/// +/// We basically always want to try and continue on error, unless the error is fatal for the entire +/// subsystem. +pub fn log_error(result: Result<()>) -> std::result::Result<(), FatalError> { + match result.into_nested()? { + Ok(()) => Ok(()), + Err(jfyi) => { + jfyi.log(); + Ok(()) + }, + } +} + +impl JfyiError { + /// Log a `JfyiError`. + pub fn log(self) { + gum::warn!(target: LOG_TARGET, "{}", self); + } +} diff --git a/polkadot/node/network/availability-recovery/src/lib.rs b/polkadot/node/network/availability-recovery/src/lib.rs index 94b9d9546cdecd4a244bc3de9e10c1db4c3c066d..167125f987ab8f9af4f1d8b91ebd33d80bd05039 100644 --- a/polkadot/node/network/availability-recovery/src/lib.rs +++ b/polkadot/node/network/availability-recovery/src/lib.rs @@ -19,7 +19,7 @@ #![warn(missing_docs)] use std::{ - collections::{HashMap, VecDeque}, + collections::{BTreeMap, VecDeque}, iter::Iterator, num::NonZeroUsize, pin::Pin, @@ -34,31 +34,41 @@ use futures::{ stream::{FuturesUnordered, StreamExt}, task::{Context, Poll}, }; +use sc_network::ProtocolName; use schnellru::{ByLength, LruMap}; -use task::{FetchChunks, FetchChunksParams, FetchFull, FetchFullParams}; +use task::{ + FetchChunks, FetchChunksParams, FetchFull, FetchFullParams, FetchSystematicChunks, + FetchSystematicChunksParams, +}; -use fatality::Nested; use polkadot_erasure_coding::{ - branch_hash, branches, obtain_chunks_v1, recovery_threshold, Error as ErasureEncodingError, + branches, obtain_chunks_v1, recovery_threshold, systematic_recovery_threshold, + Error as ErasureEncodingError, }; use task::{RecoveryParams, RecoveryStrategy, RecoveryTask}; +use error::{log_error, Error, FatalError, Result}; use polkadot_node_network_protocol::{ - request_response::{v1 as request_v1, IncomingRequestReceiver}, + request_response::{ + v1 as request_v1, v2 as request_v2, IncomingRequestReceiver, IsRequest, ReqProtocolNames, + }, UnifiedReputationChange as Rep, }; -use polkadot_node_primitives::{AvailableData, ErasureChunk}; +use polkadot_node_primitives::AvailableData; use polkadot_node_subsystem::{ errors::RecoveryError, jaeger, messages::{AvailabilityRecoveryMessage, AvailabilityStoreMessage}, overseer, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, SpawnedSubsystem, - SubsystemContext, SubsystemError, SubsystemResult, + SubsystemContext, SubsystemError, +}; +use polkadot_node_subsystem_util::{ + availability_chunks::availability_chunk_indices, + runtime::{ExtendedSessionInfo, RuntimeInfo}, }; -use polkadot_node_subsystem_util::request_session_info; use polkadot_primitives::{ - BlakeTwo256, BlockNumber, CandidateHash, CandidateReceipt, GroupIndex, Hash, HashT, - SessionIndex, SessionInfo, ValidatorIndex, + node_features, BlockNumber, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, GroupIndex, + Hash, SessionIndex, ValidatorIndex, }; mod error; @@ -70,6 +80,8 @@ pub use metrics::Metrics; #[cfg(test)] mod tests; +type RecoveryResult = std::result::Result; + const LOG_TARGET: &str = "parachain::availability-recovery"; // Size of the LRU cache where we keep recovered data. @@ -77,19 +89,35 @@ const LRU_SIZE: u32 = 16; const COST_INVALID_REQUEST: Rep = Rep::CostMajor("Peer sent unparsable request"); -/// PoV size limit in bytes for which prefer fetching from backers. -const SMALL_POV_LIMIT: usize = 128 * 1024; +/// PoV size limit in bytes for which prefer fetching from backers. (conservative, Polkadot for now) +pub(crate) const CONSERVATIVE_FETCH_CHUNKS_THRESHOLD: usize = 1 * 1024 * 1024; +/// PoV size limit in bytes for which prefer fetching from backers. (Kusama and all testnets) +pub const FETCH_CHUNKS_THRESHOLD: usize = 4 * 1024 * 1024; #[derive(Clone, PartialEq)] /// The strategy we use to recover the PoV. pub enum RecoveryStrategyKind { - /// We always try the backing group first, then fallback to validator chunks. - BackersFirstAlways, /// We try the backing group first if PoV size is lower than specified, then fallback to /// validator chunks. BackersFirstIfSizeLower(usize), + /// We try the backing group first if PoV size is lower than specified, then fallback to + /// systematic chunks. Regular chunk recovery as a last resort. + BackersFirstIfSizeLowerThenSystematicChunks(usize), + + /// The following variants are only helpful for integration tests. + /// + /// We always try the backing group first, then fallback to validator chunks. + #[allow(dead_code)] + BackersFirstAlways, /// We always recover using validator chunks. + #[allow(dead_code)] ChunksAlways, + /// First try the backing group. Then systematic chunks. + #[allow(dead_code)] + BackersThenSystematicChunks, + /// Always recover using systematic chunks, fall back to regular chunks. + #[allow(dead_code)] + SystematicChunks, } /// The Availability Recovery Subsystem. @@ -107,11 +135,15 @@ pub struct AvailabilityRecoverySubsystem { metrics: Metrics, /// The type of check to perform after available data was recovered. post_recovery_check: PostRecoveryCheck, + /// Full protocol name for ChunkFetchingV1. + req_v1_protocol_name: ProtocolName, + /// Full protocol name for ChunkFetchingV2. + req_v2_protocol_name: ProtocolName, } #[derive(Clone, PartialEq, Debug)] /// The type of check to perform after available data was recovered. -pub enum PostRecoveryCheck { +enum PostRecoveryCheck { /// Reencode the data and check erasure root. For validators. Reencode, /// Only check the pov hash. For collators only. @@ -119,56 +151,18 @@ pub enum PostRecoveryCheck { } /// Expensive erasure coding computations that we want to run on a blocking thread. -pub enum ErasureTask { +enum ErasureTask { /// Reconstructs `AvailableData` from chunks given `n_validators`. Reconstruct( usize, - HashMap, - oneshot::Sender>, + BTreeMap>, + oneshot::Sender>, ), /// Re-encode `AvailableData` into erasure chunks in order to verify the provided root hash of /// the Merkle tree. Reencode(usize, Hash, AvailableData, oneshot::Sender>), } -const fn is_unavailable( - received_chunks: usize, - requesting_chunks: usize, - unrequested_validators: usize, - threshold: usize, -) -> bool { - received_chunks + requesting_chunks + unrequested_validators < threshold -} - -/// Check validity of a chunk. -fn is_chunk_valid(params: &RecoveryParams, chunk: &ErasureChunk) -> bool { - let anticipated_hash = - match branch_hash(¶ms.erasure_root, chunk.proof(), chunk.index.0 as usize) { - Ok(hash) => hash, - Err(e) => { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - validator_index = ?chunk.index, - error = ?e, - "Invalid Merkle proof", - ); - return false - }, - }; - let erasure_chunk_hash = BlakeTwo256::hash(&chunk.chunk); - if anticipated_hash != erasure_chunk_hash { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - validator_index = ?chunk.index, - "Merkle proof mismatch" - ); - return false - } - true -} - /// Re-encode the data into erasure chunks in order to verify /// the root hash of the provided Merkle tree, which is built /// on-top of the encoded chunks. @@ -212,12 +206,12 @@ fn reconstructed_data_matches_root( /// Accumulate all awaiting sides for some particular `AvailableData`. struct RecoveryHandle { candidate_hash: CandidateHash, - remote: RemoteHandle>, - awaiting: Vec>>, + remote: RemoteHandle, + awaiting: Vec>, } impl Future for RecoveryHandle { - type Output = Option<(CandidateHash, Result)>; + type Output = Option<(CandidateHash, RecoveryResult)>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut indices_to_remove = Vec::new(); @@ -271,7 +265,7 @@ enum CachedRecovery { impl CachedRecovery { /// Convert back to `Result` to deliver responses. - fn into_result(self) -> Result { + fn into_result(self) -> RecoveryResult { match self { Self::Valid(d) => Ok(d), Self::Invalid => Err(RecoveryError::Invalid), @@ -279,9 +273,9 @@ impl CachedRecovery { } } -impl TryFrom> for CachedRecovery { +impl TryFrom for CachedRecovery { type Error = (); - fn try_from(o: Result) -> Result { + fn try_from(o: RecoveryResult) -> std::result::Result { match o { Ok(d) => Ok(Self::Valid(d)), Err(RecoveryError::Invalid) => Ok(Self::Invalid), @@ -303,6 +297,9 @@ struct State { /// An LRU cache of recently recovered data. availability_lru: LruMap, + + /// Cached runtime info. + runtime_info: RuntimeInfo, } impl Default for State { @@ -311,6 +308,7 @@ impl Default for State { ongoing_recoveries: FuturesUnordered::new(), live_block: (0, Hash::default()), availability_lru: LruMap::new(ByLength::new(LRU_SIZE)), + runtime_info: RuntimeInfo::new(None), } } } @@ -327,9 +325,10 @@ impl AvailabilityRecoverySubsystem { } /// Handles a signal from the overseer. -async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemResult { +/// Returns true if subsystem receives a deadly signal. +async fn handle_signal(state: &mut State, signal: OverseerSignal) -> bool { match signal { - OverseerSignal::Conclude => Ok(true), + OverseerSignal::Conclude => true, OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { activated, .. }) => { // if activated is non-empty, set state.live_block to the highest block in `activated` if let Some(activated) = activated { @@ -338,9 +337,9 @@ async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemRe } } - Ok(false) + false }, - OverseerSignal::BlockFinalized(_, _) => Ok(false), + OverseerSignal::BlockFinalized(_, _) => false, } } @@ -349,27 +348,11 @@ async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemRe async fn launch_recovery_task( state: &mut State, ctx: &mut Context, - session_info: SessionInfo, - receipt: CandidateReceipt, - response_sender: oneshot::Sender>, - metrics: &Metrics, + response_sender: oneshot::Sender, recovery_strategies: VecDeque::Sender>>>, - bypass_availability_store: bool, - post_recovery_check: PostRecoveryCheck, -) -> error::Result<()> { - let candidate_hash = receipt.hash(); - let params = RecoveryParams { - validator_authority_keys: session_info.discovery_keys.clone(), - n_validators: session_info.validators.len(), - threshold: recovery_threshold(session_info.validators.len())?, - candidate_hash, - erasure_root: receipt.descriptor.erasure_root, - metrics: metrics.clone(), - bypass_availability_store, - post_recovery_check, - pov_hash: receipt.descriptor.pov_hash, - }; - + params: RecoveryParams, +) -> Result<()> { + let candidate_hash = params.candidate_hash; let recovery_task = RecoveryTask::new(ctx.sender().clone(), params, recovery_strategies); let (remote, remote_handle) = recovery_task.run().remote_handle(); @@ -380,15 +363,8 @@ async fn launch_recovery_task( awaiting: vec![response_sender], }); - if let Err(e) = ctx.spawn("recovery-task", Box::pin(remote)) { - gum::warn!( - target: LOG_TARGET, - err = ?e, - "Failed to spawn a recovery task", - ); - } - - Ok(()) + ctx.spawn("recovery-task", Box::pin(remote)) + .map_err(|err| Error::SpawnTask(err)) } /// Handles an availability recovery request. @@ -399,13 +375,16 @@ async fn handle_recover( receipt: CandidateReceipt, session_index: SessionIndex, backing_group: Option, - response_sender: oneshot::Sender>, + response_sender: oneshot::Sender, metrics: &Metrics, erasure_task_tx: futures::channel::mpsc::Sender, recovery_strategy_kind: RecoveryStrategyKind, bypass_availability_store: bool, post_recovery_check: PostRecoveryCheck, -) -> error::Result<()> { + maybe_core_index: Option, + req_v1_protocol_name: ProtocolName, + req_v2_protocol_name: ProtocolName, +) -> Result<()> { let candidate_hash = receipt.hash(); let span = jaeger::Span::new(candidate_hash, "availability-recovery") @@ -414,14 +393,7 @@ async fn handle_recover( if let Some(result) = state.availability_lru.get(&candidate_hash).cloned().map(|v| v.into_result()) { - if let Err(e) = response_sender.send(result) { - gum::warn!( - target: LOG_TARGET, - err = ?e, - "Error responding with an availability recovery result", - ); - } - return Ok(()) + return response_sender.send(result).map_err(|_| Error::CanceledResponseSender) } if let Some(i) = @@ -432,100 +404,182 @@ async fn handle_recover( } let _span = span.child("not-cached"); - let session_info = request_session_info(state.live_block.1, session_index, ctx.sender()) - .await - .await - .map_err(error::Error::CanceledSessionInfo)??; + let session_info_res = state + .runtime_info + .get_session_info_by_index(ctx.sender(), state.live_block.1, session_index) + .await; let _span = span.child("session-info-ctx-received"); - match session_info { - Some(session_info) => { + match session_info_res { + Ok(ExtendedSessionInfo { session_info, node_features, .. }) => { + let mut backer_group = None; + let n_validators = session_info.validators.len(); + let systematic_threshold = systematic_recovery_threshold(n_validators)?; let mut recovery_strategies: VecDeque< Box::Sender>>, - > = VecDeque::with_capacity(2); + > = VecDeque::with_capacity(3); if let Some(backing_group) = backing_group { if let Some(backing_validators) = session_info.validator_groups.get(backing_group) { let mut small_pov_size = true; - if let RecoveryStrategyKind::BackersFirstIfSizeLower(small_pov_limit) = - recovery_strategy_kind - { - // Get our own chunk size to get an estimate of the PoV size. - let chunk_size: Result, error::Error> = - query_chunk_size(ctx, candidate_hash).await; - if let Ok(Some(chunk_size)) = chunk_size { - let pov_size_estimate = - chunk_size.saturating_mul(session_info.validators.len()) / 3; - small_pov_size = pov_size_estimate < small_pov_limit; - - gum::trace!( - target: LOG_TARGET, - ?candidate_hash, - pov_size_estimate, - small_pov_limit, - enabled = small_pov_size, - "Prefer fetch from backing group", - ); - } else { - // we have a POV limit but were not able to query the chunk size, so - // don't use the backing group. - small_pov_size = false; - } + match recovery_strategy_kind { + RecoveryStrategyKind::BackersFirstIfSizeLower(fetch_chunks_threshold) | + RecoveryStrategyKind::BackersFirstIfSizeLowerThenSystematicChunks( + fetch_chunks_threshold, + ) => { + // Get our own chunk size to get an estimate of the PoV size. + let chunk_size: Result> = + query_chunk_size(ctx, candidate_hash).await; + if let Ok(Some(chunk_size)) = chunk_size { + let pov_size_estimate = chunk_size * systematic_threshold; + small_pov_size = pov_size_estimate < fetch_chunks_threshold; + + if small_pov_size { + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + pov_size_estimate, + fetch_chunks_threshold, + "Prefer fetch from backing group", + ); + } + } else { + // we have a POV limit but were not able to query the chunk size, so + // don't use the backing group. + small_pov_size = false; + } + }, + _ => {}, }; match (&recovery_strategy_kind, small_pov_size) { (RecoveryStrategyKind::BackersFirstAlways, _) | - (RecoveryStrategyKind::BackersFirstIfSizeLower(_), true) => recovery_strategies.push_back( - Box::new(FetchFull::new(FetchFullParams { - validators: backing_validators.to_vec(), - erasure_task_tx: erasure_task_tx.clone(), - })), - ), + (RecoveryStrategyKind::BackersFirstIfSizeLower(_), true) | + ( + RecoveryStrategyKind::BackersFirstIfSizeLowerThenSystematicChunks(_), + true, + ) | + (RecoveryStrategyKind::BackersThenSystematicChunks, _) => + recovery_strategies.push_back(Box::new(FetchFull::new( + FetchFullParams { validators: backing_validators.to_vec() }, + ))), _ => {}, }; + + backer_group = Some(backing_validators); + } + } + + let chunk_mapping_enabled = if let Some(&true) = node_features + .get(usize::from(node_features::FeatureIndex::AvailabilityChunkMapping as u8)) + .as_deref() + { + true + } else { + false + }; + + // We can only attempt systematic recovery if we received the core index of the + // candidate and chunk mapping is enabled. + if let Some(core_index) = maybe_core_index { + if matches!( + recovery_strategy_kind, + RecoveryStrategyKind::BackersThenSystematicChunks | + RecoveryStrategyKind::SystematicChunks | + RecoveryStrategyKind::BackersFirstIfSizeLowerThenSystematicChunks(_) + ) && chunk_mapping_enabled + { + let chunk_indices = + availability_chunk_indices(Some(node_features), n_validators, core_index)?; + + let chunk_indices: VecDeque<_> = chunk_indices + .iter() + .enumerate() + .map(|(v_index, c_index)| { + ( + *c_index, + ValidatorIndex( + u32::try_from(v_index) + .expect("validator count should not exceed u32"), + ), + ) + }) + .collect(); + + // Only get the validators according to the threshold. + let validators = chunk_indices + .clone() + .into_iter() + .filter(|(c_index, _)| { + usize::try_from(c_index.0) + .expect("usize is at least u32 bytes on all modern targets.") < + systematic_threshold + }) + .collect(); + + recovery_strategies.push_back(Box::new(FetchSystematicChunks::new( + FetchSystematicChunksParams { + validators, + backers: backer_group.map(|v| v.to_vec()).unwrap_or_else(|| vec![]), + }, + ))); } } recovery_strategies.push_back(Box::new(FetchChunks::new(FetchChunksParams { n_validators: session_info.validators.len(), - erasure_task_tx, }))); + let session_info = session_info.clone(); + + let n_validators = session_info.validators.len(); + launch_recovery_task( state, ctx, - session_info, - receipt, response_sender, - metrics, recovery_strategies, - bypass_availability_store, - post_recovery_check, + RecoveryParams { + validator_authority_keys: session_info.discovery_keys.clone(), + n_validators, + threshold: recovery_threshold(n_validators)?, + systematic_threshold, + candidate_hash, + erasure_root: receipt.descriptor.erasure_root, + metrics: metrics.clone(), + bypass_availability_store, + post_recovery_check, + pov_hash: receipt.descriptor.pov_hash, + req_v1_protocol_name, + req_v2_protocol_name, + chunk_mapping_enabled, + erasure_task_tx, + }, ) .await }, - None => { - gum::warn!(target: LOG_TARGET, "SessionInfo is `None` at {:?}", state.live_block); + Err(_) => { response_sender .send(Err(RecoveryError::Unavailable)) - .map_err(|_| error::Error::CanceledResponseSender)?; - Ok(()) + .map_err(|_| Error::CanceledResponseSender)?; + + Err(Error::SessionInfoUnavailable(state.live_block.1)) }, } } -/// Queries a chunk from av-store. +/// Queries the full `AvailableData` from av-store. #[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)] async fn query_full_data( ctx: &mut Context, candidate_hash: CandidateHash, -) -> error::Result> { +) -> Result> { let (tx, rx) = oneshot::channel(); ctx.send_message(AvailabilityStoreMessage::QueryAvailableData(candidate_hash, tx)) .await; - rx.await.map_err(error::Error::CanceledQueryFullData) + rx.await.map_err(Error::CanceledQueryFullData) } /// Queries a chunk from av-store. @@ -533,12 +587,12 @@ async fn query_full_data( async fn query_chunk_size( ctx: &mut Context, candidate_hash: CandidateHash, -) -> error::Result> { +) -> Result> { let (tx, rx) = oneshot::channel(); ctx.send_message(AvailabilityStoreMessage::QueryChunkSize(candidate_hash, tx)) .await; - rx.await.map_err(error::Error::CanceledQueryFullData) + rx.await.map_err(Error::CanceledQueryFullData) } #[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)] @@ -547,64 +601,80 @@ impl AvailabilityRecoverySubsystem { /// which never requests the `AvailabilityStoreSubsystem` subsystem and only checks the POV hash /// instead of reencoding the available data. pub fn for_collator( + fetch_chunks_threshold: Option, req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, metrics: Metrics, ) -> Self { Self { - recovery_strategy_kind: RecoveryStrategyKind::BackersFirstIfSizeLower(SMALL_POV_LIMIT), + recovery_strategy_kind: RecoveryStrategyKind::BackersFirstIfSizeLower( + fetch_chunks_threshold.unwrap_or(CONSERVATIVE_FETCH_CHUNKS_THRESHOLD), + ), bypass_availability_store: true, post_recovery_check: PostRecoveryCheck::PovHash, req_receiver, metrics, + req_v1_protocol_name: req_protocol_names + .get_name(request_v1::ChunkFetchingRequest::PROTOCOL), + req_v2_protocol_name: req_protocol_names + .get_name(request_v2::ChunkFetchingRequest::PROTOCOL), } } - /// Create a new instance of `AvailabilityRecoverySubsystem` which starts with a fast path to - /// request data from backers. - pub fn with_fast_path( + /// Create an optimised new instance of `AvailabilityRecoverySubsystem` suitable for validator + /// nodes, which: + /// - for small POVs (over the `fetch_chunks_threshold` or the + /// `CONSERVATIVE_FETCH_CHUNKS_THRESHOLD`), it attempts full recovery from backers, if backing + /// group supplied. + /// - for large POVs, attempts systematic recovery, if core_index supplied and + /// AvailabilityChunkMapping node feature is enabled. + /// - as a last resort, attempt regular chunk recovery from all validators. + pub fn for_validator( + fetch_chunks_threshold: Option, req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, metrics: Metrics, ) -> Self { Self { - recovery_strategy_kind: RecoveryStrategyKind::BackersFirstAlways, + recovery_strategy_kind: + RecoveryStrategyKind::BackersFirstIfSizeLowerThenSystematicChunks( + fetch_chunks_threshold.unwrap_or(CONSERVATIVE_FETCH_CHUNKS_THRESHOLD), + ), bypass_availability_store: false, post_recovery_check: PostRecoveryCheck::Reencode, req_receiver, metrics, + req_v1_protocol_name: req_protocol_names + .get_name(request_v1::ChunkFetchingRequest::PROTOCOL), + req_v2_protocol_name: req_protocol_names + .get_name(request_v2::ChunkFetchingRequest::PROTOCOL), } } - /// Create a new instance of `AvailabilityRecoverySubsystem` which requests only chunks - pub fn with_chunks_only( + /// Customise the recovery strategy kind + /// Currently only useful for tests. + #[cfg(any(test, feature = "subsystem-benchmarks"))] + pub fn with_recovery_strategy_kind( req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, metrics: Metrics, + recovery_strategy_kind: RecoveryStrategyKind, ) -> Self { Self { - recovery_strategy_kind: RecoveryStrategyKind::ChunksAlways, - bypass_availability_store: false, - post_recovery_check: PostRecoveryCheck::Reencode, - req_receiver, - metrics, - } - } - - /// Create a new instance of `AvailabilityRecoverySubsystem` which requests chunks if PoV is - /// above a threshold. - pub fn with_chunks_if_pov_large( - req_receiver: IncomingRequestReceiver, - metrics: Metrics, - ) -> Self { - Self { - recovery_strategy_kind: RecoveryStrategyKind::BackersFirstIfSizeLower(SMALL_POV_LIMIT), + recovery_strategy_kind, bypass_availability_store: false, post_recovery_check: PostRecoveryCheck::Reencode, req_receiver, metrics, + req_v1_protocol_name: req_protocol_names + .get_name(request_v1::ChunkFetchingRequest::PROTOCOL), + req_v2_protocol_name: req_protocol_names + .get_name(request_v2::ChunkFetchingRequest::PROTOCOL), } } /// Starts the inner subsystem loop. - pub async fn run(self, mut ctx: Context) -> SubsystemResult<()> { + pub async fn run(self, mut ctx: Context) -> std::result::Result<(), FatalError> { let mut state = State::default(); let Self { mut req_receiver, @@ -612,6 +682,8 @@ impl AvailabilityRecoverySubsystem { recovery_strategy_kind, bypass_availability_store, post_recovery_check, + req_v1_protocol_name, + req_v2_protocol_name, } = self; let (erasure_task_tx, erasure_task_rx) = futures::channel::mpsc::channel(16); @@ -647,53 +719,44 @@ impl AvailabilityRecoverySubsystem { loop { let recv_req = req_receiver.recv(|| vec![COST_INVALID_REQUEST]).fuse(); pin_mut!(recv_req); - futures::select! { + let res = futures::select! { erasure_task = erasure_task_rx.next() => { match erasure_task { Some(task) => { - let send_result = to_pool + to_pool .next() .expect("Pool size is `NonZeroUsize`; qed") .send(task) .await - .map_err(|_| RecoveryError::ChannelClosed); - - if let Err(err) = send_result { - gum::warn!( - target: LOG_TARGET, - ?err, - "Failed to send erasure coding task", - ); - } + .map_err(|_| RecoveryError::ChannelClosed) }, None => { - gum::debug!( - target: LOG_TARGET, - "Erasure task channel closed", - ); - - return Err(SubsystemError::with_origin("availability-recovery", RecoveryError::ChannelClosed)) + Err(RecoveryError::ChannelClosed) } - } + }.map_err(Into::into) } - v = ctx.recv().fuse() => { - match v? { - FromOrchestra::Signal(signal) => if handle_signal( - &mut state, - signal, - ).await? { - gum::debug!(target: LOG_TARGET, "subsystem concluded"); - return Ok(()); - } - FromOrchestra::Communication { msg } => { - match msg { - AvailabilityRecoveryMessage::RecoverAvailableData( - receipt, - session_index, - maybe_backing_group, - response_sender, - ) => { - if let Err(e) = handle_recover( + signal = ctx.recv().fuse() => { + match signal { + Ok(signal) => { + match signal { + FromOrchestra::Signal(signal) => if handle_signal( + &mut state, + signal, + ).await { + gum::debug!(target: LOG_TARGET, "subsystem concluded"); + return Ok(()); + } else { + Ok(()) + }, + FromOrchestra::Communication { + msg: AvailabilityRecoveryMessage::RecoverAvailableData( + receipt, + session_index, + maybe_backing_group, + maybe_core_index, + response_sender, + ) + } => handle_recover( &mut state, &mut ctx, receipt, @@ -704,21 +767,18 @@ impl AvailabilityRecoverySubsystem { erasure_task_tx.clone(), recovery_strategy_kind.clone(), bypass_availability_store, - post_recovery_check.clone() - ).await { - gum::warn!( - target: LOG_TARGET, - err = ?e, - "Error handling a recovery request", - ); - } - } + post_recovery_check.clone(), + maybe_core_index, + req_v1_protocol_name.clone(), + req_v2_protocol_name.clone(), + ).await } - } + }, + Err(e) => Err(Error::SubsystemReceive(e)) } } in_req = recv_req => { - match in_req.into_nested().map_err(|fatal| SubsystemError::with_origin("availability-recovery", fatal))? { + match in_req { Ok(req) => { if bypass_availability_store { gum::debug!( @@ -726,40 +786,42 @@ impl AvailabilityRecoverySubsystem { "Skipping request to availability-store.", ); let _ = req.send_response(None.into()); - continue - } - match query_full_data(&mut ctx, req.payload.candidate_hash).await { - Ok(res) => { - let _ = req.send_response(res.into()); - } - Err(e) => { - gum::debug!( - target: LOG_TARGET, - err = ?e, - "Failed to query available data.", - ); - - let _ = req.send_response(None.into()); + Ok(()) + } else { + match query_full_data(&mut ctx, req.payload.candidate_hash).await { + Ok(res) => { + let _ = req.send_response(res.into()); + Ok(()) + } + Err(e) => { + let _ = req.send_response(None.into()); + Err(e) + } } } } - Err(jfyi) => { - gum::debug!( - target: LOG_TARGET, - error = ?jfyi, - "Decoding incoming request failed" - ); - continue - } + Err(e) => Err(Error::IncomingRequest(e)) } } output = state.ongoing_recoveries.select_next_some() => { + let mut res = Ok(()); if let Some((candidate_hash, result)) = output { + if let Err(ref e) = result { + res = Err(Error::Recovery(e.clone())); + } + if let Ok(recovery) = CachedRecovery::try_from(result) { state.availability_lru.insert(candidate_hash, recovery); } } + + res } + }; + + // Only bubble up fatal errors, but log all of them. + if let Err(e) = res { + log_error(Err(e))?; } } } @@ -827,7 +889,13 @@ async fn erasure_task_thread( Some(ErasureTask::Reconstruct(n_validators, chunks, sender)) => { let _ = sender.send(polkadot_erasure_coding::reconstruct_v1( n_validators, - chunks.values().map(|c| (&c.chunk[..], c.index.0 as usize)), + chunks.iter().map(|(c_index, chunk)| { + ( + &chunk[..], + usize::try_from(c_index.0) + .expect("usize is at least u32 bytes on all modern targets."), + ) + }), )); }, Some(ErasureTask::Reencode(n_validators, root, available_data, sender)) => { diff --git a/polkadot/node/network/availability-recovery/src/metrics.rs b/polkadot/node/network/availability-recovery/src/metrics.rs index 9f4cddc57e43a93089fbb08ec4a18dfd77ffea8d..4e269df55027b69fbff7604ac85d980f4fd36c6f 100644 --- a/polkadot/node/network/availability-recovery/src/metrics.rs +++ b/polkadot/node/network/availability-recovery/src/metrics.rs @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use polkadot_node_subsystem::prometheus::HistogramVec; use polkadot_node_subsystem_util::metrics::{ self, - prometheus::{self, Counter, CounterVec, Histogram, Opts, PrometheusError, Registry, U64}, + prometheus::{ + self, prometheus::HistogramTimer, Counter, CounterVec, Histogram, Opts, PrometheusError, + Registry, U64, + }, }; /// Availability Distribution metrics. @@ -28,26 +32,61 @@ struct MetricsInner { /// Number of sent chunk requests. /// /// Gets incremented on each sent chunk requests. - chunk_requests_issued: Counter, + /// + /// Split by chunk type: + /// - `regular_chunks` + /// - `systematic_chunks` + chunk_requests_issued: CounterVec, + /// Total number of bytes recovered /// /// Gets incremented on each successful recovery recovered_bytes_total: Counter, + /// A counter for finished chunk requests. /// - /// Split by result: + /// Split by the chunk type (`regular_chunks` or `systematic_chunks`) + /// + /// Also split by result: /// - `no_such_chunk` ... peer did not have the requested chunk /// - `timeout` ... request timed out. - /// - `network_error` ... Some networking issue except timeout + /// - `error` ... Some networking issue except timeout /// - `invalid` ... Chunk was received, but not valid. /// - `success` chunk_requests_finished: CounterVec, + /// A counter for successful chunk requests, split by the network protocol version. + chunk_request_protocols: CounterVec, + + /// Number of sent available data requests. + full_data_requests_issued: Counter, + + /// Counter for finished available data requests. + /// + /// Split by the result type: + /// + /// - `no_such_data` ... peer did not have the requested data + /// - `timeout` ... request timed out. + /// - `error` ... Some networking issue except timeout + /// - `invalid` ... data was received, but not valid. + /// - `success` + full_data_requests_finished: CounterVec, + /// The duration of request to response. - time_chunk_request: Histogram, + /// + /// Split by chunk type (`regular_chunks` or `systematic_chunks`). + time_chunk_request: HistogramVec, /// The duration between the pure recovery and verification. - time_erasure_recovery: Histogram, + /// + /// Split by recovery type (`regular_chunks`, `systematic_chunks` or `full_from_backers`). + time_erasure_recovery: HistogramVec, + + /// How much time it takes to reconstruct the available data from chunks. + /// + /// Split by chunk type (`regular_chunks` or `systematic_chunks`), as the algorithms are + /// different. + time_erasure_reconstruct: HistogramVec, /// How much time it takes to re-encode the data into erasure chunks in order to verify /// the root hash of the provided Merkle tree. See `reconstructed_data_matches_root`. @@ -58,6 +97,10 @@ struct MetricsInner { time_full_recovery: Histogram, /// Number of full recoveries that have been finished one way or the other. + /// + /// Split by recovery `strategy_type` (`full_from_backers, systematic_chunks, regular_chunks, + /// all`). `all` is used for failed recoveries that tried all available strategies. + /// Also split by `result` type. full_recoveries_finished: CounterVec, /// Number of full recoveries that have been started on this subsystem. @@ -73,87 +116,175 @@ impl Metrics { Metrics(None) } - /// Increment counter on fetched labels. - pub fn on_chunk_request_issued(&self) { + /// Increment counter for chunk requests. + pub fn on_chunk_request_issued(&self, chunk_type: &str) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_issued.inc() + metrics.chunk_requests_issued.with_label_values(&[chunk_type]).inc() + } + } + + /// Increment counter for full data requests. + pub fn on_full_request_issued(&self) { + if let Some(metrics) = &self.0 { + metrics.full_data_requests_issued.inc() } } /// A chunk request timed out. - pub fn on_chunk_request_timeout(&self) { + pub fn on_chunk_request_timeout(&self, chunk_type: &str) { + if let Some(metrics) = &self.0 { + metrics + .chunk_requests_finished + .with_label_values(&[chunk_type, "timeout"]) + .inc() + } + } + + /// A full data request timed out. + pub fn on_full_request_timeout(&self) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_finished.with_label_values(&["timeout"]).inc() + metrics.full_data_requests_finished.with_label_values(&["timeout"]).inc() } } /// A chunk request failed because validator did not have its chunk. - pub fn on_chunk_request_no_such_chunk(&self) { + pub fn on_chunk_request_no_such_chunk(&self, chunk_type: &str) { + if let Some(metrics) = &self.0 { + metrics + .chunk_requests_finished + .with_label_values(&[chunk_type, "no_such_chunk"]) + .inc() + } + } + + /// A full data request failed because the validator did not have it. + pub fn on_full_request_no_such_data(&self) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_finished.with_label_values(&["no_such_chunk"]).inc() + metrics.full_data_requests_finished.with_label_values(&["no_such_data"]).inc() } } /// A chunk request failed for some non timeout related network error. - pub fn on_chunk_request_error(&self) { + pub fn on_chunk_request_error(&self, chunk_type: &str) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_finished.with_label_values(&["error"]).inc() + metrics.chunk_requests_finished.with_label_values(&[chunk_type, "error"]).inc() + } + } + + /// A full data request failed for some non timeout related network error. + pub fn on_full_request_error(&self) { + if let Some(metrics) = &self.0 { + metrics.full_data_requests_finished.with_label_values(&["error"]).inc() } } /// A chunk request succeeded, but was not valid. - pub fn on_chunk_request_invalid(&self) { + pub fn on_chunk_request_invalid(&self, chunk_type: &str) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_finished.with_label_values(&["invalid"]).inc() + metrics + .chunk_requests_finished + .with_label_values(&[chunk_type, "invalid"]) + .inc() + } + } + + /// A full data request succeeded, but was not valid. + pub fn on_full_request_invalid(&self) { + if let Some(metrics) = &self.0 { + metrics.full_data_requests_finished.with_label_values(&["invalid"]).inc() } } /// A chunk request succeeded. - pub fn on_chunk_request_succeeded(&self) { + pub fn on_chunk_request_succeeded(&self, chunk_type: &str) { if let Some(metrics) = &self.0 { - metrics.chunk_requests_finished.with_label_values(&["success"]).inc() + metrics + .chunk_requests_finished + .with_label_values(&[chunk_type, "success"]) + .inc() + } + } + + /// A chunk response was received on the v1 protocol. + pub fn on_chunk_response_v1(&self) { + if let Some(metrics) = &self.0 { + metrics.chunk_request_protocols.with_label_values(&["v1"]).inc() + } + } + + /// A chunk response was received on the v2 protocol. + pub fn on_chunk_response_v2(&self) { + if let Some(metrics) = &self.0 { + metrics.chunk_request_protocols.with_label_values(&["v2"]).inc() + } + } + + /// A full data request succeeded. + pub fn on_full_request_succeeded(&self) { + if let Some(metrics) = &self.0 { + metrics.full_data_requests_finished.with_label_values(&["success"]).inc() } } /// Get a timer to time request/response duration. - pub fn time_chunk_request(&self) -> Option { - self.0.as_ref().map(|metrics| metrics.time_chunk_request.start_timer()) + pub fn time_chunk_request(&self, chunk_type: &str) -> Option { + self.0.as_ref().map(|metrics| { + metrics.time_chunk_request.with_label_values(&[chunk_type]).start_timer() + }) } /// Get a timer to time erasure code recover. - pub fn time_erasure_recovery(&self) -> Option { - self.0.as_ref().map(|metrics| metrics.time_erasure_recovery.start_timer()) + pub fn time_erasure_recovery(&self, chunk_type: &str) -> Option { + self.0.as_ref().map(|metrics| { + metrics.time_erasure_recovery.with_label_values(&[chunk_type]).start_timer() + }) + } + + /// Get a timer for available data reconstruction. + pub fn time_erasure_reconstruct(&self, chunk_type: &str) -> Option { + self.0.as_ref().map(|metrics| { + metrics.time_erasure_reconstruct.with_label_values(&[chunk_type]).start_timer() + }) } /// Get a timer to time chunk encoding. - pub fn time_reencode_chunks(&self) -> Option { + pub fn time_reencode_chunks(&self) -> Option { self.0.as_ref().map(|metrics| metrics.time_reencode_chunks.start_timer()) } /// Get a timer to measure the time of the complete recovery process. - pub fn time_full_recovery(&self) -> Option { + pub fn time_full_recovery(&self) -> Option { self.0.as_ref().map(|metrics| metrics.time_full_recovery.start_timer()) } /// A full recovery succeeded. - pub fn on_recovery_succeeded(&self, bytes: usize) { + pub fn on_recovery_succeeded(&self, strategy_type: &str, bytes: usize) { if let Some(metrics) = &self.0 { - metrics.full_recoveries_finished.with_label_values(&["success"]).inc(); + metrics + .full_recoveries_finished + .with_label_values(&["success", strategy_type]) + .inc(); metrics.recovered_bytes_total.inc_by(bytes as u64) } } /// A full recovery failed (data not available). - pub fn on_recovery_failed(&self) { + pub fn on_recovery_failed(&self, strategy_type: &str) { if let Some(metrics) = &self.0 { - metrics.full_recoveries_finished.with_label_values(&["failure"]).inc() + metrics + .full_recoveries_finished + .with_label_values(&["failure", strategy_type]) + .inc() } } /// A full recovery failed (data was recovered, but invalid). - pub fn on_recovery_invalid(&self) { + pub fn on_recovery_invalid(&self, strategy_type: &str) { if let Some(metrics) = &self.0 { - metrics.full_recoveries_finished.with_label_values(&["invalid"]).inc() + metrics + .full_recoveries_finished + .with_label_values(&["invalid", strategy_type]) + .inc() } } @@ -169,9 +300,17 @@ impl metrics::Metrics for Metrics { fn try_register(registry: &Registry) -> Result { let metrics = MetricsInner { chunk_requests_issued: prometheus::register( + CounterVec::new( + Opts::new("polkadot_parachain_availability_recovery_chunk_requests_issued", + "Total number of issued chunk requests."), + &["type"] + )?, + registry, + )?, + full_data_requests_issued: prometheus::register( Counter::new( - "polkadot_parachain_availability_recovery_chunk_requests_issued", - "Total number of issued chunk requests.", + "polkadot_parachain_availability_recovery_full_data_requests_issued", + "Total number of issued full data requests.", )?, registry, )?, @@ -188,22 +327,49 @@ impl metrics::Metrics for Metrics { "polkadot_parachain_availability_recovery_chunk_requests_finished", "Total number of chunk requests finished.", ), + &["result", "type"], + )?, + registry, + )?, + chunk_request_protocols: prometheus::register( + CounterVec::new( + Opts::new( + "polkadot_parachain_availability_recovery_chunk_request_protocols", + "Total number of successful chunk requests, mapped by the protocol version (v1 or v2).", + ), + &["protocol"], + )?, + registry, + )?, + full_data_requests_finished: prometheus::register( + CounterVec::new( + Opts::new( + "polkadot_parachain_availability_recovery_full_data_requests_finished", + "Total number of full data requests finished.", + ), &["result"], )?, registry, )?, time_chunk_request: prometheus::register( - prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( + prometheus::HistogramVec::new(prometheus::HistogramOpts::new( "polkadot_parachain_availability_recovery_time_chunk_request", "Time spent waiting for a response to a chunk request", - ))?, + ), &["type"])?, registry, )?, time_erasure_recovery: prometheus::register( - prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( + prometheus::HistogramVec::new(prometheus::HistogramOpts::new( "polkadot_parachain_availability_recovery_time_erasure_recovery", "Time spent to recover the erasure code and verify the merkle root by re-encoding as erasure chunks", - ))?, + ), &["type"])?, + registry, + )?, + time_erasure_reconstruct: prometheus::register( + prometheus::HistogramVec::new(prometheus::HistogramOpts::new( + "polkadot_parachain_availability_recovery_time_erasure_reconstruct", + "Time spent to reconstruct the data from chunks", + ), &["type"])?, registry, )?, time_reencode_chunks: prometheus::register( @@ -226,7 +392,7 @@ impl metrics::Metrics for Metrics { "polkadot_parachain_availability_recovery_recoveries_finished", "Total number of recoveries that finished.", ), - &["result"], + &["result", "strategy_type"], )?, registry, )?, diff --git a/polkadot/node/network/availability-recovery/src/task.rs b/polkadot/node/network/availability-recovery/src/task.rs deleted file mode 100644 index c300c221da5c6da8f40e8a6db3dede59ba207a58..0000000000000000000000000000000000000000 --- a/polkadot/node/network/availability-recovery/src/task.rs +++ /dev/null @@ -1,861 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Recovery task and associated strategies. - -#![warn(missing_docs)] - -use crate::{ - futures_undead::FuturesUndead, is_chunk_valid, is_unavailable, metrics::Metrics, ErasureTask, - PostRecoveryCheck, LOG_TARGET, -}; -use futures::{channel::oneshot, SinkExt}; -use parity_scale_codec::Encode; -#[cfg(not(test))] -use polkadot_node_network_protocol::request_response::CHUNK_REQUEST_TIMEOUT; -use polkadot_node_network_protocol::request_response::{ - self as req_res, outgoing::RequestError, OutgoingRequest, Recipient, Requests, -}; -use polkadot_node_primitives::{AvailableData, ErasureChunk}; -use polkadot_node_subsystem::{ - messages::{AvailabilityStoreMessage, NetworkBridgeTxMessage}, - overseer, RecoveryError, -}; -use polkadot_primitives::{AuthorityDiscoveryId, CandidateHash, Hash, ValidatorIndex}; -use rand::seq::SliceRandom; -use sc_network::{IfDisconnected, OutboundFailure, RequestFailure}; -use std::{ - collections::{HashMap, VecDeque}, - time::Duration, -}; - -// How many parallel recovery tasks should be running at once. -const N_PARALLEL: usize = 50; - -/// Time after which we consider a request to have failed -/// -/// and we should try more peers. Note in theory the request times out at the network level, -/// measurements have shown, that in practice requests might actually take longer to fail in -/// certain occasions. (The very least, authority discovery is not part of the timeout.) -/// -/// For the time being this value is the same as the timeout on the networking layer, but as this -/// timeout is more soft than the networking one, it might make sense to pick different values as -/// well. -#[cfg(not(test))] -const TIMEOUT_START_NEW_REQUESTS: Duration = CHUNK_REQUEST_TIMEOUT; -#[cfg(test)] -const TIMEOUT_START_NEW_REQUESTS: Duration = Duration::from_millis(100); - -#[async_trait::async_trait] -/// Common trait for runnable recovery strategies. -pub trait RecoveryStrategy: Send { - /// Main entry point of the strategy. - async fn run( - &mut self, - state: &mut State, - sender: &mut Sender, - common_params: &RecoveryParams, - ) -> Result; - - /// Return the name of the strategy for logging purposes. - fn display_name(&self) -> &'static str; -} - -/// Recovery parameters common to all strategies in a `RecoveryTask`. -pub struct RecoveryParams { - /// Discovery ids of `validators`. - pub validator_authority_keys: Vec, - - /// Number of validators. - pub n_validators: usize, - - /// The number of chunks needed. - pub threshold: usize, - - /// A hash of the relevant candidate. - pub candidate_hash: CandidateHash, - - /// The root of the erasure encoding of the candidate. - pub erasure_root: Hash, - - /// Metrics to report. - pub metrics: Metrics, - - /// Do not request data from availability-store. Useful for collators. - pub bypass_availability_store: bool, - - /// The type of check to perform after available data was recovered. - pub post_recovery_check: PostRecoveryCheck, - - /// The blake2-256 hash of the PoV. - pub pov_hash: Hash, -} - -/// Intermediate/common data that must be passed between `RecoveryStrategy`s belonging to the -/// same `RecoveryTask`. -pub struct State { - /// Chunks received so far. - received_chunks: HashMap, -} - -impl State { - fn new() -> Self { - Self { received_chunks: HashMap::new() } - } - - fn insert_chunk(&mut self, validator: ValidatorIndex, chunk: ErasureChunk) { - self.received_chunks.insert(validator, chunk); - } - - fn chunk_count(&self) -> usize { - self.received_chunks.len() - } - - /// Retrieve the local chunks held in the av-store (either 0 or 1). - async fn populate_from_av_store( - &mut self, - params: &RecoveryParams, - sender: &mut Sender, - ) -> Vec { - let (tx, rx) = oneshot::channel(); - sender - .send_message(AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx)) - .await; - - match rx.await { - Ok(chunks) => { - // This should either be length 1 or 0. If we had the whole data, - // we wouldn't have reached this stage. - let chunk_indices: Vec<_> = chunks.iter().map(|c| c.index).collect(); - - for chunk in chunks { - if is_chunk_valid(params, &chunk) { - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - validator_index = ?chunk.index, - "Found valid chunk on disk" - ); - self.insert_chunk(chunk.index, chunk); - } else { - gum::error!( - target: LOG_TARGET, - "Loaded invalid chunk from disk! Disk/Db corruption _very_ likely - please fix ASAP!" - ); - }; - } - - chunk_indices - }, - Err(oneshot::Canceled) => { - gum::warn!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - "Failed to reach the availability store" - ); - - vec![] - }, - } - } - - /// Launch chunk requests in parallel, according to the parameters. - async fn launch_parallel_chunk_requests( - &mut self, - params: &RecoveryParams, - sender: &mut Sender, - desired_requests_count: usize, - validators: &mut VecDeque, - requesting_chunks: &mut FuturesUndead< - Result, (ValidatorIndex, RequestError)>, - >, - ) where - Sender: overseer::AvailabilityRecoverySenderTrait, - { - let candidate_hash = ¶ms.candidate_hash; - let already_requesting_count = requesting_chunks.len(); - - let mut requests = Vec::with_capacity(desired_requests_count - already_requesting_count); - - while requesting_chunks.len() < desired_requests_count { - if let Some(validator_index) = validators.pop_back() { - let validator = params.validator_authority_keys[validator_index.0 as usize].clone(); - gum::trace!( - target: LOG_TARGET, - ?validator, - ?validator_index, - ?candidate_hash, - "Requesting chunk", - ); - - // Request data. - let raw_request = req_res::v1::ChunkFetchingRequest { - candidate_hash: params.candidate_hash, - index: validator_index, - }; - - let (req, res) = OutgoingRequest::new(Recipient::Authority(validator), raw_request); - requests.push(Requests::ChunkFetchingV1(req)); - - params.metrics.on_chunk_request_issued(); - let timer = params.metrics.time_chunk_request(); - - requesting_chunks.push(Box::pin(async move { - let _timer = timer; - match res.await { - Ok(req_res::v1::ChunkFetchingResponse::Chunk(chunk)) => - Ok(Some(chunk.recombine_into_chunk(&raw_request))), - Ok(req_res::v1::ChunkFetchingResponse::NoSuchChunk) => Ok(None), - Err(e) => Err((validator_index, e)), - } - })); - } else { - break - } - } - - sender - .send_message(NetworkBridgeTxMessage::SendRequests( - requests, - IfDisconnected::TryConnect, - )) - .await; - } - - /// Wait for a sufficient amount of chunks to reconstruct according to the provided `params`. - async fn wait_for_chunks( - &mut self, - params: &RecoveryParams, - validators: &mut VecDeque, - requesting_chunks: &mut FuturesUndead< - Result, (ValidatorIndex, RequestError)>, - >, - can_conclude: impl Fn(usize, usize, usize, &RecoveryParams, usize) -> bool, - ) -> (usize, usize) { - let metrics = ¶ms.metrics; - - let mut total_received_responses = 0; - let mut error_count = 0; - - // Wait for all current requests to conclude or time-out, or until we reach enough chunks. - // We also declare requests undead, once `TIMEOUT_START_NEW_REQUESTS` is reached and will - // return in that case for `launch_parallel_requests` to fill up slots again. - while let Some(request_result) = - requesting_chunks.next_with_timeout(TIMEOUT_START_NEW_REQUESTS).await - { - total_received_responses += 1; - - match request_result { - Ok(Some(chunk)) => - if is_chunk_valid(params, &chunk) { - metrics.on_chunk_request_succeeded(); - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - validator_index = ?chunk.index, - "Received valid chunk", - ); - self.insert_chunk(chunk.index, chunk); - } else { - metrics.on_chunk_request_invalid(); - error_count += 1; - }, - Ok(None) => { - metrics.on_chunk_request_no_such_chunk(); - error_count += 1; - }, - Err((validator_index, e)) => { - error_count += 1; - - gum::trace!( - target: LOG_TARGET, - candidate_hash= ?params.candidate_hash, - err = ?e, - ?validator_index, - "Failure requesting chunk", - ); - - match e { - RequestError::InvalidResponse(_) => { - metrics.on_chunk_request_invalid(); - - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - err = ?e, - ?validator_index, - "Chunk fetching response was invalid", - ); - }, - RequestError::NetworkError(err) => { - // No debug logs on general network errors - that became very spammy - // occasionally. - if let RequestFailure::Network(OutboundFailure::Timeout) = err { - metrics.on_chunk_request_timeout(); - } else { - metrics.on_chunk_request_error(); - } - - validators.push_front(validator_index); - }, - RequestError::Canceled(_) => { - metrics.on_chunk_request_error(); - - validators.push_front(validator_index); - }, - } - }, - } - - // Stop waiting for requests when we either can already recover the data - // or have gotten firm 'No' responses from enough validators. - if can_conclude( - validators.len(), - requesting_chunks.total_len(), - self.chunk_count(), - params, - error_count, - ) { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?params.candidate_hash, - received_chunks_count = ?self.chunk_count(), - requested_chunks_count = ?requesting_chunks.len(), - threshold = ?params.threshold, - "Can conclude availability for a candidate", - ); - break - } - } - - (total_received_responses, error_count) - } -} - -/// A stateful reconstruction of availability data in reference to -/// a candidate hash. -pub struct RecoveryTask { - sender: Sender, - params: RecoveryParams, - strategies: VecDeque>>, - state: State, -} - -impl RecoveryTask -where - Sender: overseer::AvailabilityRecoverySenderTrait, -{ - /// Instantiate a new recovery task. - pub fn new( - sender: Sender, - params: RecoveryParams, - strategies: VecDeque>>, - ) -> Self { - Self { sender, params, strategies, state: State::new() } - } - - async fn in_availability_store(&mut self) -> Option { - if !self.params.bypass_availability_store { - let (tx, rx) = oneshot::channel(); - self.sender - .send_message(AvailabilityStoreMessage::QueryAvailableData( - self.params.candidate_hash, - tx, - )) - .await; - - match rx.await { - Ok(Some(data)) => return Some(data), - Ok(None) => {}, - Err(oneshot::Canceled) => { - gum::warn!( - target: LOG_TARGET, - candidate_hash = ?self.params.candidate_hash, - "Failed to reach the availability store", - ) - }, - } - } - - None - } - - /// Run this recovery task to completion. It will loop through the configured strategies - /// in-order and return whenever the first one recovers the full `AvailableData`. - pub async fn run(mut self) -> Result { - if let Some(data) = self.in_availability_store().await { - return Ok(data) - } - - self.params.metrics.on_recovery_started(); - - let _timer = self.params.metrics.time_full_recovery(); - - while let Some(mut current_strategy) = self.strategies.pop_front() { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?self.params.candidate_hash, - "Starting `{}` strategy", - current_strategy.display_name(), - ); - - let res = current_strategy.run(&mut self.state, &mut self.sender, &self.params).await; - - match res { - Err(RecoveryError::Unavailable) => - if self.strategies.front().is_some() { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?self.params.candidate_hash, - "Recovery strategy `{}` did not conclude. Trying the next one.", - current_strategy.display_name(), - ); - continue - }, - Err(err) => { - match &err { - RecoveryError::Invalid => self.params.metrics.on_recovery_invalid(), - _ => self.params.metrics.on_recovery_failed(), - } - return Err(err) - }, - Ok(data) => { - self.params.metrics.on_recovery_succeeded(data.encoded_size()); - return Ok(data) - }, - } - } - - // We have no other strategies to try. - gum::warn!( - target: LOG_TARGET, - candidate_hash = ?self.params.candidate_hash, - "Recovery of available data failed.", - ); - self.params.metrics.on_recovery_failed(); - - Err(RecoveryError::Unavailable) - } -} - -/// `RecoveryStrategy` that sequentially tries to fetch the full `AvailableData` from -/// already-connected validators in the configured validator set. -pub struct FetchFull { - params: FetchFullParams, -} - -pub struct FetchFullParams { - /// Validators that will be used for fetching the data. - pub validators: Vec, - /// Channel to the erasure task handler. - pub erasure_task_tx: futures::channel::mpsc::Sender, -} - -impl FetchFull { - /// Create a new `FetchFull` recovery strategy. - pub fn new(mut params: FetchFullParams) -> Self { - params.validators.shuffle(&mut rand::thread_rng()); - Self { params } - } -} - -#[async_trait::async_trait] -impl RecoveryStrategy for FetchFull { - fn display_name(&self) -> &'static str { - "Full recovery from backers" - } - - async fn run( - &mut self, - _: &mut State, - sender: &mut Sender, - common_params: &RecoveryParams, - ) -> Result { - loop { - // Pop the next validator, and proceed to next fetch_chunks_task if we're out. - let validator_index = - self.params.validators.pop().ok_or_else(|| RecoveryError::Unavailable)?; - - // Request data. - let (req, response) = OutgoingRequest::new( - Recipient::Authority( - common_params.validator_authority_keys[validator_index.0 as usize].clone(), - ), - req_res::v1::AvailableDataFetchingRequest { - candidate_hash: common_params.candidate_hash, - }, - ); - - sender - .send_message(NetworkBridgeTxMessage::SendRequests( - vec![Requests::AvailableDataFetchingV1(req)], - IfDisconnected::ImmediateError, - )) - .await; - - match response.await { - Ok(req_res::v1::AvailableDataFetchingResponse::AvailableData(data)) => { - let maybe_data = match common_params.post_recovery_check { - PostRecoveryCheck::Reencode => { - let (reencode_tx, reencode_rx) = oneshot::channel(); - self.params - .erasure_task_tx - .send(ErasureTask::Reencode( - common_params.n_validators, - common_params.erasure_root, - data, - reencode_tx, - )) - .await - .map_err(|_| RecoveryError::ChannelClosed)?; - - reencode_rx.await.map_err(|_| RecoveryError::ChannelClosed)? - }, - PostRecoveryCheck::PovHash => - (data.pov.hash() == common_params.pov_hash).then_some(data), - }; - - match maybe_data { - Some(data) => { - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - "Received full data", - ); - - return Ok(data) - }, - None => { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - ?validator_index, - "Invalid data response", - ); - - // it doesn't help to report the peer with req/res. - // we'll try the next backer. - }, - }; - }, - Ok(req_res::v1::AvailableDataFetchingResponse::NoSuchData) => {}, - Err(e) => gum::debug!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - ?validator_index, - err = ?e, - "Error fetching full available data." - ), - } - } - } -} - -/// `RecoveryStrategy` that requests chunks from validators, in parallel. -pub struct FetchChunks { - /// How many requests have been unsuccessful so far. - error_count: usize, - /// Total number of responses that have been received, including failed ones. - total_received_responses: usize, - /// Collection of in-flight requests. - requesting_chunks: FuturesUndead, (ValidatorIndex, RequestError)>>, - /// A random shuffling of the validators which indicates the order in which we connect to the - /// validators and request the chunk from them. - validators: VecDeque, - /// Channel to the erasure task handler. - erasure_task_tx: futures::channel::mpsc::Sender, -} - -/// Parameters specific to the `FetchChunks` strategy. -pub struct FetchChunksParams { - /// Total number of validators. - pub n_validators: usize, - /// Channel to the erasure task handler. - pub erasure_task_tx: futures::channel::mpsc::Sender, -} - -impl FetchChunks { - /// Instantiate a new strategy. - pub fn new(params: FetchChunksParams) -> Self { - let mut shuffling: Vec<_> = (0..params.n_validators) - .map(|i| ValidatorIndex(i.try_into().expect("number of validators must fit in a u32"))) - .collect(); - shuffling.shuffle(&mut rand::thread_rng()); - - Self { - error_count: 0, - total_received_responses: 0, - requesting_chunks: FuturesUndead::new(), - validators: shuffling.into(), - erasure_task_tx: params.erasure_task_tx, - } - } - - fn is_unavailable( - unrequested_validators: usize, - in_flight_requests: usize, - chunk_count: usize, - threshold: usize, - ) -> bool { - is_unavailable(chunk_count, in_flight_requests, unrequested_validators, threshold) - } - - /// Desired number of parallel requests. - /// - /// For the given threshold (total required number of chunks) get the desired number of - /// requests we want to have running in parallel at this time. - fn get_desired_request_count(&self, chunk_count: usize, threshold: usize) -> usize { - // Upper bound for parallel requests. - // We want to limit this, so requests can be processed within the timeout and we limit the - // following feedback loop: - // 1. Requests fail due to timeout - // 2. We request more chunks to make up for it - // 3. Bandwidth is spread out even more, so we get even more timeouts - // 4. We request more chunks to make up for it ... - let max_requests_boundary = std::cmp::min(N_PARALLEL, threshold); - // How many chunks are still needed? - let remaining_chunks = threshold.saturating_sub(chunk_count); - // What is the current error rate, so we can make up for it? - let inv_error_rate = - self.total_received_responses.checked_div(self.error_count).unwrap_or(0); - // Actual number of requests we want to have in flight in parallel: - std::cmp::min( - max_requests_boundary, - remaining_chunks + remaining_chunks.checked_div(inv_error_rate).unwrap_or(0), - ) - } - - async fn attempt_recovery( - &mut self, - state: &mut State, - common_params: &RecoveryParams, - ) -> Result { - let recovery_duration = common_params.metrics.time_erasure_recovery(); - - // Send request to reconstruct available data from chunks. - let (avilable_data_tx, available_data_rx) = oneshot::channel(); - self.erasure_task_tx - .send(ErasureTask::Reconstruct( - common_params.n_validators, - // Safe to leave an empty vec in place, as we're stopping the recovery process if - // this reconstruct fails. - std::mem::take(&mut state.received_chunks), - avilable_data_tx, - )) - .await - .map_err(|_| RecoveryError::ChannelClosed)?; - - let available_data_response = - available_data_rx.await.map_err(|_| RecoveryError::ChannelClosed)?; - - match available_data_response { - Ok(data) => { - let maybe_data = match common_params.post_recovery_check { - PostRecoveryCheck::Reencode => { - // Send request to re-encode the chunks and check merkle root. - let (reencode_tx, reencode_rx) = oneshot::channel(); - self.erasure_task_tx - .send(ErasureTask::Reencode( - common_params.n_validators, - common_params.erasure_root, - data, - reencode_tx, - )) - .await - .map_err(|_| RecoveryError::ChannelClosed)?; - - reencode_rx.await.map_err(|_| RecoveryError::ChannelClosed)?.or_else(|| { - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - erasure_root = ?common_params.erasure_root, - "Data recovery error - root mismatch", - ); - None - }) - }, - PostRecoveryCheck::PovHash => - (data.pov.hash() == common_params.pov_hash).then_some(data).or_else(|| { - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - pov_hash = ?common_params.pov_hash, - "Data recovery error - PoV hash mismatch", - ); - None - }), - }; - - if let Some(data) = maybe_data { - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - erasure_root = ?common_params.erasure_root, - "Data recovery from chunks complete", - ); - - Ok(data) - } else { - recovery_duration.map(|rd| rd.stop_and_discard()); - - Err(RecoveryError::Invalid) - } - }, - Err(err) => { - recovery_duration.map(|rd| rd.stop_and_discard()); - gum::trace!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - erasure_root = ?common_params.erasure_root, - ?err, - "Data recovery error ", - ); - - Err(RecoveryError::Invalid) - }, - } - } -} - -#[async_trait::async_trait] -impl RecoveryStrategy for FetchChunks { - fn display_name(&self) -> &'static str { - "Fetch chunks" - } - - async fn run( - &mut self, - state: &mut State, - sender: &mut Sender, - common_params: &RecoveryParams, - ) -> Result { - // First query the store for any chunks we've got. - if !common_params.bypass_availability_store { - let local_chunk_indices = state.populate_from_av_store(common_params, sender).await; - self.validators.retain(|i| !local_chunk_indices.contains(i)); - } - - // No need to query the validators that have the chunks we already received. - self.validators.retain(|i| !state.received_chunks.contains_key(i)); - - loop { - // If received_chunks has more than threshold entries, attempt to recover the data. - // If that fails, or a re-encoding of it doesn't match the expected erasure root, - // return Err(RecoveryError::Invalid). - // Do this before requesting any chunks because we may have enough of them coming from - // past RecoveryStrategies. - if state.chunk_count() >= common_params.threshold { - return self.attempt_recovery(state, common_params).await - } - - if Self::is_unavailable( - self.validators.len(), - self.requesting_chunks.total_len(), - state.chunk_count(), - common_params.threshold, - ) { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?common_params.candidate_hash, - erasure_root = ?common_params.erasure_root, - received = %state.chunk_count(), - requesting = %self.requesting_chunks.len(), - total_requesting = %self.requesting_chunks.total_len(), - n_validators = %common_params.n_validators, - "Data recovery from chunks is not possible", - ); - - return Err(RecoveryError::Unavailable) - } - - let desired_requests_count = - self.get_desired_request_count(state.chunk_count(), common_params.threshold); - let already_requesting_count = self.requesting_chunks.len(); - gum::debug!( - target: LOG_TARGET, - ?common_params.candidate_hash, - ?desired_requests_count, - error_count= ?self.error_count, - total_received = ?self.total_received_responses, - threshold = ?common_params.threshold, - ?already_requesting_count, - "Requesting availability chunks for a candidate", - ); - state - .launch_parallel_chunk_requests( - common_params, - sender, - desired_requests_count, - &mut self.validators, - &mut self.requesting_chunks, - ) - .await; - - let (total_responses, error_count) = state - .wait_for_chunks( - common_params, - &mut self.validators, - &mut self.requesting_chunks, - |unrequested_validators, reqs, chunk_count, params, _error_count| { - chunk_count >= params.threshold || - Self::is_unavailable( - unrequested_validators, - reqs, - chunk_count, - params.threshold, - ) - }, - ) - .await; - - self.total_received_responses += total_responses; - self.error_count += error_count; - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use polkadot_erasure_coding::recovery_threshold; - - #[test] - fn parallel_request_calculation_works_as_expected() { - let num_validators = 100; - let threshold = recovery_threshold(num_validators).unwrap(); - let (erasure_task_tx, _erasure_task_rx) = futures::channel::mpsc::channel(16); - - let mut fetch_chunks_task = - FetchChunks::new(FetchChunksParams { n_validators: 100, erasure_task_tx }); - assert_eq!(fetch_chunks_task.get_desired_request_count(0, threshold), threshold); - fetch_chunks_task.error_count = 1; - fetch_chunks_task.total_received_responses = 1; - // We saturate at threshold (34): - assert_eq!(fetch_chunks_task.get_desired_request_count(0, threshold), threshold); - - fetch_chunks_task.total_received_responses = 2; - // With given error rate - still saturating: - assert_eq!(fetch_chunks_task.get_desired_request_count(1, threshold), threshold); - fetch_chunks_task.total_received_responses += 8; - // error rate: 1/10 - // remaining chunks needed: threshold (34) - 9 - // expected: 24 * (1+ 1/10) = (next greater integer) = 27 - assert_eq!(fetch_chunks_task.get_desired_request_count(9, threshold), 27); - fetch_chunks_task.error_count = 0; - // With error count zero - we should fetch exactly as needed: - assert_eq!(fetch_chunks_task.get_desired_request_count(10, threshold), threshold - 10); - } -} diff --git a/polkadot/node/network/availability-recovery/src/task/mod.rs b/polkadot/node/network/availability-recovery/src/task/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..800a82947d6f30e0073646aa1760b405f637ec8f --- /dev/null +++ b/polkadot/node/network/availability-recovery/src/task/mod.rs @@ -0,0 +1,197 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Main recovery task logic. Runs recovery strategies. + +#![warn(missing_docs)] + +mod strategy; + +pub use self::strategy::{ + FetchChunks, FetchChunksParams, FetchFull, FetchFullParams, FetchSystematicChunks, + FetchSystematicChunksParams, RecoveryStrategy, State, +}; + +#[cfg(test)] +pub use self::strategy::{REGULAR_CHUNKS_REQ_RETRY_LIMIT, SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT}; + +use crate::{metrics::Metrics, ErasureTask, PostRecoveryCheck, LOG_TARGET}; + +use parity_scale_codec::Encode; +use polkadot_node_primitives::AvailableData; +use polkadot_node_subsystem::{messages::AvailabilityStoreMessage, overseer, RecoveryError}; +use polkadot_primitives::{AuthorityDiscoveryId, CandidateHash, Hash}; +use sc_network::ProtocolName; + +use futures::channel::{mpsc, oneshot}; +use std::collections::VecDeque; + +/// Recovery parameters common to all strategies in a `RecoveryTask`. +#[derive(Clone)] +pub struct RecoveryParams { + /// Discovery ids of `validators`. + pub validator_authority_keys: Vec, + + /// Number of validators. + pub n_validators: usize, + + /// The number of regular chunks needed. + pub threshold: usize, + + /// The number of systematic chunks needed. + pub systematic_threshold: usize, + + /// A hash of the relevant candidate. + pub candidate_hash: CandidateHash, + + /// The root of the erasure encoding of the candidate. + pub erasure_root: Hash, + + /// Metrics to report. + pub metrics: Metrics, + + /// Do not request data from availability-store. Useful for collators. + pub bypass_availability_store: bool, + + /// The type of check to perform after available data was recovered. + pub post_recovery_check: PostRecoveryCheck, + + /// The blake2-256 hash of the PoV. + pub pov_hash: Hash, + + /// Protocol name for ChunkFetchingV1. + pub req_v1_protocol_name: ProtocolName, + + /// Protocol name for ChunkFetchingV2. + pub req_v2_protocol_name: ProtocolName, + + /// Whether or not chunk mapping is enabled. + pub chunk_mapping_enabled: bool, + + /// Channel to the erasure task handler. + pub erasure_task_tx: mpsc::Sender, +} + +/// A stateful reconstruction of availability data in reference to +/// a candidate hash. +pub struct RecoveryTask { + sender: Sender, + params: RecoveryParams, + strategies: VecDeque>>, + state: State, +} + +impl RecoveryTask +where + Sender: overseer::AvailabilityRecoverySenderTrait, +{ + /// Instantiate a new recovery task. + pub fn new( + sender: Sender, + params: RecoveryParams, + strategies: VecDeque>>, + ) -> Self { + Self { sender, params, strategies, state: State::new() } + } + + async fn in_availability_store(&mut self) -> Option { + if !self.params.bypass_availability_store { + let (tx, rx) = oneshot::channel(); + self.sender + .send_message(AvailabilityStoreMessage::QueryAvailableData( + self.params.candidate_hash, + tx, + )) + .await; + + match rx.await { + Ok(Some(data)) => return Some(data), + Ok(None) => {}, + Err(oneshot::Canceled) => { + gum::warn!( + target: LOG_TARGET, + candidate_hash = ?self.params.candidate_hash, + "Failed to reach the availability store", + ) + }, + } + } + + None + } + + /// Run this recovery task to completion. It will loop through the configured strategies + /// in-order and return whenever the first one recovers the full `AvailableData`. + pub async fn run(mut self) -> Result { + if let Some(data) = self.in_availability_store().await { + return Ok(data) + } + + self.params.metrics.on_recovery_started(); + + let _timer = self.params.metrics.time_full_recovery(); + + while let Some(current_strategy) = self.strategies.pop_front() { + let display_name = current_strategy.display_name(); + let strategy_type = current_strategy.strategy_type(); + + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?self.params.candidate_hash, + "Starting `{}` strategy", + display_name + ); + + let res = current_strategy.run(&mut self.state, &mut self.sender, &self.params).await; + + match res { + Err(RecoveryError::Unavailable) => + if self.strategies.front().is_some() { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?self.params.candidate_hash, + "Recovery strategy `{}` did not conclude. Trying the next one.", + display_name + ); + continue + }, + Err(err) => { + match &err { + RecoveryError::Invalid => + self.params.metrics.on_recovery_invalid(strategy_type), + _ => self.params.metrics.on_recovery_failed(strategy_type), + } + return Err(err) + }, + Ok(data) => { + self.params.metrics.on_recovery_succeeded(strategy_type, data.encoded_size()); + return Ok(data) + }, + } + } + + // We have no other strategies to try. + gum::warn!( + target: LOG_TARGET, + candidate_hash = ?self.params.candidate_hash, + "Recovery of available data failed.", + ); + + self.params.metrics.on_recovery_failed("all"); + + Err(RecoveryError::Unavailable) + } +} diff --git a/polkadot/node/network/availability-recovery/src/task/strategy/chunks.rs b/polkadot/node/network/availability-recovery/src/task/strategy/chunks.rs new file mode 100644 index 0000000000000000000000000000000000000000..b6376a5b543ed75d511571ec48d2fee8cac6a7d4 --- /dev/null +++ b/polkadot/node/network/availability-recovery/src/task/strategy/chunks.rs @@ -0,0 +1,335 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use crate::{ + futures_undead::FuturesUndead, + task::{ + strategy::{ + do_post_recovery_check, is_unavailable, OngoingRequests, N_PARALLEL, + REGULAR_CHUNKS_REQ_RETRY_LIMIT, + }, + RecoveryParams, State, + }, + ErasureTask, RecoveryStrategy, LOG_TARGET, +}; + +use polkadot_node_primitives::AvailableData; +use polkadot_node_subsystem::{overseer, RecoveryError}; +use polkadot_primitives::ValidatorIndex; + +use futures::{channel::oneshot, SinkExt}; +use rand::seq::SliceRandom; +use std::collections::VecDeque; + +/// Parameters specific to the `FetchChunks` strategy. +pub struct FetchChunksParams { + pub n_validators: usize, +} + +/// `RecoveryStrategy` that requests chunks from validators, in parallel. +pub struct FetchChunks { + /// How many requests have been unsuccessful so far. + error_count: usize, + /// Total number of responses that have been received, including failed ones. + total_received_responses: usize, + /// A shuffled array of validator indices. + validators: VecDeque, + /// Collection of in-flight requests. + requesting_chunks: OngoingRequests, +} + +impl FetchChunks { + /// Instantiate a new strategy. + pub fn new(params: FetchChunksParams) -> Self { + // Shuffle the validators to make sure that we don't request chunks from the same + // validators over and over. + let mut validators: VecDeque = + (0..params.n_validators).map(|i| ValidatorIndex(i as u32)).collect(); + validators.make_contiguous().shuffle(&mut rand::thread_rng()); + + Self { + error_count: 0, + total_received_responses: 0, + validators, + requesting_chunks: FuturesUndead::new(), + } + } + + fn is_unavailable( + unrequested_validators: usize, + in_flight_requests: usize, + chunk_count: usize, + threshold: usize, + ) -> bool { + is_unavailable(chunk_count, in_flight_requests, unrequested_validators, threshold) + } + + /// Desired number of parallel requests. + /// + /// For the given threshold (total required number of chunks) get the desired number of + /// requests we want to have running in parallel at this time. + fn get_desired_request_count(&self, chunk_count: usize, threshold: usize) -> usize { + // Upper bound for parallel requests. + // We want to limit this, so requests can be processed within the timeout and we limit the + // following feedback loop: + // 1. Requests fail due to timeout + // 2. We request more chunks to make up for it + // 3. Bandwidth is spread out even more, so we get even more timeouts + // 4. We request more chunks to make up for it ... + let max_requests_boundary = std::cmp::min(N_PARALLEL, threshold); + // How many chunks are still needed? + let remaining_chunks = threshold.saturating_sub(chunk_count); + // What is the current error rate, so we can make up for it? + let inv_error_rate = + self.total_received_responses.checked_div(self.error_count).unwrap_or(0); + // Actual number of requests we want to have in flight in parallel: + std::cmp::min( + max_requests_boundary, + remaining_chunks + remaining_chunks.checked_div(inv_error_rate).unwrap_or(0), + ) + } + + async fn attempt_recovery( + &mut self, + state: &mut State, + common_params: &RecoveryParams, + ) -> Result { + let recovery_duration = common_params + .metrics + .time_erasure_recovery(RecoveryStrategy::::strategy_type(self)); + + // Send request to reconstruct available data from chunks. + let (avilable_data_tx, available_data_rx) = oneshot::channel(); + + let mut erasure_task_tx = common_params.erasure_task_tx.clone(); + erasure_task_tx + .send(ErasureTask::Reconstruct( + common_params.n_validators, + // Safe to leave an empty vec in place, as we're stopping the recovery process if + // this reconstruct fails. + std::mem::take(&mut state.received_chunks) + .into_iter() + .map(|(c_index, chunk)| (c_index, chunk.chunk)) + .collect(), + avilable_data_tx, + )) + .await + .map_err(|_| RecoveryError::ChannelClosed)?; + + let available_data_response = + available_data_rx.await.map_err(|_| RecoveryError::ChannelClosed)?; + + match available_data_response { + // Attempt post-recovery check. + Ok(data) => do_post_recovery_check(common_params, data) + .await + .map_err(|e| { + recovery_duration.map(|rd| rd.stop_and_discard()); + e + }) + .map(|data| { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + "Data recovery from chunks complete", + ); + data + }), + Err(err) => { + recovery_duration.map(|rd| rd.stop_and_discard()); + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + ?err, + "Data recovery error", + ); + + Err(RecoveryError::Invalid) + }, + } + } +} + +#[async_trait::async_trait] +impl RecoveryStrategy for FetchChunks { + fn display_name(&self) -> &'static str { + "Fetch chunks" + } + + fn strategy_type(&self) -> &'static str { + "regular_chunks" + } + + async fn run( + mut self: Box, + state: &mut State, + sender: &mut Sender, + common_params: &RecoveryParams, + ) -> Result { + // First query the store for any chunks we've got. + if !common_params.bypass_availability_store { + let local_chunk_indices = state.populate_from_av_store(common_params, sender).await; + self.validators.retain(|validator_index| { + !local_chunk_indices.iter().any(|(v_index, _)| v_index == validator_index) + }); + } + + // No need to query the validators that have the chunks we already received or that we know + // don't have the data from previous strategies. + self.validators.retain(|v_index| { + !state.received_chunks.values().any(|c| v_index == &c.validator_index) && + state.can_retry_request( + &(common_params.validator_authority_keys[v_index.0 as usize].clone(), *v_index), + REGULAR_CHUNKS_REQ_RETRY_LIMIT, + ) + }); + + // Safe to `take` here, as we're consuming `self` anyway and we're not using the + // `validators` field in other methods. + let mut validators_queue: VecDeque<_> = std::mem::take(&mut self.validators) + .into_iter() + .map(|validator_index| { + ( + common_params.validator_authority_keys[validator_index.0 as usize].clone(), + validator_index, + ) + }) + .collect(); + + loop { + // If received_chunks has more than threshold entries, attempt to recover the data. + // If that fails, or a re-encoding of it doesn't match the expected erasure root, + // return Err(RecoveryError::Invalid). + // Do this before requesting any chunks because we may have enough of them coming from + // past RecoveryStrategies. + if state.chunk_count() >= common_params.threshold { + return self.attempt_recovery::(state, common_params).await + } + + if Self::is_unavailable( + validators_queue.len(), + self.requesting_chunks.total_len(), + state.chunk_count(), + common_params.threshold, + ) { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + received = %state.chunk_count(), + requesting = %self.requesting_chunks.len(), + total_requesting = %self.requesting_chunks.total_len(), + n_validators = %common_params.n_validators, + "Data recovery from chunks is not possible", + ); + + return Err(RecoveryError::Unavailable) + } + + let desired_requests_count = + self.get_desired_request_count(state.chunk_count(), common_params.threshold); + let already_requesting_count = self.requesting_chunks.len(); + gum::debug!( + target: LOG_TARGET, + ?common_params.candidate_hash, + ?desired_requests_count, + error_count= ?self.error_count, + total_received = ?self.total_received_responses, + threshold = ?common_params.threshold, + ?already_requesting_count, + "Requesting availability chunks for a candidate", + ); + + let strategy_type = RecoveryStrategy::::strategy_type(&*self); + + state + .launch_parallel_chunk_requests( + strategy_type, + common_params, + sender, + desired_requests_count, + &mut validators_queue, + &mut self.requesting_chunks, + ) + .await; + + let (total_responses, error_count) = state + .wait_for_chunks( + strategy_type, + common_params, + REGULAR_CHUNKS_REQ_RETRY_LIMIT, + &mut validators_queue, + &mut self.requesting_chunks, + &mut vec![], + |unrequested_validators, + in_flight_reqs, + chunk_count, + _systematic_chunk_count| { + chunk_count >= common_params.threshold || + Self::is_unavailable( + unrequested_validators, + in_flight_reqs, + chunk_count, + common_params.threshold, + ) + }, + ) + .await; + + self.total_received_responses += total_responses; + self.error_count += error_count; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_erasure_coding::recovery_threshold; + + #[test] + fn test_get_desired_request_count() { + let n_validators = 100; + let threshold = recovery_threshold(n_validators).unwrap(); + + let mut fetch_chunks_task = FetchChunks::new(FetchChunksParams { n_validators }); + assert_eq!(fetch_chunks_task.get_desired_request_count(0, threshold), threshold); + fetch_chunks_task.error_count = 1; + fetch_chunks_task.total_received_responses = 1; + // We saturate at threshold (34): + assert_eq!(fetch_chunks_task.get_desired_request_count(0, threshold), threshold); + + // We saturate at the parallel limit. + assert_eq!(fetch_chunks_task.get_desired_request_count(0, N_PARALLEL + 2), N_PARALLEL); + + fetch_chunks_task.total_received_responses = 2; + // With given error rate - still saturating: + assert_eq!(fetch_chunks_task.get_desired_request_count(1, threshold), threshold); + fetch_chunks_task.total_received_responses = 10; + // error rate: 1/10 + // remaining chunks needed: threshold (34) - 9 + // expected: 24 * (1+ 1/10) = (next greater integer) = 27 + assert_eq!(fetch_chunks_task.get_desired_request_count(9, threshold), 27); + // We saturate at the parallel limit. + assert_eq!(fetch_chunks_task.get_desired_request_count(9, N_PARALLEL + 9), N_PARALLEL); + + fetch_chunks_task.error_count = 0; + // With error count zero - we should fetch exactly as needed: + assert_eq!(fetch_chunks_task.get_desired_request_count(10, threshold), threshold - 10); + } +} diff --git a/polkadot/node/network/availability-recovery/src/task/strategy/full.rs b/polkadot/node/network/availability-recovery/src/task/strategy/full.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d7fbe8ea3c8da42ab3227750852c02d328b6dd8 --- /dev/null +++ b/polkadot/node/network/availability-recovery/src/task/strategy/full.rs @@ -0,0 +1,174 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use crate::{ + task::{RecoveryParams, RecoveryStrategy, State}, + ErasureTask, PostRecoveryCheck, LOG_TARGET, +}; + +use polkadot_node_network_protocol::request_response::{ + self as req_res, outgoing::RequestError, OutgoingRequest, Recipient, Requests, +}; +use polkadot_node_primitives::AvailableData; +use polkadot_node_subsystem::{messages::NetworkBridgeTxMessage, overseer, RecoveryError}; +use polkadot_primitives::ValidatorIndex; +use sc_network::{IfDisconnected, OutboundFailure, RequestFailure}; + +use futures::{channel::oneshot, SinkExt}; +use rand::seq::SliceRandom; + +/// Parameters specific to the `FetchFull` strategy. +pub struct FetchFullParams { + /// Validators that will be used for fetching the data. + pub validators: Vec, +} + +/// `RecoveryStrategy` that sequentially tries to fetch the full `AvailableData` from +/// already-connected validators in the configured validator set. +pub struct FetchFull { + params: FetchFullParams, +} + +impl FetchFull { + /// Create a new `FetchFull` recovery strategy. + pub fn new(mut params: FetchFullParams) -> Self { + params.validators.shuffle(&mut rand::thread_rng()); + Self { params } + } +} + +#[async_trait::async_trait] +impl RecoveryStrategy for FetchFull { + fn display_name(&self) -> &'static str { + "Full recovery from backers" + } + + fn strategy_type(&self) -> &'static str { + "full_from_backers" + } + + async fn run( + mut self: Box, + _: &mut State, + sender: &mut Sender, + common_params: &RecoveryParams, + ) -> Result { + let strategy_type = RecoveryStrategy::::strategy_type(&*self); + + loop { + // Pop the next validator. + let validator_index = + self.params.validators.pop().ok_or_else(|| RecoveryError::Unavailable)?; + + // Request data. + let (req, response) = OutgoingRequest::new( + Recipient::Authority( + common_params.validator_authority_keys[validator_index.0 as usize].clone(), + ), + req_res::v1::AvailableDataFetchingRequest { + candidate_hash: common_params.candidate_hash, + }, + ); + + sender + .send_message(NetworkBridgeTxMessage::SendRequests( + vec![Requests::AvailableDataFetchingV1(req)], + IfDisconnected::ImmediateError, + )) + .await; + + common_params.metrics.on_full_request_issued(); + + match response.await { + Ok(req_res::v1::AvailableDataFetchingResponse::AvailableData(data)) => { + let recovery_duration = + common_params.metrics.time_erasure_recovery(strategy_type); + let maybe_data = match common_params.post_recovery_check { + PostRecoveryCheck::Reencode => { + let (reencode_tx, reencode_rx) = oneshot::channel(); + let mut erasure_task_tx = common_params.erasure_task_tx.clone(); + + erasure_task_tx + .send(ErasureTask::Reencode( + common_params.n_validators, + common_params.erasure_root, + data, + reencode_tx, + )) + .await + .map_err(|_| RecoveryError::ChannelClosed)?; + + reencode_rx.await.map_err(|_| RecoveryError::ChannelClosed)? + }, + PostRecoveryCheck::PovHash => + (data.pov.hash() == common_params.pov_hash).then_some(data), + }; + + match maybe_data { + Some(data) => { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + "Received full data", + ); + + common_params.metrics.on_full_request_succeeded(); + return Ok(data) + }, + None => { + common_params.metrics.on_full_request_invalid(); + recovery_duration.map(|rd| rd.stop_and_discard()); + + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + ?validator_index, + "Invalid data response", + ); + + // it doesn't help to report the peer with req/res. + // we'll try the next backer. + }, + } + }, + Ok(req_res::v1::AvailableDataFetchingResponse::NoSuchData) => { + common_params.metrics.on_full_request_no_such_data(); + }, + Err(e) => { + match &e { + RequestError::Canceled(_) => common_params.metrics.on_full_request_error(), + RequestError::InvalidResponse(_) => + common_params.metrics.on_full_request_invalid(), + RequestError::NetworkError(req_failure) => { + if let RequestFailure::Network(OutboundFailure::Timeout) = req_failure { + common_params.metrics.on_full_request_timeout(); + } else { + common_params.metrics.on_full_request_error(); + } + }, + }; + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + ?validator_index, + err = ?e, + "Error fetching full available data." + ); + }, + } + } + } +} diff --git a/polkadot/node/network/availability-recovery/src/task/strategy/mod.rs b/polkadot/node/network/availability-recovery/src/task/strategy/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..fb31ff6aa77920ff49d22571898e03fe93d9654b --- /dev/null +++ b/polkadot/node/network/availability-recovery/src/task/strategy/mod.rs @@ -0,0 +1,1558 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Recovery strategies. + +mod chunks; +mod full; +mod systematic; + +pub use self::{ + chunks::{FetchChunks, FetchChunksParams}, + full::{FetchFull, FetchFullParams}, + systematic::{FetchSystematicChunks, FetchSystematicChunksParams}, +}; +use crate::{ + futures_undead::FuturesUndead, ErasureTask, PostRecoveryCheck, RecoveryParams, LOG_TARGET, +}; + +use futures::{channel::oneshot, SinkExt}; +use parity_scale_codec::Decode; +use polkadot_erasure_coding::branch_hash; +#[cfg(not(test))] +use polkadot_node_network_protocol::request_response::CHUNK_REQUEST_TIMEOUT; +use polkadot_node_network_protocol::request_response::{ + self as req_res, outgoing::RequestError, OutgoingRequest, Recipient, Requests, +}; +use polkadot_node_primitives::{AvailableData, ErasureChunk}; +use polkadot_node_subsystem::{ + messages::{AvailabilityStoreMessage, NetworkBridgeTxMessage}, + overseer, RecoveryError, +}; +use polkadot_primitives::{AuthorityDiscoveryId, BlakeTwo256, ChunkIndex, HashT, ValidatorIndex}; +use sc_network::{IfDisconnected, OutboundFailure, ProtocolName, RequestFailure}; +use std::{ + collections::{BTreeMap, HashMap, VecDeque}, + time::Duration, +}; + +// How many parallel chunk fetching requests should be running at once. +const N_PARALLEL: usize = 50; + +/// Time after which we consider a request to have failed +/// +/// and we should try more peers. Note in theory the request times out at the network level, +/// measurements have shown, that in practice requests might actually take longer to fail in +/// certain occasions. (The very least, authority discovery is not part of the timeout.) +/// +/// For the time being this value is the same as the timeout on the networking layer, but as this +/// timeout is more soft than the networking one, it might make sense to pick different values as +/// well. +#[cfg(not(test))] +const TIMEOUT_START_NEW_REQUESTS: Duration = CHUNK_REQUEST_TIMEOUT; +#[cfg(test)] +const TIMEOUT_START_NEW_REQUESTS: Duration = Duration::from_millis(100); + +/// The maximum number of times systematic chunk recovery will try making a request for a given +/// (validator,chunk) pair, if the error was not fatal. Added so that we don't get stuck in an +/// infinite retry loop. +pub const SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT: u32 = 2; +/// The maximum number of times regular chunk recovery will try making a request for a given +/// (validator,chunk) pair, if the error was not fatal. Added so that we don't get stuck in an +/// infinite retry loop. +pub const REGULAR_CHUNKS_REQ_RETRY_LIMIT: u32 = 5; + +// Helpful type alias for tracking ongoing chunk requests. +type OngoingRequests = FuturesUndead<( + AuthorityDiscoveryId, + ValidatorIndex, + Result<(Option, ProtocolName), RequestError>, +)>; + +const fn is_unavailable( + received_chunks: usize, + requesting_chunks: usize, + unrequested_validators: usize, + threshold: usize, +) -> bool { + received_chunks + requesting_chunks + unrequested_validators < threshold +} + +/// Check validity of a chunk. +fn is_chunk_valid(params: &RecoveryParams, chunk: &ErasureChunk) -> bool { + let anticipated_hash = + match branch_hash(¶ms.erasure_root, chunk.proof(), chunk.index.0 as usize) { + Ok(hash) => hash, + Err(e) => { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + chunk_index = ?chunk.index, + error = ?e, + "Invalid Merkle proof", + ); + return false + }, + }; + let erasure_chunk_hash = BlakeTwo256::hash(&chunk.chunk); + if anticipated_hash != erasure_chunk_hash { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + chunk_index = ?chunk.index, + "Merkle proof mismatch" + ); + return false + } + true +} + +/// Perform the validity checks after recovery. +async fn do_post_recovery_check( + params: &RecoveryParams, + data: AvailableData, +) -> Result { + let mut erasure_task_tx = params.erasure_task_tx.clone(); + match params.post_recovery_check { + PostRecoveryCheck::Reencode => { + // Send request to re-encode the chunks and check merkle root. + let (reencode_tx, reencode_rx) = oneshot::channel(); + erasure_task_tx + .send(ErasureTask::Reencode( + params.n_validators, + params.erasure_root, + data, + reencode_tx, + )) + .await + .map_err(|_| RecoveryError::ChannelClosed)?; + + reencode_rx.await.map_err(|_| RecoveryError::ChannelClosed)?.ok_or_else(|| { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + erasure_root = ?params.erasure_root, + "Data recovery error - root mismatch", + ); + RecoveryError::Invalid + }) + }, + PostRecoveryCheck::PovHash => { + let pov = data.pov.clone(); + (pov.hash() == params.pov_hash).then_some(data).ok_or_else(|| { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + expected_pov_hash = ?params.pov_hash, + actual_pov_hash = ?pov.hash(), + "Data recovery error - PoV hash mismatch", + ); + RecoveryError::Invalid + }) + }, + } +} + +#[async_trait::async_trait] +/// Common trait for runnable recovery strategies. +pub trait RecoveryStrategy: Send { + /// Main entry point of the strategy. + async fn run( + mut self: Box, + state: &mut State, + sender: &mut Sender, + common_params: &RecoveryParams, + ) -> Result; + + /// Return the name of the strategy for logging purposes. + fn display_name(&self) -> &'static str; + + /// Return the strategy type for use as a metric label. + fn strategy_type(&self) -> &'static str; +} + +/// Utility type used for recording the result of requesting a chunk from a validator. +enum ErrorRecord { + NonFatal(u32), + Fatal, +} + +/// Helper struct used for the `received_chunks` mapping. +/// Compared to `ErasureChunk`, it doesn't need to hold the `ChunkIndex` (because it's the key used +/// for the map) and proof, but needs to hold the `ValidatorIndex` instead. +struct Chunk { + /// The erasure-encoded chunk of data belonging to the candidate block. + chunk: Vec, + /// The validator index that corresponds to this chunk. Not always the same as the chunk index. + validator_index: ValidatorIndex, +} + +/// Intermediate/common data that must be passed between `RecoveryStrategy`s belonging to the +/// same `RecoveryTask`. +pub struct State { + /// Chunks received so far. + /// This MUST be a `BTreeMap` in order for systematic recovery to work (the algorithm assumes + /// that chunks are ordered by their index). If we ever switch this to some non-ordered + /// collection, we need to add a sort step to the systematic recovery. + received_chunks: BTreeMap, + + /// A record of errors returned when requesting a chunk from a validator. + recorded_errors: HashMap<(AuthorityDiscoveryId, ValidatorIndex), ErrorRecord>, +} + +impl State { + pub fn new() -> Self { + Self { received_chunks: BTreeMap::new(), recorded_errors: HashMap::new() } + } + + fn insert_chunk(&mut self, chunk_index: ChunkIndex, chunk: Chunk) { + self.received_chunks.insert(chunk_index, chunk); + } + + fn chunk_count(&self) -> usize { + self.received_chunks.len() + } + + fn systematic_chunk_count(&self, systematic_threshold: usize) -> usize { + self.received_chunks + .range(ChunkIndex(0)..ChunkIndex(systematic_threshold as u32)) + .count() + } + + fn record_error_fatal( + &mut self, + authority_id: AuthorityDiscoveryId, + validator_index: ValidatorIndex, + ) { + self.recorded_errors.insert((authority_id, validator_index), ErrorRecord::Fatal); + } + + fn record_error_non_fatal( + &mut self, + authority_id: AuthorityDiscoveryId, + validator_index: ValidatorIndex, + ) { + self.recorded_errors + .entry((authority_id, validator_index)) + .and_modify(|record| { + if let ErrorRecord::NonFatal(ref mut count) = record { + *count = count.saturating_add(1); + } + }) + .or_insert(ErrorRecord::NonFatal(1)); + } + + fn can_retry_request( + &self, + key: &(AuthorityDiscoveryId, ValidatorIndex), + retry_threshold: u32, + ) -> bool { + match self.recorded_errors.get(key) { + None => true, + Some(entry) => match entry { + ErrorRecord::Fatal => false, + ErrorRecord::NonFatal(count) if *count < retry_threshold => true, + ErrorRecord::NonFatal(_) => false, + }, + } + } + + /// Retrieve the local chunks held in the av-store (should be either 0 or 1). + async fn populate_from_av_store( + &mut self, + params: &RecoveryParams, + sender: &mut Sender, + ) -> Vec<(ValidatorIndex, ChunkIndex)> { + let (tx, rx) = oneshot::channel(); + sender + .send_message(AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx)) + .await; + + match rx.await { + Ok(chunks) => { + // This should either be length 1 or 0. If we had the whole data, + // we wouldn't have reached this stage. + let chunk_indices: Vec<_> = chunks + .iter() + .map(|(validator_index, chunk)| (*validator_index, chunk.index)) + .collect(); + + for (validator_index, chunk) in chunks { + if is_chunk_valid(params, &chunk) { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + chunk_index = ?chunk.index, + "Found valid chunk on disk" + ); + self.insert_chunk( + chunk.index, + Chunk { chunk: chunk.chunk, validator_index }, + ); + } else { + gum::error!( + target: LOG_TARGET, + "Loaded invalid chunk from disk! Disk/Db corruption _very_ likely - please fix ASAP!" + ); + }; + } + + chunk_indices + }, + Err(oneshot::Canceled) => { + gum::warn!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + "Failed to reach the availability store" + ); + + vec![] + }, + } + } + + /// Launch chunk requests in parallel, according to the parameters. + async fn launch_parallel_chunk_requests( + &mut self, + strategy_type: &str, + params: &RecoveryParams, + sender: &mut Sender, + desired_requests_count: usize, + validators: &mut VecDeque<(AuthorityDiscoveryId, ValidatorIndex)>, + requesting_chunks: &mut OngoingRequests, + ) where + Sender: overseer::AvailabilityRecoverySenderTrait, + { + let candidate_hash = params.candidate_hash; + let already_requesting_count = requesting_chunks.len(); + + let to_launch = desired_requests_count - already_requesting_count; + let mut requests = Vec::with_capacity(to_launch); + + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + "Attempting to launch {} requests", + to_launch + ); + + while requesting_chunks.len() < desired_requests_count { + if let Some((authority_id, validator_index)) = validators.pop_back() { + gum::trace!( + target: LOG_TARGET, + ?authority_id, + ?validator_index, + ?candidate_hash, + "Requesting chunk", + ); + + // Request data. + let raw_request_v2 = + req_res::v2::ChunkFetchingRequest { candidate_hash, index: validator_index }; + let raw_request_v1 = req_res::v1::ChunkFetchingRequest::from(raw_request_v2); + + let (req, res) = OutgoingRequest::new_with_fallback( + Recipient::Authority(authority_id.clone()), + raw_request_v2, + raw_request_v1, + ); + requests.push(Requests::ChunkFetching(req)); + + params.metrics.on_chunk_request_issued(strategy_type); + let timer = params.metrics.time_chunk_request(strategy_type); + let v1_protocol_name = params.req_v1_protocol_name.clone(); + let v2_protocol_name = params.req_v2_protocol_name.clone(); + + let chunk_mapping_enabled = params.chunk_mapping_enabled; + let authority_id_clone = authority_id.clone(); + + requesting_chunks.push(Box::pin(async move { + let _timer = timer; + let res = match res.await { + Ok((bytes, protocol)) => + if v2_protocol_name == protocol { + match req_res::v2::ChunkFetchingResponse::decode(&mut &bytes[..]) { + Ok(req_res::v2::ChunkFetchingResponse::Chunk(chunk)) => + Ok((Some(chunk.into()), protocol)), + Ok(req_res::v2::ChunkFetchingResponse::NoSuchChunk) => + Ok((None, protocol)), + Err(e) => Err(RequestError::InvalidResponse(e)), + } + } else if v1_protocol_name == protocol { + // V1 protocol version must not be used when chunk mapping node + // feature is enabled, because we can't know the real index of the + // returned chunk. + // This case should never be reached as long as the + // `AvailabilityChunkMapping` feature is only enabled after the + // v1 version is removed. Still, log this. + if chunk_mapping_enabled { + gum::info!( + target: LOG_TARGET, + ?candidate_hash, + authority_id = ?authority_id_clone, + "Another validator is responding on /req_chunk/1 protocol while the availability chunk \ + mapping feature is enabled in the runtime. All validators must switch to /req_chunk/2." + ); + } + + match req_res::v1::ChunkFetchingResponse::decode(&mut &bytes[..]) { + Ok(req_res::v1::ChunkFetchingResponse::Chunk(chunk)) => Ok(( + Some(chunk.recombine_into_chunk(&raw_request_v1)), + protocol, + )), + Ok(req_res::v1::ChunkFetchingResponse::NoSuchChunk) => + Ok((None, protocol)), + Err(e) => Err(RequestError::InvalidResponse(e)), + } + } else { + Err(RequestError::NetworkError(RequestFailure::UnknownProtocol)) + }, + + Err(e) => Err(e), + }; + + (authority_id, validator_index, res) + })); + } else { + break + } + } + + if requests.len() != 0 { + sender + .send_message(NetworkBridgeTxMessage::SendRequests( + requests, + IfDisconnected::TryConnect, + )) + .await; + } + } + + /// Wait for a sufficient amount of chunks to reconstruct according to the provided `params`. + async fn wait_for_chunks( + &mut self, + strategy_type: &str, + params: &RecoveryParams, + retry_threshold: u32, + validators: &mut VecDeque<(AuthorityDiscoveryId, ValidatorIndex)>, + requesting_chunks: &mut OngoingRequests, + // If supplied, these validators will be used as a backup for requesting chunks. They + // should hold all chunks. Each of them will only be used to query one chunk. + backup_validators: &mut Vec, + // Function that returns `true` when this strategy can conclude. Either if we got enough + // chunks or if it's impossible. + mut can_conclude: impl FnMut( + // Number of validators left in the queue + usize, + // Number of in flight requests + usize, + // Number of valid chunks received so far + usize, + // Number of valid systematic chunks received so far + usize, + ) -> bool, + ) -> (usize, usize) { + let metrics = ¶ms.metrics; + + let mut total_received_responses = 0; + let mut error_count = 0; + + // Wait for all current requests to conclude or time-out, or until we reach enough chunks. + // We also declare requests undead, once `TIMEOUT_START_NEW_REQUESTS` is reached and will + // return in that case for `launch_parallel_requests` to fill up slots again. + while let Some(res) = requesting_chunks.next_with_timeout(TIMEOUT_START_NEW_REQUESTS).await + { + total_received_responses += 1; + + let (authority_id, validator_index, request_result) = res; + + let mut is_error = false; + + match request_result { + Ok((maybe_chunk, protocol)) => { + match protocol { + name if name == params.req_v1_protocol_name => + params.metrics.on_chunk_response_v1(), + name if name == params.req_v2_protocol_name => + params.metrics.on_chunk_response_v2(), + _ => {}, + } + + match maybe_chunk { + Some(chunk) => + if is_chunk_valid(params, &chunk) { + metrics.on_chunk_request_succeeded(strategy_type); + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + ?authority_id, + ?validator_index, + "Received valid chunk", + ); + self.insert_chunk( + chunk.index, + Chunk { chunk: chunk.chunk, validator_index }, + ); + } else { + metrics.on_chunk_request_invalid(strategy_type); + error_count += 1; + // Record that we got an invalid chunk so that subsequent strategies + // don't try requesting this again. + self.record_error_fatal(authority_id.clone(), validator_index); + is_error = true; + }, + None => { + metrics.on_chunk_request_no_such_chunk(strategy_type); + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + ?authority_id, + ?validator_index, + "Validator did not have the chunk", + ); + error_count += 1; + // Record that the validator did not have this chunk so that subsequent + // strategies don't try requesting this again. + self.record_error_fatal(authority_id.clone(), validator_index); + is_error = true; + }, + } + }, + Err(err) => { + error_count += 1; + + gum::trace!( + target: LOG_TARGET, + candidate_hash= ?params.candidate_hash, + ?err, + ?authority_id, + ?validator_index, + "Failure requesting chunk", + ); + + is_error = true; + + match err { + RequestError::InvalidResponse(_) => { + metrics.on_chunk_request_invalid(strategy_type); + + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?params.candidate_hash, + ?err, + ?authority_id, + ?validator_index, + "Chunk fetching response was invalid", + ); + + // Record that we got an invalid chunk so that this or + // subsequent strategies don't try requesting this again. + self.record_error_fatal(authority_id.clone(), validator_index); + }, + RequestError::NetworkError(err) => { + // No debug logs on general network errors - that became very + // spammy occasionally. + if let RequestFailure::Network(OutboundFailure::Timeout) = err { + metrics.on_chunk_request_timeout(strategy_type); + } else { + metrics.on_chunk_request_error(strategy_type); + } + + // Record that we got a non-fatal error so that this or + // subsequent strategies will retry requesting this only a + // limited number of times. + self.record_error_non_fatal(authority_id.clone(), validator_index); + }, + RequestError::Canceled(_) => { + metrics.on_chunk_request_error(strategy_type); + + // Record that we got a non-fatal error so that this or + // subsequent strategies will retry requesting this only a + // limited number of times. + self.record_error_non_fatal(authority_id.clone(), validator_index); + }, + } + }, + } + + if is_error { + // First, see if we can retry the request. + if self.can_retry_request(&(authority_id.clone(), validator_index), retry_threshold) + { + validators.push_front((authority_id, validator_index)); + } else { + // Otherwise, try requesting from a backer as a backup, if we've not already + // requested the same chunk from it. + + let position = backup_validators.iter().position(|v| { + !self.recorded_errors.contains_key(&(v.clone(), validator_index)) + }); + if let Some(position) = position { + // Use swap_remove because it's faster and we don't care about order here. + let backer = backup_validators.swap_remove(position); + validators.push_front((backer, validator_index)); + } + } + } + + if can_conclude( + validators.len(), + requesting_chunks.total_len(), + self.chunk_count(), + self.systematic_chunk_count(params.systematic_threshold), + ) { + gum::debug!( + target: LOG_TARGET, + validators_len = validators.len(), + candidate_hash = ?params.candidate_hash, + received_chunks_count = ?self.chunk_count(), + requested_chunks_count = ?requesting_chunks.len(), + threshold = ?params.threshold, + "Can conclude availability recovery strategy", + ); + break + } + } + + (total_received_responses, error_count) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{tests::*, Metrics, RecoveryStrategy, RecoveryTask}; + use assert_matches::assert_matches; + use futures::{ + channel::mpsc::{self, UnboundedReceiver}, + executor, future, Future, FutureExt, StreamExt, + }; + use parity_scale_codec::Error as DecodingError; + use polkadot_erasure_coding::{recovery_threshold, systematic_recovery_threshold}; + use polkadot_node_network_protocol::request_response::Protocol; + use polkadot_node_primitives::{BlockData, PoV}; + use polkadot_node_subsystem::{AllMessages, TimeoutExt}; + use polkadot_node_subsystem_test_helpers::{ + derive_erasure_chunks_with_proofs_and_root, sender_receiver, TestSubsystemSender, + }; + use polkadot_primitives::{CandidateHash, HeadData, PersistedValidationData}; + use polkadot_primitives_test_helpers::dummy_hash; + use sp_keyring::Sr25519Keyring; + use std::sync::Arc; + + const TIMEOUT: Duration = Duration::from_secs(1); + + impl Default for RecoveryParams { + fn default() -> Self { + let validators = vec![ + Sr25519Keyring::Ferdie, + Sr25519Keyring::Alice.into(), + Sr25519Keyring::Bob.into(), + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::One, + Sr25519Keyring::Two, + ]; + let (erasure_task_tx, _erasure_task_rx) = mpsc::channel(10); + + Self { + validator_authority_keys: validator_authority_id(&validators), + n_validators: validators.len(), + threshold: recovery_threshold(validators.len()).unwrap(), + systematic_threshold: systematic_recovery_threshold(validators.len()).unwrap(), + candidate_hash: CandidateHash(dummy_hash()), + erasure_root: dummy_hash(), + metrics: Metrics::new_dummy(), + bypass_availability_store: false, + post_recovery_check: PostRecoveryCheck::Reencode, + pov_hash: dummy_hash(), + req_v1_protocol_name: "/req_chunk/1".into(), + req_v2_protocol_name: "/req_chunk/2".into(), + chunk_mapping_enabled: true, + erasure_task_tx, + } + } + } + + impl RecoveryParams { + fn create_chunks(&mut self) -> Vec { + let available_data = dummy_available_data(); + let (chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( + self.n_validators, + &available_data, + |_, _| {}, + ); + + self.erasure_root = erasure_root; + self.pov_hash = available_data.pov.hash(); + + chunks + } + } + + fn dummy_available_data() -> AvailableData { + let validation_data = PersistedValidationData { + parent_head: HeadData(vec![7, 8, 9]), + relay_parent_number: Default::default(), + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }; + + AvailableData { + validation_data, + pov: Arc::new(PoV { block_data: BlockData(vec![42; 64]) }), + } + } + + fn test_harness, TestFut: Future>( + receiver_future: impl FnOnce(UnboundedReceiver) -> RecvFut, + test: impl FnOnce(TestSubsystemSender) -> TestFut, + ) { + let (sender, receiver) = sender_receiver(); + + let test_fut = test(sender); + let receiver_future = receiver_future(receiver); + + futures::pin_mut!(test_fut); + futures::pin_mut!(receiver_future); + + executor::block_on(future::join(test_fut, receiver_future)).1 + } + + #[test] + fn test_recorded_errors() { + let retry_threshold = 2; + let mut state = State::new(); + + let alice = Sr25519Keyring::Alice.public(); + let bob = Sr25519Keyring::Bob.public(); + let eve = Sr25519Keyring::Eve.public(); + + assert!(state.can_retry_request(&(alice.into(), 0.into()), retry_threshold)); + assert!(state.can_retry_request(&(alice.into(), 0.into()), 0)); + state.record_error_non_fatal(alice.into(), 0.into()); + assert!(state.can_retry_request(&(alice.into(), 0.into()), retry_threshold)); + state.record_error_non_fatal(alice.into(), 0.into()); + assert!(!state.can_retry_request(&(alice.into(), 0.into()), retry_threshold)); + state.record_error_non_fatal(alice.into(), 0.into()); + assert!(!state.can_retry_request(&(alice.into(), 0.into()), retry_threshold)); + + assert!(state.can_retry_request(&(alice.into(), 0.into()), 5)); + + state.record_error_fatal(bob.into(), 1.into()); + assert!(!state.can_retry_request(&(bob.into(), 1.into()), retry_threshold)); + state.record_error_non_fatal(bob.into(), 1.into()); + assert!(!state.can_retry_request(&(bob.into(), 1.into()), retry_threshold)); + + assert!(state.can_retry_request(&(eve.into(), 4.into()), 0)); + assert!(state.can_retry_request(&(eve.into(), 4.into()), retry_threshold)); + } + + #[test] + fn test_populate_from_av_store() { + let params = RecoveryParams::default(); + + // Failed to reach the av store + { + let params = params.clone(); + let candidate_hash = params.candidate_hash; + let mut state = State::new(); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAllChunks(hash, tx)) => { + assert_eq!(hash, candidate_hash); + drop(tx); + }); + }, + |mut sender| async move { + let local_chunk_indices = + state.populate_from_av_store(¶ms, &mut sender).await; + + assert_eq!(state.chunk_count(), 0); + assert_eq!(local_chunk_indices.len(), 0); + }, + ); + } + + // Found invalid chunk + { + let mut params = params.clone(); + let candidate_hash = params.candidate_hash; + let mut state = State::new(); + let chunks = params.create_chunks(); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAllChunks(hash, tx)) => { + assert_eq!(hash, candidate_hash); + let mut chunk = chunks[0].clone(); + chunk.index = 3.into(); + tx.send(vec![(2.into(), chunk)]).unwrap(); + }); + }, + |mut sender| async move { + let local_chunk_indices = + state.populate_from_av_store(¶ms, &mut sender).await; + + assert_eq!(state.chunk_count(), 0); + assert_eq!(local_chunk_indices.len(), 1); + }, + ); + } + + // Found valid chunk + { + let mut params = params.clone(); + let candidate_hash = params.candidate_hash; + let mut state = State::new(); + let chunks = params.create_chunks(); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAllChunks(hash, tx)) => { + assert_eq!(hash, candidate_hash); + tx.send(vec![(4.into(), chunks[1].clone())]).unwrap(); + }); + }, + |mut sender| async move { + let local_chunk_indices = + state.populate_from_av_store(¶ms, &mut sender).await; + + assert_eq!(state.chunk_count(), 1); + assert_eq!(local_chunk_indices.len(), 1); + }, + ); + } + } + + #[test] + fn test_launch_parallel_chunk_requests() { + let params = RecoveryParams::default(); + let alice: AuthorityDiscoveryId = Sr25519Keyring::Alice.public().into(); + let bob: AuthorityDiscoveryId = Sr25519Keyring::Bob.public().into(); + let eve: AuthorityDiscoveryId = Sr25519Keyring::Eve.public().into(); + + // No validators to request from. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + let mut validators = VecDeque::new(); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |mut sender| async move { + state + .launch_parallel_chunk_requests( + "regular", + ¶ms, + &mut sender, + 3, + &mut validators, + &mut ongoing_reqs, + ) + .await; + + assert_eq!(ongoing_reqs.total_len(), 0); + }, + ); + } + + // Has validators but no need to request more. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + let mut validators = VecDeque::new(); + validators.push_back((alice.clone(), ValidatorIndex(1))); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |mut sender| async move { + state + .launch_parallel_chunk_requests( + "regular", + ¶ms, + &mut sender, + 0, + &mut validators, + &mut ongoing_reqs, + ) + .await; + + assert_eq!(ongoing_reqs.total_len(), 0); + }, + ); + } + + // Has validators but no need to request more. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + ongoing_reqs.push(async { todo!() }.boxed()); + ongoing_reqs.soft_cancel(); + let mut validators = VecDeque::new(); + validators.push_back((alice.clone(), ValidatorIndex(1))); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |mut sender| async move { + state + .launch_parallel_chunk_requests( + "regular", + ¶ms, + &mut sender, + 0, + &mut validators, + &mut ongoing_reqs, + ) + .await; + + assert_eq!(ongoing_reqs.total_len(), 1); + assert_eq!(ongoing_reqs.len(), 0); + }, + ); + } + + // Needs to request more. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + ongoing_reqs.push(async { todo!() }.boxed()); + ongoing_reqs.soft_cancel(); + ongoing_reqs.push(async { todo!() }.boxed()); + let mut validators = VecDeque::new(); + validators.push_back((alice.clone(), 0.into())); + validators.push_back((bob, 1.into())); + validators.push_back((eve, 2.into())); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendRequests(requests, _)) if requests.len() +== 3 ); + }, + |mut sender| async move { + state + .launch_parallel_chunk_requests( + "regular", + ¶ms, + &mut sender, + 10, + &mut validators, + &mut ongoing_reqs, + ) + .await; + + assert_eq!(ongoing_reqs.total_len(), 5); + assert_eq!(ongoing_reqs.len(), 4); + }, + ); + } + + // Check network protocol versioning. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + let mut validators = VecDeque::new(); + validators.push_back((alice, 0.into())); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + match receiver.next().timeout(TIMEOUT).await.unwrap().unwrap() { + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendRequests( + mut requests, + _, + )) => { + assert_eq!(requests.len(), 1); + // By default, we should use the new protocol version with a fallback on + // the older one. + let (protocol, request) = requests.remove(0).encode_request(); + assert_eq!(protocol, Protocol::ChunkFetchingV2); + assert_eq!( + request.fallback_request.unwrap().1, + Protocol::ChunkFetchingV1 + ); + }, + _ => unreachable!(), + } + }, + |mut sender| async move { + state + .launch_parallel_chunk_requests( + "regular", + ¶ms, + &mut sender, + 10, + &mut validators, + &mut ongoing_reqs, + ) + .await; + + assert_eq!(ongoing_reqs.total_len(), 1); + assert_eq!(ongoing_reqs.len(), 1); + }, + ); + } + } + + #[test] + fn test_wait_for_chunks() { + let params = RecoveryParams::default(); + let retry_threshold = 2; + + // No ongoing requests. + { + let params = params.clone(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + let mut validators = VecDeque::new(); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |_| async move { + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut vec![], + |_, _, _, _| false, + ) + .await; + assert_eq!(total_responses, 0); + assert_eq!(error_count, 0); + assert_eq!(state.chunk_count(), 0); + }, + ); + } + + // Complex scenario. + { + let mut params = params.clone(); + let chunks = params.create_chunks(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[0].clone(), + 0.into(), + Ok((Some(chunks[0].clone()), "".into())), + )) + .boxed(), + ); + ongoing_reqs.soft_cancel(); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[1].clone(), + 1.into(), + Ok((Some(chunks[1].clone()), "".into())), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[2].clone(), + 2.into(), + Ok((None, "".into())), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[3].clone(), + 3.into(), + Err(RequestError::from(DecodingError::from("err"))), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[4].clone(), + 4.into(), + Err(RequestError::NetworkError(RequestFailure::NotConnected)), + )) + .boxed(), + ); + + let mut validators: VecDeque<_> = (5..params.n_validators as u32) + .map(|i| (params.validator_authority_keys[i as usize].clone(), i.into())) + .collect(); + validators.push_back(( + Sr25519Keyring::AliceStash.public().into(), + ValidatorIndex(params.n_validators as u32), + )); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |_| async move { + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut vec![], + |_, _, _, _| false, + ) + .await; + assert_eq!(total_responses, 5); + assert_eq!(error_count, 3); + assert_eq!(state.chunk_count(), 2); + + let mut expected_validators: VecDeque<_> = (4..params.n_validators as u32) + .map(|i| (params.validator_authority_keys[i as usize].clone(), i.into())) + .collect(); + expected_validators.push_back(( + Sr25519Keyring::AliceStash.public().into(), + ValidatorIndex(params.n_validators as u32), + )); + + assert_eq!(validators, expected_validators); + + // This time we'll go over the recoverable error threshold. + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[4].clone(), + 4.into(), + Err(RequestError::NetworkError(RequestFailure::NotConnected)), + )) + .boxed(), + ); + + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut vec![], + |_, _, _, _| false, + ) + .await; + assert_eq!(total_responses, 1); + assert_eq!(error_count, 1); + assert_eq!(state.chunk_count(), 2); + + validators.pop_front(); + let mut expected_validators: VecDeque<_> = (5..params.n_validators as u32) + .map(|i| (params.validator_authority_keys[i as usize].clone(), i.into())) + .collect(); + expected_validators.push_back(( + Sr25519Keyring::AliceStash.public().into(), + ValidatorIndex(params.n_validators as u32), + )); + + assert_eq!(validators, expected_validators); + + // Check that can_conclude returning true terminates the loop. + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut vec![], + |_, _, _, _| true, + ) + .await; + assert_eq!(total_responses, 0); + assert_eq!(error_count, 0); + assert_eq!(state.chunk_count(), 2); + + assert_eq!(validators, expected_validators); + }, + ); + } + + // Complex scenario with backups in the backing group. + { + let mut params = params.clone(); + let chunks = params.create_chunks(); + let mut state = State::new(); + let mut ongoing_reqs = OngoingRequests::new(); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[0].clone(), + 0.into(), + Ok((Some(chunks[0].clone()), "".into())), + )) + .boxed(), + ); + ongoing_reqs.soft_cancel(); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[1].clone(), + 1.into(), + Ok((Some(chunks[1].clone()), "".into())), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[2].clone(), + 2.into(), + Ok((None, "".into())), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[3].clone(), + 3.into(), + Err(RequestError::from(DecodingError::from("err"))), + )) + .boxed(), + ); + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[4].clone(), + 4.into(), + Err(RequestError::NetworkError(RequestFailure::NotConnected)), + )) + .boxed(), + ); + + let mut validators: VecDeque<_> = (5..params.n_validators as u32) + .map(|i| (params.validator_authority_keys[i as usize].clone(), i.into())) + .collect(); + validators.push_back(( + Sr25519Keyring::Eve.public().into(), + ValidatorIndex(params.n_validators as u32), + )); + + let mut backup_backers = vec![ + params.validator_authority_keys[2].clone(), + params.validator_authority_keys[0].clone(), + params.validator_authority_keys[4].clone(), + params.validator_authority_keys[3].clone(), + Sr25519Keyring::AliceStash.public().into(), + Sr25519Keyring::BobStash.public().into(), + ]; + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |_| async move { + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut backup_backers, + |_, _, _, _| false, + ) + .await; + assert_eq!(total_responses, 5); + assert_eq!(error_count, 3); + assert_eq!(state.chunk_count(), 2); + + let mut expected_validators: VecDeque<_> = (5..params.n_validators as u32) + .map(|i| (params.validator_authority_keys[i as usize].clone(), i.into())) + .collect(); + expected_validators.push_back(( + Sr25519Keyring::Eve.public().into(), + ValidatorIndex(params.n_validators as u32), + )); + // We picked a backer as a backup for chunks 2 and 3. + expected_validators + .push_front((params.validator_authority_keys[0].clone(), 2.into())); + expected_validators + .push_front((params.validator_authority_keys[2].clone(), 3.into())); + expected_validators + .push_front((params.validator_authority_keys[4].clone(), 4.into())); + + assert_eq!(validators, expected_validators); + + // This time we'll go over the recoverable error threshold for chunk 4. + ongoing_reqs.push( + future::ready(( + params.validator_authority_keys[4].clone(), + 4.into(), + Err(RequestError::NetworkError(RequestFailure::NotConnected)), + )) + .boxed(), + ); + + validators.pop_front(); + + let (total_responses, error_count) = state + .wait_for_chunks( + "regular", + ¶ms, + retry_threshold, + &mut validators, + &mut ongoing_reqs, + &mut backup_backers, + |_, _, _, _| false, + ) + .await; + assert_eq!(total_responses, 1); + assert_eq!(error_count, 1); + assert_eq!(state.chunk_count(), 2); + + expected_validators.pop_front(); + expected_validators + .push_front((Sr25519Keyring::AliceStash.public().into(), 4.into())); + + assert_eq!(validators, expected_validators); + }, + ); + } + } + + #[test] + fn test_recovery_strategy_run() { + let params = RecoveryParams::default(); + + struct GoodStrategy; + #[async_trait::async_trait] + impl RecoveryStrategy for GoodStrategy { + fn display_name(&self) -> &'static str { + "GoodStrategy" + } + + fn strategy_type(&self) -> &'static str { + "good_strategy" + } + + async fn run( + mut self: Box, + _state: &mut State, + _sender: &mut Sender, + _common_params: &RecoveryParams, + ) -> Result { + Ok(dummy_available_data()) + } + } + + struct UnavailableStrategy; + #[async_trait::async_trait] + impl RecoveryStrategy + for UnavailableStrategy + { + fn display_name(&self) -> &'static str { + "UnavailableStrategy" + } + + fn strategy_type(&self) -> &'static str { + "unavailable_strategy" + } + + async fn run( + mut self: Box, + _state: &mut State, + _sender: &mut Sender, + _common_params: &RecoveryParams, + ) -> Result { + Err(RecoveryError::Unavailable) + } + } + + struct InvalidStrategy; + #[async_trait::async_trait] + impl RecoveryStrategy + for InvalidStrategy + { + fn display_name(&self) -> &'static str { + "InvalidStrategy" + } + + fn strategy_type(&self) -> &'static str { + "invalid_strategy" + } + + async fn run( + mut self: Box, + _state: &mut State, + _sender: &mut Sender, + _common_params: &RecoveryParams, + ) -> Result { + Err(RecoveryError::Invalid) + } + } + + // No recovery strategies. + { + let mut params = params.clone(); + let strategies = VecDeque::new(); + params.bypass_availability_store = true; + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |sender| async move { + let task = RecoveryTask::new(sender, params, strategies); + + assert_eq!(task.run().await.unwrap_err(), RecoveryError::Unavailable); + }, + ); + } + + // If we have the data in av-store, returns early. + { + let params = params.clone(); + let strategies = VecDeque::new(); + let candidate_hash = params.candidate_hash; + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAvailableData(hash, tx)) => { + assert_eq!(hash, candidate_hash); + tx.send(Some(dummy_available_data())).unwrap(); + }); + }, + |sender| async move { + let task = RecoveryTask::new(sender, params, strategies); + + assert_eq!(task.run().await.unwrap(), dummy_available_data()); + }, + ); + } + + // Strategy returning `RecoveryError::Invalid`` will short-circuit the entire task. + { + let mut params = params.clone(); + params.bypass_availability_store = true; + let mut strategies: VecDeque>> = + VecDeque::new(); + strategies.push_back(Box::new(InvalidStrategy)); + strategies.push_back(Box::new(GoodStrategy)); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + // Shouldn't send any requests. + assert!(receiver.next().timeout(TIMEOUT).await.unwrap().is_none()); + }, + |sender| async move { + let task = RecoveryTask::new(sender, params, strategies); + + assert_eq!(task.run().await.unwrap_err(), RecoveryError::Invalid); + }, + ); + } + + // Strategy returning `Unavailable` will fall back to the next one. + { + let params = params.clone(); + let candidate_hash = params.candidate_hash; + let mut strategies: VecDeque>> = + VecDeque::new(); + strategies.push_back(Box::new(UnavailableStrategy)); + strategies.push_back(Box::new(GoodStrategy)); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAvailableData(hash, tx)) => { + assert_eq!(hash, candidate_hash); + tx.send(Some(dummy_available_data())).unwrap(); + }); + }, + |sender| async move { + let task = RecoveryTask::new(sender, params, strategies); + + assert_eq!(task.run().await.unwrap(), dummy_available_data()); + }, + ); + } + + // More complex scenario. + { + let params = params.clone(); + let candidate_hash = params.candidate_hash; + let mut strategies: VecDeque>> = + VecDeque::new(); + strategies.push_back(Box::new(UnavailableStrategy)); + strategies.push_back(Box::new(UnavailableStrategy)); + strategies.push_back(Box::new(GoodStrategy)); + strategies.push_back(Box::new(InvalidStrategy)); + + test_harness( + |mut receiver: UnboundedReceiver| async move { + assert_matches!( + receiver.next().timeout(TIMEOUT).await.unwrap().unwrap(), + AllMessages::AvailabilityStore(AvailabilityStoreMessage::QueryAvailableData(hash, tx)) => { + assert_eq!(hash, candidate_hash); + tx.send(Some(dummy_available_data())).unwrap(); + }); + }, + |sender| async move { + let task = RecoveryTask::new(sender, params, strategies); + + assert_eq!(task.run().await.unwrap(), dummy_available_data()); + }, + ); + } + } + + #[test] + fn test_is_unavailable() { + assert_eq!(is_unavailable(0, 0, 0, 0), false); + assert_eq!(is_unavailable(2, 2, 2, 0), false); + // Already reached the threshold. + assert_eq!(is_unavailable(3, 0, 10, 3), false); + assert_eq!(is_unavailable(3, 2, 0, 3), false); + assert_eq!(is_unavailable(3, 2, 10, 3), false); + // It's still possible to reach the threshold + assert_eq!(is_unavailable(0, 0, 10, 3), false); + assert_eq!(is_unavailable(0, 0, 3, 3), false); + assert_eq!(is_unavailable(1, 1, 1, 3), false); + // Not possible to reach the threshold + assert_eq!(is_unavailable(0, 0, 0, 3), true); + assert_eq!(is_unavailable(2, 3, 2, 10), true); + } +} diff --git a/polkadot/node/network/availability-recovery/src/task/strategy/systematic.rs b/polkadot/node/network/availability-recovery/src/task/strategy/systematic.rs new file mode 100644 index 0000000000000000000000000000000000000000..677bc2d1375aa75900123c39f1fbe59c8902ea69 --- /dev/null +++ b/polkadot/node/network/availability-recovery/src/task/strategy/systematic.rs @@ -0,0 +1,343 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use crate::{ + futures_undead::FuturesUndead, + task::{ + strategy::{ + do_post_recovery_check, is_unavailable, OngoingRequests, N_PARALLEL, + SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT, + }, + RecoveryParams, RecoveryStrategy, State, + }, + LOG_TARGET, +}; + +use polkadot_node_primitives::AvailableData; +use polkadot_node_subsystem::{overseer, RecoveryError}; +use polkadot_primitives::{ChunkIndex, ValidatorIndex}; + +use std::collections::VecDeque; + +/// Parameters needed for fetching systematic chunks. +pub struct FetchSystematicChunksParams { + /// Validators that hold the systematic chunks. + pub validators: Vec<(ChunkIndex, ValidatorIndex)>, + /// Validators in the backing group, to be used as a backup for requesting systematic chunks. + pub backers: Vec, +} + +/// `RecoveryStrategy` that attempts to recover the systematic chunks from the validators that +/// hold them, in order to bypass the erasure code reconstruction step, which is costly. +pub struct FetchSystematicChunks { + /// Systematic recovery threshold. + threshold: usize, + /// Validators that hold the systematic chunks. + validators: Vec<(ChunkIndex, ValidatorIndex)>, + /// Backers to be used as a backup. + backers: Vec, + /// Collection of in-flight requests. + requesting_chunks: OngoingRequests, +} + +impl FetchSystematicChunks { + /// Instantiate a new systematic chunks strategy. + pub fn new(params: FetchSystematicChunksParams) -> Self { + Self { + threshold: params.validators.len(), + validators: params.validators, + backers: params.backers, + requesting_chunks: FuturesUndead::new(), + } + } + + fn is_unavailable( + unrequested_validators: usize, + in_flight_requests: usize, + systematic_chunk_count: usize, + threshold: usize, + ) -> bool { + is_unavailable( + systematic_chunk_count, + in_flight_requests, + unrequested_validators, + threshold, + ) + } + + /// Desired number of parallel requests. + /// + /// For the given threshold (total required number of chunks) get the desired number of + /// requests we want to have running in parallel at this time. + fn get_desired_request_count(&self, chunk_count: usize, threshold: usize) -> usize { + // Upper bound for parallel requests. + let max_requests_boundary = std::cmp::min(N_PARALLEL, threshold); + // How many chunks are still needed? + let remaining_chunks = threshold.saturating_sub(chunk_count); + // Actual number of requests we want to have in flight in parallel: + // We don't have to make up for any error rate, as an error fetching a systematic chunk + // results in failure of the entire strategy. + std::cmp::min(max_requests_boundary, remaining_chunks) + } + + async fn attempt_systematic_recovery( + &mut self, + state: &mut State, + common_params: &RecoveryParams, + ) -> Result { + let strategy_type = RecoveryStrategy::::strategy_type(self); + let recovery_duration = common_params.metrics.time_erasure_recovery(strategy_type); + let reconstruct_duration = common_params.metrics.time_erasure_reconstruct(strategy_type); + let chunks = state + .received_chunks + .range( + ChunkIndex(0).. + ChunkIndex( + u32::try_from(self.threshold) + .expect("validator count should not exceed u32"), + ), + ) + .map(|(_, chunk)| chunk.chunk.clone()) + .collect::>(); + + let available_data = polkadot_erasure_coding::reconstruct_from_systematic_v1( + common_params.n_validators, + chunks, + ); + + match available_data { + Ok(data) => { + drop(reconstruct_duration); + + // Attempt post-recovery check. + do_post_recovery_check(common_params, data) + .await + .map_err(|e| { + recovery_duration.map(|rd| rd.stop_and_discard()); + e + }) + .map(|data| { + gum::trace!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + "Data recovery from systematic chunks complete", + ); + data + }) + }, + Err(err) => { + reconstruct_duration.map(|rd| rd.stop_and_discard()); + recovery_duration.map(|rd| rd.stop_and_discard()); + + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + ?err, + "Systematic data recovery error", + ); + + Err(RecoveryError::Invalid) + }, + } + } +} + +#[async_trait::async_trait] +impl RecoveryStrategy + for FetchSystematicChunks +{ + fn display_name(&self) -> &'static str { + "Fetch systematic chunks" + } + + fn strategy_type(&self) -> &'static str { + "systematic_chunks" + } + + async fn run( + mut self: Box, + state: &mut State, + sender: &mut Sender, + common_params: &RecoveryParams, + ) -> Result { + // First query the store for any chunks we've got. + if !common_params.bypass_availability_store { + let local_chunk_indices = state.populate_from_av_store(common_params, sender).await; + + for (_, our_c_index) in &local_chunk_indices { + // If we are among the systematic validators but hold an invalid chunk, we cannot + // perform the systematic recovery. Fall through to the next strategy. + if self.validators.iter().any(|(c_index, _)| c_index == our_c_index) && + !state.received_chunks.contains_key(our_c_index) + { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + requesting = %self.requesting_chunks.len(), + total_requesting = %self.requesting_chunks.total_len(), + n_validators = %common_params.n_validators, + chunk_index = ?our_c_index, + "Systematic chunk recovery is not possible. We are among the systematic validators but hold an invalid chunk", + ); + return Err(RecoveryError::Unavailable) + } + } + } + + // No need to query the validators that have the chunks we already received or that we know + // don't have the data from previous strategies. + self.validators.retain(|(c_index, v_index)| { + !state.received_chunks.contains_key(c_index) && + state.can_retry_request( + &(common_params.validator_authority_keys[v_index.0 as usize].clone(), *v_index), + SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT, + ) + }); + + let mut systematic_chunk_count = state + .received_chunks + .range(ChunkIndex(0)..ChunkIndex(self.threshold as u32)) + .count(); + + // Safe to `take` here, as we're consuming `self` anyway and we're not using the + // `validators` or `backers` fields in other methods. + let mut validators_queue: VecDeque<_> = std::mem::take(&mut self.validators) + .into_iter() + .map(|(_, validator_index)| { + ( + common_params.validator_authority_keys[validator_index.0 as usize].clone(), + validator_index, + ) + }) + .collect(); + let mut backers: Vec<_> = std::mem::take(&mut self.backers) + .into_iter() + .map(|validator_index| { + common_params.validator_authority_keys[validator_index.0 as usize].clone() + }) + .collect(); + + loop { + // If received_chunks has `systematic_chunk_threshold` entries, attempt to recover the + // data. + if systematic_chunk_count >= self.threshold { + return self.attempt_systematic_recovery::(state, common_params).await + } + + if Self::is_unavailable( + validators_queue.len(), + self.requesting_chunks.total_len(), + systematic_chunk_count, + self.threshold, + ) { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?common_params.candidate_hash, + erasure_root = ?common_params.erasure_root, + %systematic_chunk_count, + requesting = %self.requesting_chunks.len(), + total_requesting = %self.requesting_chunks.total_len(), + n_validators = %common_params.n_validators, + systematic_threshold = ?self.threshold, + "Data recovery from systematic chunks is not possible", + ); + + return Err(RecoveryError::Unavailable) + } + + let desired_requests_count = + self.get_desired_request_count(systematic_chunk_count, self.threshold); + let already_requesting_count = self.requesting_chunks.len(); + gum::debug!( + target: LOG_TARGET, + ?common_params.candidate_hash, + ?desired_requests_count, + total_received = ?systematic_chunk_count, + systematic_threshold = ?self.threshold, + ?already_requesting_count, + "Requesting systematic availability chunks for a candidate", + ); + + let strategy_type = RecoveryStrategy::::strategy_type(&*self); + + state + .launch_parallel_chunk_requests( + strategy_type, + common_params, + sender, + desired_requests_count, + &mut validators_queue, + &mut self.requesting_chunks, + ) + .await; + + let _ = state + .wait_for_chunks( + strategy_type, + common_params, + SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT, + &mut validators_queue, + &mut self.requesting_chunks, + &mut backers, + |unrequested_validators, + in_flight_reqs, + // Don't use this chunk count, as it may contain non-systematic chunks. + _chunk_count, + new_systematic_chunk_count| { + systematic_chunk_count = new_systematic_chunk_count; + + let is_unavailable = Self::is_unavailable( + unrequested_validators, + in_flight_reqs, + systematic_chunk_count, + self.threshold, + ); + + systematic_chunk_count >= self.threshold || is_unavailable + }, + ) + .await; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_erasure_coding::systematic_recovery_threshold; + + #[test] + fn test_get_desired_request_count() { + let num_validators = 100; + let threshold = systematic_recovery_threshold(num_validators).unwrap(); + + let systematic_chunks_task = FetchSystematicChunks::new(FetchSystematicChunksParams { + validators: vec![(1.into(), 1.into()); num_validators], + backers: vec![], + }); + assert_eq!(systematic_chunks_task.get_desired_request_count(0, threshold), threshold); + assert_eq!(systematic_chunks_task.get_desired_request_count(5, threshold), threshold - 5); + assert_eq!( + systematic_chunks_task.get_desired_request_count(num_validators * 2, threshold), + 0 + ); + assert_eq!(systematic_chunks_task.get_desired_request_count(0, N_PARALLEL * 2), N_PARALLEL); + assert_eq!(systematic_chunks_task.get_desired_request_count(N_PARALLEL, N_PARALLEL + 2), 2); + } +} diff --git a/polkadot/node/network/availability-recovery/src/tests.rs b/polkadot/node/network/availability-recovery/src/tests.rs index 909f6a25f46b1eca3074095b6f54f0415d62c562..d0a4a2d8b60e8a969b8d8bf73731afd28de83093 100644 --- a/polkadot/node/network/availability-recovery/src/tests.rs +++ b/polkadot/node/network/availability-recovery/src/tests.rs @@ -14,38 +14,133 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::{sync::Arc, time::Duration}; +use crate::task::{REGULAR_CHUNKS_REQ_RETRY_LIMIT, SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT}; + +use super::*; +use std::{result::Result, sync::Arc, time::Duration}; use assert_matches::assert_matches; use futures::{executor, future}; use futures_timer::Delay; +use rstest::rstest; use parity_scale_codec::Encode; use polkadot_node_network_protocol::request_response::{ - self as req_res, v1::AvailableDataFetchingRequest, IncomingRequest, Protocol, Recipient, - ReqProtocolNames, Requests, + self as req_res, + v1::{AvailableDataFetchingRequest, ChunkResponse}, + IncomingRequest, Protocol, Recipient, ReqProtocolNames, Requests, }; -use polkadot_node_subsystem_test_helpers::derive_erasure_chunks_with_proofs_and_root; - -use super::*; -use sc_network::{IfDisconnected, OutboundFailure, ProtocolName, RequestFailure}; - -use polkadot_node_primitives::{BlockData, PoV, Proof}; +use polkadot_node_primitives::{BlockData, ErasureChunk, PoV, Proof}; use polkadot_node_subsystem::messages::{ AllMessages, NetworkBridgeTxMessage, RuntimeApiMessage, RuntimeApiRequest, }; use polkadot_node_subsystem_test_helpers::{ - make_subsystem_context, mock::new_leaf, TestSubsystemContextHandle, + derive_erasure_chunks_with_proofs_and_root, make_subsystem_context, mock::new_leaf, + TestSubsystemContextHandle, }; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - AuthorityDiscoveryId, Block, Hash, HeadData, IndexedVec, PersistedValidationData, ValidatorId, + node_features, AuthorityDiscoveryId, Block, ExecutorParams, Hash, HeadData, IndexedVec, + NodeFeatures, PersistedValidationData, SessionInfo, ValidatorId, }; use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; +use sc_network::{IfDisconnected, OutboundFailure, ProtocolName, RequestFailure}; +use sp_keyring::Sr25519Keyring; type VirtualOverseer = TestSubsystemContextHandle; +// Implement some helper constructors for the AvailabilityRecoverySubsystem + +/// Create a new instance of `AvailabilityRecoverySubsystem` which starts with a fast path to +/// request data from backers. +fn with_fast_path( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + req_receiver, + req_protocol_names, + metrics, + RecoveryStrategyKind::BackersFirstAlways, + ) +} + +/// Create a new instance of `AvailabilityRecoverySubsystem` which requests only chunks +fn with_chunks_only( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + req_receiver, + req_protocol_names, + metrics, + RecoveryStrategyKind::ChunksAlways, + ) +} + +/// Create a new instance of `AvailabilityRecoverySubsystem` which requests chunks if PoV is +/// above a threshold. +fn with_chunks_if_pov_large( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + req_receiver, + req_protocol_names, + metrics, + RecoveryStrategyKind::BackersFirstIfSizeLower(FETCH_CHUNKS_THRESHOLD), + ) +} + +/// Create a new instance of `AvailabilityRecoverySubsystem` which requests systematic chunks if +/// PoV is above a threshold. +fn with_systematic_chunks_if_pov_large( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::for_validator( + Some(FETCH_CHUNKS_THRESHOLD), + req_receiver, + req_protocol_names, + metrics, + ) +} + +/// Create a new instance of `AvailabilityRecoverySubsystem` which first requests full data +/// from backers, with a fallback to recover from systematic chunks. +fn with_fast_path_then_systematic_chunks( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + req_receiver, + req_protocol_names, + metrics, + RecoveryStrategyKind::BackersThenSystematicChunks, + ) +} + +/// Create a new instance of `AvailabilityRecoverySubsystem` which first attempts to request +/// systematic chunks, with a fallback to requesting regular chunks. +fn with_systematic_chunks( + req_receiver: IncomingRequestReceiver, + req_protocol_names: &ReqProtocolNames, + metrics: Metrics, +) -> AvailabilityRecoverySubsystem { + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + req_receiver, + req_protocol_names, + metrics, + RecoveryStrategyKind::SystematicChunks, + ) +} + // Deterministic genesis hash for protocol names const GENESIS_HASH: Hash = Hash::repeat_byte(0xff); @@ -61,14 +156,11 @@ fn request_receiver( receiver.0 } -fn test_harness>( +fn test_harness>( subsystem: AvailabilityRecoverySubsystem, - test: impl FnOnce(VirtualOverseer) -> T, + test: impl FnOnce(VirtualOverseer) -> Fut, ) { - let _ = env_logger::builder() - .is_test(true) - .filter(Some("polkadot_availability_recovery"), log::LevelFilter::Trace) - .try_init(); + sp_tracing::init_for_tests(); let pool = sp_core::testing::TaskExecutor::new(); @@ -138,8 +230,6 @@ async fn overseer_recv( msg } -use sp_keyring::Sr25519Keyring; - #[derive(Debug)] enum Has { No, @@ -163,27 +253,127 @@ struct TestState { validators: Vec, validator_public: IndexedVec, validator_authority_id: Vec, + validator_groups: IndexedVec>, current: Hash, candidate: CandidateReceipt, session_index: SessionIndex, + core_index: CoreIndex, + node_features: NodeFeatures, persisted_validation_data: PersistedValidationData, available_data: AvailableData, - chunks: Vec, - invalid_chunks: Vec, + chunks: IndexedVec, + invalid_chunks: IndexedVec, } impl TestState { + fn new(node_features: NodeFeatures) -> Self { + let validators = vec![ + Sr25519Keyring::Ferdie, // <- this node, role: validator + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::One, + Sr25519Keyring::Two, + ]; + + let validator_public = validator_pubkeys(&validators); + let validator_authority_id = validator_authority_id(&validators); + let validator_groups = vec![ + vec![1.into(), 0.into(), 3.into(), 4.into()], + vec![5.into(), 6.into()], + vec![2.into()], + ]; + + let current = Hash::repeat_byte(1); + + let mut candidate = dummy_candidate_receipt(dummy_hash()); + + let session_index = 10; + + let persisted_validation_data = PersistedValidationData { + parent_head: HeadData(vec![7, 8, 9]), + relay_parent_number: Default::default(), + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }; + + let pov = PoV { block_data: BlockData(vec![42; 64]) }; + + let available_data = AvailableData { + validation_data: persisted_validation_data.clone(), + pov: Arc::new(pov), + }; + + let core_index = CoreIndex(2); + + let (chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( + validators.len(), + &available_data, + |_, _| {}, + ); + let chunks = map_chunks(chunks, &node_features, validators.len(), core_index); + + // Mess around: + let invalid_chunks = chunks + .iter() + .cloned() + .map(|mut chunk| { + if chunk.chunk.len() >= 2 && chunk.chunk[0] != chunk.chunk[1] { + chunk.chunk[0] = chunk.chunk[1]; + } else if chunk.chunk.len() >= 1 { + chunk.chunk[0] = !chunk.chunk[0]; + } else { + chunk.proof = Proof::dummy_proof(); + } + chunk + }) + .collect(); + debug_assert_ne!(chunks, invalid_chunks); + + candidate.descriptor.erasure_root = erasure_root; + candidate.descriptor.relay_parent = Hash::repeat_byte(10); + candidate.descriptor.pov_hash = Hash::repeat_byte(3); + + Self { + validators, + validator_public, + validator_authority_id, + validator_groups: IndexedVec::>::try_from( + validator_groups, + ) + .unwrap(), + current, + candidate, + session_index, + core_index, + node_features, + persisted_validation_data, + available_data, + chunks, + invalid_chunks, + } + } + + fn with_empty_node_features() -> Self { + Self::new(NodeFeatures::EMPTY) + } + fn threshold(&self) -> usize { recovery_threshold(self.validators.len()).unwrap() } + fn systematic_threshold(&self) -> usize { + systematic_recovery_threshold(self.validators.len()).unwrap() + } + fn impossibility_threshold(&self) -> usize { self.validators.len() - self.threshold() + 1 } - async fn test_runtime_api(&self, virtual_overseer: &mut VirtualOverseer) { + async fn test_runtime_api_session_info(&self, virtual_overseer: &mut VirtualOverseer) { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::RuntimeApi(RuntimeApiMessage::Request( @@ -199,8 +389,7 @@ impl TestState { tx.send(Ok(Some(SessionInfo { validators: self.validator_public.clone(), discovery_keys: self.validator_authority_id.clone(), - // all validators in the same group. - validator_groups: IndexedVec::>::from(vec![(0..self.validators.len()).map(|i| ValidatorIndex(i as _)).collect()]), + validator_groups: self.validator_groups.clone(), assignment_keys: vec![], n_cores: 0, zeroth_delay_tranche_width: 0, @@ -214,6 +403,38 @@ impl TestState { }))).unwrap(); } ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + relay_parent, + RuntimeApiRequest::SessionExecutorParams( + session_index, + tx, + ) + )) => { + assert_eq!(relay_parent, self.current); + assert_eq!(session_index, self.session_index); + + tx.send(Ok(Some(ExecutorParams::new()))).unwrap(); + } + ); + } + + async fn test_runtime_api_node_features(&self, virtual_overseer: &mut VirtualOverseer) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _relay_parent, + RuntimeApiRequest::NodeFeatures( + _, + tx, + ) + )) => { + tx.send(Ok( + self.node_features.clone() + )).unwrap(); + } + ); } async fn respond_to_available_data_query( @@ -239,16 +460,19 @@ impl TestState { async fn respond_to_query_all_request( &self, virtual_overseer: &mut VirtualOverseer, - send_chunk: impl Fn(usize) -> bool, + send_chunk: impl Fn(ValidatorIndex) -> bool, ) { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::AvailabilityStore( AvailabilityStoreMessage::QueryAllChunks(_, tx) ) => { - let v = self.chunks.iter() - .filter(|c| send_chunk(c.index.0 as usize)) - .cloned() + let v = self.chunks.iter().enumerate() + .filter_map(|(val_idx, c)| if send_chunk(ValidatorIndex(val_idx as u32)) { + Some((ValidatorIndex(val_idx as u32), c.clone())) + } else { + None + }) .collect(); let _ = tx.send(v); @@ -259,16 +483,19 @@ impl TestState { async fn respond_to_query_all_request_invalid( &self, virtual_overseer: &mut VirtualOverseer, - send_chunk: impl Fn(usize) -> bool, + send_chunk: impl Fn(ValidatorIndex) -> bool, ) { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::AvailabilityStore( AvailabilityStoreMessage::QueryAllChunks(_, tx) ) => { - let v = self.invalid_chunks.iter() - .filter(|c| send_chunk(c.index.0 as usize)) - .cloned() + let v = self.invalid_chunks.iter().enumerate() + .filter_map(|(val_idx, c)| if send_chunk(ValidatorIndex(val_idx as u32)) { + Some((ValidatorIndex(val_idx as u32), c.clone())) + } else { + None + }) .collect(); let _ = tx.send(v); @@ -276,14 +503,16 @@ impl TestState { ) } - async fn test_chunk_requests( + async fn test_chunk_requests_inner( &self, req_protocol_names: &ReqProtocolNames, candidate_hash: CandidateHash, virtual_overseer: &mut VirtualOverseer, n: usize, - who_has: impl Fn(usize) -> Has, - ) -> Vec, ProtocolName), RequestFailure>>> { + mut who_has: impl FnMut(ValidatorIndex) -> Has, + systematic_recovery: bool, + protocol: Protocol, + ) -> Vec, ProtocolName), RequestFailure>>> { // arbitrary order. let mut i = 0; let mut senders = Vec::new(); @@ -301,13 +530,19 @@ impl TestState { i += 1; assert_matches!( req, - Requests::ChunkFetchingV1(req) => { + Requests::ChunkFetching(req) => { assert_eq!(req.payload.candidate_hash, candidate_hash); - let validator_index = req.payload.index.0 as usize; + let validator_index = req.payload.index; + let chunk = self.chunks.get(validator_index).unwrap().clone(); + + if systematic_recovery { + assert!(chunk.index.0 as usize <= self.systematic_threshold(), "requested non-systematic chunk"); + } + let available_data = match who_has(validator_index) { Has::No => Ok(None), - Has::Yes => Ok(Some(self.chunks[validator_index].clone().into())), + Has::Yes => Ok(Some(chunk)), Has::NetworkError(e) => Err(e), Has::DoesNotReturn => { senders.push(req.pending_response); @@ -315,11 +550,29 @@ impl TestState { } }; - let _ = req.pending_response.send( + req.pending_response.send( available_data.map(|r| - (req_res::v1::ChunkFetchingResponse::from(r).encode(), req_protocol_names.get_name(Protocol::ChunkFetchingV1)) + ( + match protocol { + Protocol::ChunkFetchingV1 => + match r { + None => req_res::v1::ChunkFetchingResponse::NoSuchChunk, + Some(c) => req_res::v1::ChunkFetchingResponse::Chunk( + ChunkResponse { + chunk: c.chunk, + proof: c.proof + } + ) + }.encode(), + Protocol::ChunkFetchingV2 => + req_res::v2::ChunkFetchingResponse::from(r).encode(), + + _ => unreachable!() + }, + req_protocol_names.get_name(protocol) + ) ) - ); + ).unwrap(); } ) } @@ -329,16 +582,61 @@ impl TestState { senders } + async fn test_chunk_requests( + &self, + req_protocol_names: &ReqProtocolNames, + candidate_hash: CandidateHash, + virtual_overseer: &mut VirtualOverseer, + n: usize, + who_has: impl FnMut(ValidatorIndex) -> Has, + systematic_recovery: bool, + ) -> Vec, ProtocolName), RequestFailure>>> { + self.test_chunk_requests_inner( + req_protocol_names, + candidate_hash, + virtual_overseer, + n, + who_has, + systematic_recovery, + Protocol::ChunkFetchingV2, + ) + .await + } + + // Use legacy network protocol version. + async fn test_chunk_requests_v1( + &self, + req_protocol_names: &ReqProtocolNames, + candidate_hash: CandidateHash, + virtual_overseer: &mut VirtualOverseer, + n: usize, + who_has: impl FnMut(ValidatorIndex) -> Has, + systematic_recovery: bool, + ) -> Vec, ProtocolName), RequestFailure>>> { + self.test_chunk_requests_inner( + req_protocol_names, + candidate_hash, + virtual_overseer, + n, + who_has, + systematic_recovery, + Protocol::ChunkFetchingV1, + ) + .await + } + async fn test_full_data_requests( &self, req_protocol_names: &ReqProtocolNames, candidate_hash: CandidateHash, virtual_overseer: &mut VirtualOverseer, who_has: impl Fn(usize) -> Has, - ) -> Vec, ProtocolName), RequestFailure>>> { + group_index: GroupIndex, + ) -> Vec, ProtocolName), RequestFailure>>> { let mut senders = Vec::new(); - for _ in 0..self.validators.len() { - // Receive a request for a chunk. + let expected_validators = self.validator_groups.get(group_index).unwrap(); + for _ in 0..expected_validators.len() { + // Receive a request for the full `AvailableData`. assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::NetworkBridgeTx( @@ -357,6 +655,7 @@ impl TestState { .iter() .position(|a| Recipient::Authority(a.clone()) == req.peer) .unwrap(); + assert!(expected_validators.contains(&ValidatorIndex(validator_index as u32))); let available_data = match who_has(validator_index) { Has::No => Ok(None), @@ -387,95 +686,67 @@ impl TestState { } } +impl Default for TestState { + fn default() -> Self { + // Enable the chunk mapping node feature. + let mut node_features = NodeFeatures::new(); + node_features + .resize(node_features::FeatureIndex::AvailabilityChunkMapping as usize + 1, false); + node_features + .set(node_features::FeatureIndex::AvailabilityChunkMapping as u8 as usize, true); + + Self::new(node_features) + } +} + fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> IndexedVec { val_ids.iter().map(|v| v.public().into()).collect() } -fn validator_authority_id(val_ids: &[Sr25519Keyring]) -> Vec { +pub fn validator_authority_id(val_ids: &[Sr25519Keyring]) -> Vec { val_ids.iter().map(|v| v.public().into()).collect() } -impl Default for TestState { - fn default() -> Self { - let validators = vec![ - Sr25519Keyring::Ferdie, // <- this node, role: validator - Sr25519Keyring::Alice, - Sr25519Keyring::Bob, - Sr25519Keyring::Charlie, - Sr25519Keyring::Dave, - ]; - - let validator_public = validator_pubkeys(&validators); - let validator_authority_id = validator_authority_id(&validators); - - let current = Hash::repeat_byte(1); - - let mut candidate = dummy_candidate_receipt(dummy_hash()); - - let session_index = 10; - - let persisted_validation_data = PersistedValidationData { - parent_head: HeadData(vec![7, 8, 9]), - relay_parent_number: Default::default(), - max_pov_size: 1024, - relay_parent_storage_root: Default::default(), - }; - - let pov = PoV { block_data: BlockData(vec![42; 64]) }; - - let available_data = AvailableData { - validation_data: persisted_validation_data.clone(), - pov: Arc::new(pov), - }; - - let (chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( - validators.len(), - &available_data, - |_, _| {}, - ); - // Mess around: - let invalid_chunks = chunks - .iter() - .cloned() - .map(|mut chunk| { - if chunk.chunk.len() >= 2 && chunk.chunk[0] != chunk.chunk[1] { - chunk.chunk[0] = chunk.chunk[1]; - } else if chunk.chunk.len() >= 1 { - chunk.chunk[0] = !chunk.chunk[0]; - } else { - chunk.proof = Proof::dummy_proof(); - } - chunk - }) - .collect(); - debug_assert_ne!(chunks, invalid_chunks); - - candidate.descriptor.erasure_root = erasure_root; - candidate.descriptor.relay_parent = Hash::repeat_byte(10); - - Self { - validators, - validator_public, - validator_authority_id, - current, - candidate, - session_index, - persisted_validation_data, - available_data, - chunks, - invalid_chunks, - } - } +/// Map the chunks to the validators according to the availability chunk mapping algorithm. +fn map_chunks( + chunks: Vec, + node_features: &NodeFeatures, + n_validators: usize, + core_index: CoreIndex, +) -> IndexedVec { + let chunk_indices = + availability_chunk_indices(Some(node_features), n_validators, core_index).unwrap(); + + (0..n_validators) + .map(|val_idx| chunks[chunk_indices[val_idx].0 as usize].clone()) + .collect::>() + .into() } -#[test] -fn availability_is_recovered_from_chunks_if_no_group_provided() { +#[rstest] +#[case(true)] +#[case(false)] +fn availability_is_recovered_from_chunks_if_no_group_provided(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_fast_path_then_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_fast_path( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -495,12 +766,15 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -512,8 +786,9 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold(), + threshold, |_| Has::Yes, + systematic_recovery, ) .await; @@ -533,16 +808,31 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { new_candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + if systematic_recovery { + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + threshold, + |_| Has::No, + systematic_recovery, + ) + .await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + + // Even if the recovery is systematic, we'll always fall back to regular recovery, so keep + // this around. test_state .test_chunk_requests( &req_protocol_names, @@ -550,6 +840,7 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { &mut virtual_overseer, test_state.impossibility_threshold(), |_| Has::No, + false, ) .await; @@ -559,16 +850,34 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() { }); } -#[test] -fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunks_only() { - let test_state = TestState::default(); +#[rstest] +#[case(true)] +#[case(false)] +fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunks_only( + #[case] systematic_recovery: bool, +) { let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); - - test_harness(subsystem, |mut virtual_overseer| async move { + let test_state = TestState::default(); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( &mut virtual_overseer, OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( @@ -586,12 +895,15 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -603,8 +915,9 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold(), + threshold, |_| Has::Yes, + systematic_recovery, ) .await; @@ -623,41 +936,80 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk AvailabilityRecoveryMessage::RecoverAvailableData( new_candidate.clone(), test_state.session_index, - None, + Some(GroupIndex(1)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; - test_state - .test_chunk_requests( - &req_protocol_names, - new_candidate.hash(), - &mut virtual_overseer, - test_state.impossibility_threshold(), - |_| Has::No, - ) - .await; + if systematic_recovery { + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + threshold * SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT as usize, + |_| Has::No, + systematic_recovery, + ) + .await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + // Even if the recovery is systematic, we'll always fall back to regular recovery, so + // keep this around. + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + test_state.impossibility_threshold() - threshold, + |_| Has::No, + false, + ) + .await; + + // A request times out with `Unavailable` error. + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + } else { + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + test_state.impossibility_threshold(), + |_| Has::No, + false, + ) + .await; - // A request times out with `Unavailable` error. - assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + // A request times out with `Unavailable` error. + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + } virtual_overseer }); } -#[test] -fn bad_merkle_path_leads_to_recovery_error() { - let mut test_state = TestState::default(); +#[rstest] +#[case(true)] +#[case(false)] +fn bad_merkle_path_leads_to_recovery_error(#[case] systematic_recovery: bool) { let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let mut test_state = TestState::default(); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -677,25 +1029,40 @@ fn bad_merkle_path_leads_to_recovery_error() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); // Create some faulty chunks. - test_state.chunks[0].chunk = vec![0; 32]; - test_state.chunks[1].chunk = vec![1; 32]; - test_state.chunks[2].chunk = vec![2; 32]; - test_state.chunks[3].chunk = vec![3; 32]; - test_state.chunks[4].chunk = vec![4; 32]; + for chunk in test_state.chunks.iter_mut() { + chunk.chunk = vec![0; 32]; + } test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + if systematic_recovery { + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.systematic_threshold(), + |_| Has::No, + systematic_recovery, + ) + .await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + test_state .test_chunk_requests( &req_protocol_names, @@ -703,6 +1070,7 @@ fn bad_merkle_path_leads_to_recovery_error() { &mut virtual_overseer, test_state.impossibility_threshold(), |_| Has::Yes, + false, ) .await; @@ -712,14 +1080,24 @@ fn bad_merkle_path_leads_to_recovery_error() { }); } -#[test] -fn wrong_chunk_index_leads_to_recovery_error() { +#[rstest] +#[case(true)] +#[case(false)] +fn wrong_chunk_index_leads_to_recovery_error(#[case] systematic_recovery: bool) { let mut test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -739,32 +1117,55 @@ fn wrong_chunk_index_leads_to_recovery_error() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; - let candidate_hash = test_state.candidate.hash(); + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; - // These chunks should fail the index check as they don't have the correct index for - // validator. - test_state.chunks[1] = test_state.chunks[0].clone(); - test_state.chunks[2] = test_state.chunks[0].clone(); - test_state.chunks[3] = test_state.chunks[0].clone(); - test_state.chunks[4] = test_state.chunks[0].clone(); + let candidate_hash = test_state.candidate.hash(); test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + // Chunks should fail the index check as they don't have the correct index. + + // *(test_state.chunks.get_mut(0.into()).unwrap()) = + // test_state.chunks.get(1.into()).unwrap().clone(); + let first_chunk = test_state.chunks.get(0.into()).unwrap().clone(); + for c_index in 1..test_state.chunks.len() { + *(test_state.chunks.get_mut(ValidatorIndex(c_index as u32)).unwrap()) = + first_chunk.clone(); + } + + if systematic_recovery { + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.systematic_threshold(), + |_| Has::Yes, + // We set this to false, as we know we will be requesting the wrong indices. + false, + ) + .await; + + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + test_state .test_chunk_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.impossibility_threshold(), - |_| Has::No, + test_state.chunks.len() - 1, + |_| Has::Yes, + false, ) .await; @@ -774,14 +1175,30 @@ fn wrong_chunk_index_leads_to_recovery_error() { }); } -#[test] -fn invalid_erasure_coding_leads_to_invalid_error() { +#[rstest] +#[case(true)] +#[case(false)] +fn invalid_erasure_coding_leads_to_invalid_error(#[case] systematic_recovery: bool) { let mut test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_fast_path_then_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_fast_path( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { let pov = PoV { block_data: BlockData(vec![69; 64]) }; @@ -795,7 +1212,12 @@ fn invalid_erasure_coding_leads_to_invalid_error() { |i, chunk| *chunk = vec![i as u8; 32], ); - test_state.chunks = bad_chunks; + test_state.chunks = map_chunks( + bad_chunks, + &test_state.node_features, + test_state.validators.len(), + test_state.core_index, + ); test_state.candidate.descriptor.erasure_root = bad_erasure_root; let candidate_hash = test_state.candidate.hash(); @@ -817,12 +1239,15 @@ fn invalid_erasure_coding_leads_to_invalid_error() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; @@ -832,8 +1257,9 @@ fn invalid_erasure_coding_leads_to_invalid_error() { &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold(), + threshold, |_| Has::Yes, + systematic_recovery, ) .await; @@ -843,12 +1269,74 @@ fn invalid_erasure_coding_leads_to_invalid_error() { }); } +#[test] +fn invalid_pov_hash_leads_to_invalid_error() { + let mut test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let subsystem = AvailabilityRecoverySubsystem::for_collator( + None, + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ); + + test_harness(subsystem, |mut virtual_overseer| async move { + let pov = PoV { block_data: BlockData(vec![69; 64]) }; + + test_state.candidate.descriptor.pov_hash = pov.hash(); + + let candidate_hash = test_state.candidate.hash(); + + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.threshold(), + |_| Has::Yes, + false, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Invalid); + virtual_overseer + }); +} + #[test] fn fast_path_backing_group_recovers() { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( + let subsystem = with_fast_path( request_receiver(&req_protocol_names), + &req_protocol_names, Metrics::new_dummy(), ); @@ -870,12 +1358,14 @@ fn fast_path_backing_group_recovers() { test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -892,6 +1382,7 @@ fn fast_path_backing_group_recovers() { candidate_hash, &mut virtual_overseer, who_has, + GroupIndex(0), ) .await; @@ -901,14 +1392,47 @@ fn fast_path_backing_group_recovers() { }); } -#[test] -fn recovers_from_only_chunks_if_pov_large() { - let test_state = TestState::default(); +#[rstest] +#[case(true, false)] +#[case(false, true)] +#[case(false, false)] +fn recovers_from_only_chunks_if_pov_large( + #[case] systematic_recovery: bool, + #[case] for_collator: bool, +) { + let mut test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_if_pov_large( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let (subsystem, threshold) = match (systematic_recovery, for_collator) { + (true, false) => ( + with_systematic_chunks_if_pov_large( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + (false, false) => ( + with_chunks_if_pov_large( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + (false, true) => { + test_state.candidate.descriptor.pov_hash = test_state.available_data.pov.hash(); + ( + AvailabilityRecoverySubsystem::for_collator( + None, + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ) + }, + (_, _) => unreachable!(), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -928,12 +1452,15 @@ fn recovers_from_only_chunks_if_pov_large() { test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -942,20 +1469,23 @@ fn recovers_from_only_chunks_if_pov_large() { AllMessages::AvailabilityStore( AvailabilityStoreMessage::QueryChunkSize(_, tx) ) => { - let _ = tx.send(Some(1000000)); + let _ = tx.send(Some(crate::FETCH_CHUNKS_THRESHOLD + 1)); } ); - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; - test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + if !for_collator { + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } test_state .test_chunk_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold(), + threshold, |_| Has::Yes, + systematic_recovery, ) .await; @@ -974,35 +1504,64 @@ fn recovers_from_only_chunks_if_pov_large() { AvailabilityRecoveryMessage::RecoverAvailableData( new_candidate.clone(), test_state.session_index, - Some(GroupIndex(0)), + Some(GroupIndex(1)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; - assert_matches!( overseer_recv(&mut virtual_overseer).await, AllMessages::AvailabilityStore( AvailabilityStoreMessage::QueryChunkSize(_, tx) ) => { - let _ = tx.send(Some(1000000)); + let _ = tx.send(Some(crate::FETCH_CHUNKS_THRESHOLD + 1)); } ); - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; - test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + if !for_collator { + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } - test_state - .test_chunk_requests( - &req_protocol_names, - new_candidate.hash(), - &mut virtual_overseer, - test_state.impossibility_threshold(), - |_| Has::No, - ) - .await; + if systematic_recovery { + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + test_state.systematic_threshold() * SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT as usize, + |_| Has::No, + systematic_recovery, + ) + .await; + if !for_collator { + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + // Even if the recovery is systematic, we'll always fall back to regular recovery. + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + test_state.impossibility_threshold() - threshold, + |_| Has::No, + false, + ) + .await; + } else { + test_state + .test_chunk_requests( + &req_protocol_names, + new_candidate.hash(), + &mut virtual_overseer, + test_state.impossibility_threshold(), + |_| Has::No, + false, + ) + .await; + } // A request times out with `Unavailable` error. assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); @@ -1010,14 +1569,40 @@ fn recovers_from_only_chunks_if_pov_large() { }); } -#[test] -fn fast_path_backing_group_recovers_if_pov_small() { - let test_state = TestState::default(); +#[rstest] +#[case(true, false)] +#[case(false, true)] +#[case(false, false)] +fn fast_path_backing_group_recovers_if_pov_small( + #[case] systematic_recovery: bool, + #[case] for_collator: bool, +) { + let mut test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_if_pov_large( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + + let subsystem = match (systematic_recovery, for_collator) { + (true, false) => with_systematic_chunks_if_pov_large( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + + (false, false) => with_chunks_if_pov_large( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + (false, true) => { + test_state.candidate.descriptor.pov_hash = test_state.available_data.pov.hash(); + AvailabilityRecoverySubsystem::for_collator( + None, + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ) + }, + (_, _) => unreachable!(), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1037,12 +1622,15 @@ fn fast_path_backing_group_recovers_if_pov_small() { test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -1060,7 +1648,9 @@ fn fast_path_backing_group_recovers_if_pov_small() { } ); - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + if !for_collator { + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + } test_state .test_full_data_requests( @@ -1068,6 +1658,7 @@ fn fast_path_backing_group_recovers_if_pov_small() { candidate_hash, &mut virtual_overseer, who_has, + GroupIndex(0), ) .await; @@ -1077,14 +1668,31 @@ fn fast_path_backing_group_recovers_if_pov_small() { }); } -#[test] -fn no_answers_in_fast_path_causes_chunk_requests() { +#[rstest] +#[case(true)] +#[case(false)] +fn no_answers_in_fast_path_causes_chunk_requests(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_fast_path( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_fast_path_then_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_fast_path( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1104,12 +1712,15 @@ fn no_answers_in_fast_path_causes_chunk_requests() { test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -1127,6 +1738,7 @@ fn no_answers_in_fast_path_causes_chunk_requests() { candidate_hash, &mut virtual_overseer, who_has, + GroupIndex(0), ) .await; @@ -1137,8 +1749,9 @@ fn no_answers_in_fast_path_causes_chunk_requests() { &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold(), + threshold, |_| Has::Yes, + systematic_recovery, ) .await; @@ -1148,14 +1761,25 @@ fn no_answers_in_fast_path_causes_chunk_requests() { }); } -#[test] -fn task_canceled_when_receivers_dropped() { +#[rstest] +#[case(true)] +#[case(false)] +fn task_canceled_when_receivers_dropped(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1175,12 +1799,15 @@ fn task_canceled_when_receivers_dropped() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; for _ in 0..test_state.validators.len() { match virtual_overseer.recv().timeout(TIMEOUT).await { @@ -1193,14 +1820,24 @@ fn task_canceled_when_receivers_dropped() { }); } -#[test] -fn chunks_retry_until_all_nodes_respond() { +#[rstest] +#[case(true)] +#[case(false)] +fn chunks_retry_until_all_nodes_respond(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1219,30 +1856,51 @@ fn chunks_retry_until_all_nodes_respond() { AvailabilityRecoveryMessage::RecoverAvailableData( test_state.candidate.clone(), test_state.session_index, - Some(GroupIndex(0)), + None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + if systematic_recovery { + for _ in 0..SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT { + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.systematic_threshold(), + |_| Has::timeout(), + true, + ) + .await; + } + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + test_state .test_chunk_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.validators.len() - test_state.threshold(), + test_state.impossibility_threshold(), |_| Has::timeout(), + false, ) .await; - // we get to go another round! + // We get to go another round! Actually, we get to go `REGULAR_CHUNKS_REQ_RETRY_LIMIT` + // number of times. test_state .test_chunk_requests( &req_protocol_names, @@ -1250,21 +1908,23 @@ fn chunks_retry_until_all_nodes_respond() { &mut virtual_overseer, test_state.impossibility_threshold(), |_| Has::No, + false, ) .await; - // Recovered data should match the original one. + // Recovery is impossible. assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); virtual_overseer }); } #[test] -fn not_returning_requests_wont_stall_retrieval() { +fn network_bridge_not_returning_responses_wont_stall_retrieval() { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( + let subsystem = with_chunks_only( request_receiver(&req_protocol_names), + &req_protocol_names, Metrics::new_dummy(), ); @@ -1286,12 +1946,15 @@ fn not_returning_requests_wont_stall_retrieval() { test_state.candidate.clone(), test_state.session_index, Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); @@ -1309,6 +1972,7 @@ fn not_returning_requests_wont_stall_retrieval() { &mut virtual_overseer, not_returning_count, |_| Has::DoesNotReturn, + false, ) .await; @@ -1320,6 +1984,7 @@ fn not_returning_requests_wont_stall_retrieval() { // Should start over: test_state.validators.len() + 3, |_| Has::timeout(), + false, ) .await; @@ -1331,6 +1996,7 @@ fn not_returning_requests_wont_stall_retrieval() { &mut virtual_overseer, test_state.threshold(), |_| Has::Yes, + false, ) .await; @@ -1340,14 +2006,24 @@ fn not_returning_requests_wont_stall_retrieval() { }); } -#[test] -fn all_not_returning_requests_still_recovers_on_return() { +#[rstest] +#[case(true)] +#[case(false)] +fn all_not_returning_requests_still_recovers_on_return(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1366,46 +2042,64 @@ fn all_not_returning_requests_still_recovers_on_return() { AvailabilityRecoveryMessage::RecoverAvailableData( test_state.candidate.clone(), test_state.session_index, - Some(GroupIndex(0)), + None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + let n = if systematic_recovery { + test_state.systematic_threshold() + } else { + test_state.validators.len() + }; let senders = test_state .test_chunk_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.validators.len(), + n, |_| Has::DoesNotReturn, + systematic_recovery, ) .await; future::join( async { Delay::new(Duration::from_millis(10)).await; - // Now retrieval should be able to recover. + // Now retrieval should be able progress. std::mem::drop(senders); }, - test_state.test_chunk_requests( - &req_protocol_names, - candidate_hash, - &mut virtual_overseer, - // Should start over: - test_state.validators.len() + 3, - |_| Has::timeout(), - ), + async { + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + // Should start over: + n, + |_| Has::timeout(), + systematic_recovery, + ) + .await + }, ) .await; + if systematic_recovery { + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + // we get to go another round! test_state .test_chunk_requests( @@ -1414,6 +2108,7 @@ fn all_not_returning_requests_still_recovers_on_return() { &mut virtual_overseer, test_state.threshold(), |_| Has::Yes, + false, ) .await; @@ -1423,14 +2118,24 @@ fn all_not_returning_requests_still_recovers_on_return() { }); } -#[test] -fn returns_early_if_we_have_the_data() { +#[rstest] +#[case(true)] +#[case(false)] +fn returns_early_if_we_have_the_data(#[case] systematic_recovery: bool) { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( - request_receiver(&req_protocol_names), - Metrics::new_dummy(), - ); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; test_harness(subsystem, |mut virtual_overseer| async move { overseer_signal( @@ -1450,12 +2155,15 @@ fn returns_early_if_we_have_the_data() { test_state.candidate.clone(), test_state.session_index, None, + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; test_state.respond_to_available_data_query(&mut virtual_overseer, true).await; assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); @@ -1464,11 +2172,12 @@ fn returns_early_if_we_have_the_data() { } #[test] -fn does_not_query_local_validator() { +fn returns_early_if_present_in_the_subsystem_cache() { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( + let subsystem = with_fast_path( request_receiver(&req_protocol_names), + &req_protocol_names, Metrics::new_dummy(), ); @@ -1489,50 +2198,812 @@ fn does_not_query_local_validator() { AvailabilityRecoveryMessage::RecoverAvailableData( test_state.candidate.clone(), test_state.session_index, - None, + Some(GroupIndex(0)), + Some(test_state.core_index), tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; - test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; - test_state.respond_to_query_all_request(&mut virtual_overseer, |i| i == 0).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; let candidate_hash = test_state.candidate.hash(); + let who_has = |i| match i { + 3 => Has::Yes, + _ => Has::No, + }; + + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state - .test_chunk_requests( + .test_full_data_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.validators.len(), - |i| if i == 0 { panic!("requested from local validator") } else { Has::timeout() }, + who_has, + GroupIndex(0), ) .await; - // second round, make sure it uses the local chunk. - test_state - .test_chunk_requests( - &req_protocol_names, + // Recovered data should match the original one. + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + + // A second recovery for the same candidate will return early as it'll be present in the + // cache. + let (tx, rx) = oneshot::channel(); + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + Some(GroupIndex(0)), + Some(test_state.core_index), + tx, + ), + ) + .await; + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + + virtual_overseer + }); +} + +#[rstest] +#[case(true)] +#[case(false)] +fn does_not_query_local_validator(#[case] systematic_recovery: bool) { + let test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state + .respond_to_query_all_request(&mut virtual_overseer, |i| i.0 == 0) + .await; + + let candidate_hash = test_state.candidate.hash(); + + // second round, make sure it uses the local chunk. + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + threshold - 1, + |i| if i.0 == 0 { panic!("requested from local validator") } else { Has::Yes }, + systematic_recovery, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + virtual_overseer + }); +} + +#[rstest] +#[case(true)] +#[case(false)] +fn invalid_local_chunk(#[case] systematic_recovery: bool) { + let test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + + let validator_index_for_first_chunk = test_state + .chunks + .iter() + .enumerate() + .find_map(|(val_idx, chunk)| if chunk.index.0 == 0 { Some(val_idx) } else { None }) + .unwrap() as u32; + + test_state + .respond_to_query_all_request_invalid(&mut virtual_overseer, |i| { + i.0 == validator_index_for_first_chunk + }) + .await; + + let candidate_hash = test_state.candidate.hash(); + + // If systematic recovery detects invalid local chunk, it'll directly go to regular + // recovery, if we were the one holding an invalid chunk. + if systematic_recovery { + test_state + .respond_to_query_all_request_invalid(&mut virtual_overseer, |i| { + i.0 == validator_index_for_first_chunk + }) + .await; + } + + test_state + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.threshold(), + |i| { + if i.0 == validator_index_for_first_chunk { + panic!("requested from local validator") + } else { + Has::Yes + } + }, + false, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + virtual_overseer + }); +} + +#[test] +fn systematic_chunks_are_not_requested_again_in_regular_recovery() { + // Run this test multiple times, as the order in which requests are made is random and we want + // to make sure that we catch regressions. + for _ in 0..TestState::default().chunks.len() { + let test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let subsystem = with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ); + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + let validator_index_for_first_chunk = test_state + .chunks + .iter() + .enumerate() + .find_map(|(val_idx, chunk)| if chunk.index.0 == 0 { Some(val_idx) } else { None }) + .unwrap() as u32; + + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + test_state.systematic_threshold(), + |i| if i.0 == validator_index_for_first_chunk { Has::No } else { Has::Yes }, + true, + ) + .await; + + // Falls back to regular recovery, since one validator returned a fatal error. + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + 1, + |i| { + if (test_state.chunks.get(i).unwrap().index.0 as usize) < + test_state.systematic_threshold() + { + panic!("Already requested") + } else { + Has::Yes + } + }, + false, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + virtual_overseer + }); + } +} + +#[rstest] +#[case(true, true)] +#[case(true, false)] +#[case(false, true)] +#[case(false, false)] +fn chunk_indices_are_mapped_to_different_validators( + #[case] systematic_recovery: bool, + #[case] mapping_enabled: bool, +) { + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let test_state = match mapping_enabled { + true => TestState::default(), + false => TestState::with_empty_node_features(), + }; + let subsystem = match systematic_recovery { + true => with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + false => with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, _rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + let mut chunk_indices: Vec<(u32, u32)> = vec![]; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridgeTx( + NetworkBridgeTxMessage::SendRequests( + requests, + _if_disconnected, + ) + ) => { + for req in requests { + assert_matches!( + req, + Requests::ChunkFetching(req) => { + assert_eq!(req.payload.candidate_hash, test_state.candidate.hash()); + + let validator_index = req.payload.index; + let chunk_index = test_state.chunks.get(validator_index).unwrap().index; + + if systematic_recovery && mapping_enabled { + assert!((chunk_index.0 as usize) <= test_state.systematic_threshold(), "requested non-systematic chunk"); + } + + chunk_indices.push((chunk_index.0, validator_index.0)); + } + ) + } + } + ); + + if mapping_enabled { + assert!(!chunk_indices.iter().any(|(c_index, v_index)| c_index == v_index)); + } else { + assert!(chunk_indices.iter().all(|(c_index, v_index)| c_index == v_index)); + } + + virtual_overseer + }); +} + +#[rstest] +#[case(true, false)] +#[case(false, true)] +#[case(false, false)] +fn number_of_request_retries_is_bounded( + #[case] systematic_recovery: bool, + #[case] should_fail: bool, +) { + let mut test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + // We need the number of validators to be evenly divisible by the threshold for this test to be + // easier to write. + let n_validators = 6; + test_state.validators.truncate(n_validators); + test_state.validator_authority_id.truncate(n_validators); + let mut temp = test_state.validator_public.to_vec(); + temp.truncate(n_validators); + test_state.validator_public = temp.into(); + + let (chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( + n_validators, + &test_state.available_data, + |_, _| {}, + ); + test_state.chunks = + map_chunks(chunks, &test_state.node_features, n_validators, test_state.core_index); + test_state.candidate.descriptor.erasure_root = erasure_root; + + let (subsystem, retry_limit) = match systematic_recovery { + false => ( + with_chunks_only( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + REGULAR_CHUNKS_REQ_RETRY_LIMIT, + ), + true => ( + with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT, + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + let validator_count_per_iteration = if systematic_recovery { + test_state.systematic_threshold() + } else { + test_state.chunks.len() + }; + + // Network errors are considered non-fatal but should be retried a limited number of times. + for _ in 1..retry_limit { + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + validator_count_per_iteration, + |_| Has::timeout(), + systematic_recovery, + ) + .await; + } + + if should_fail { + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + validator_count_per_iteration, + |_| Has::timeout(), + systematic_recovery, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + } else { + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + test_state.threshold(), + |_| Has::Yes, + systematic_recovery, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + } + + virtual_overseer + }); +} + +#[test] +fn systematic_recovery_retries_from_backers() { + let test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let subsystem = with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ); + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + let group_index = GroupIndex(2); + let group_size = test_state.validator_groups.get(group_index).unwrap().len(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + Some(group_index), + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + let mut cnt = 0; + + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + test_state.systematic_threshold(), + |_| { + let res = if cnt < group_size { Has::timeout() } else { Has::Yes }; + cnt += 1; + res + }, + true, + ) + .await; + + // Exhaust retries. + for _ in 0..(SYSTEMATIC_CHUNKS_REQ_RETRY_LIMIT - 1) { + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + group_size, + |_| Has::No, + true, + ) + .await; + } + + // Now, final chance is to try from a backer. + test_state + .test_chunk_requests( + &req_protocol_names, + test_state.candidate.hash(), + &mut virtual_overseer, + group_size, + |_| Has::Yes, + true, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + virtual_overseer + }); +} + +#[rstest] +#[case(true)] +#[case(false)] +fn test_legacy_network_protocol_with_mapping_disabled(#[case] systematic_recovery: bool) { + // In this case, when the mapping is disabled, recovery will work with both v2 and v1 requests, + // under the assumption that ValidatorIndex is always equal to ChunkIndex. However, systematic + // recovery will not be possible, it will fall back to regular recovery. + let test_state = TestState::with_empty_node_features(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_fast_path( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + + let candidate_hash = test_state.candidate.hash(); + + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + test_state + .test_chunk_requests_v1( + &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold() - 1, - |i| if i == 0 { panic!("requested from local validator") } else { Has::Yes }, + threshold, + |_| Has::Yes, + false, ) .await; + // Recovered data should match the original one. assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); virtual_overseer }); } +#[rstest] +#[case(true)] +#[case(false)] +fn test_legacy_network_protocol_with_mapping_enabled(#[case] systematic_recovery: bool) { + // In this case, when the mapping is enabled, we MUST only use v2. Recovery should fail for v1. + let test_state = TestState::default(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let (subsystem, threshold) = match systematic_recovery { + true => ( + with_systematic_chunks( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.systematic_threshold(), + ), + false => ( + with_fast_path( + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ), + test_state.threshold(), + ), + }; + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + + let candidate_hash = test_state.candidate.hash(); + + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + if systematic_recovery { + test_state + .test_chunk_requests_v1( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + threshold, + |_| Has::Yes, + systematic_recovery, + ) + .await; + + // Systematic recovery failed, trying regular recovery. + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + } + + test_state + .test_chunk_requests_v1( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.validators.len() - test_state.threshold(), + |_| Has::Yes, + false, + ) + .await; + + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + virtual_overseer + }); +} + #[test] -fn invalid_local_chunk_is_ignored() { +fn test_systematic_recovery_skipped_if_no_core_index() { let test_state = TestState::default(); let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let subsystem = AvailabilityRecoverySubsystem::with_chunks_only( + let subsystem = with_systematic_chunks( request_receiver(&req_protocol_names), + &req_protocol_names, Metrics::new_dummy(), ); @@ -1554,30 +3025,99 @@ fn invalid_local_chunk_is_ignored() { test_state.candidate.clone(), test_state.session_index, None, + None, tx, ), ) .await; - test_state.test_runtime_api(&mut virtual_overseer).await; + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + + let candidate_hash = test_state.candidate.hash(); + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + // Systematic recovery not possible without core index, falling back to regular recovery. test_state - .respond_to_query_all_request_invalid(&mut virtual_overseer, |i| i == 0) + .test_chunk_requests( + &req_protocol_names, + candidate_hash, + &mut virtual_overseer, + test_state.validators.len() - test_state.threshold(), + |_| Has::No, + false, + ) .await; + // Make it fail, in order to assert that indeed regular recovery was attempted. If it were + // systematic recovery, we would have had one more attempt for regular reconstruction. + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); + virtual_overseer + }); +} + +#[test] +fn test_systematic_recovery_skipped_if_mapping_disabled() { + let test_state = TestState::with_empty_node_features(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let subsystem = AvailabilityRecoverySubsystem::for_validator( + None, + request_receiver(&req_protocol_names), + &req_protocol_names, + Metrics::new_dummy(), + ); + + test_harness(subsystem, |mut virtual_overseer| async move { + overseer_signal( + &mut virtual_overseer, + OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( + test_state.current, + 1, + ))), + ) + .await; + + let (tx, rx) = oneshot::channel(); + + overseer_send( + &mut virtual_overseer, + AvailabilityRecoveryMessage::RecoverAvailableData( + test_state.candidate.clone(), + test_state.session_index, + None, + Some(test_state.core_index), + tx, + ), + ) + .await; + + test_state.test_runtime_api_session_info(&mut virtual_overseer).await; + + test_state.test_runtime_api_node_features(&mut virtual_overseer).await; + let candidate_hash = test_state.candidate.hash(); + test_state.respond_to_available_data_query(&mut virtual_overseer, false).await; + test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await; + + // Systematic recovery not possible without core index, falling back to regular recovery. test_state .test_chunk_requests( &req_protocol_names, candidate_hash, &mut virtual_overseer, - test_state.threshold() - 1, - |i| if i == 0 { panic!("requested from local validator") } else { Has::Yes }, + test_state.validators.len() - test_state.threshold(), + |_| Has::No, + false, ) .await; - assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data); + // Make it fail, in order to assert that indeed regular recovery was attempted. If it were + // systematic recovery, we would have had one more attempt for regular reconstruction. + assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable); virtual_overseer }); } diff --git a/polkadot/node/network/bridge/Cargo.toml b/polkadot/node/network/bridge/Cargo.toml index 9c2423e7e5810c3406ab4f40c219dbd8001245bb..b609fb1e071957868c4bff91e02ca5d110aae9ee 100644 --- a/polkadot/node/network/bridge/Cargo.toml +++ b/polkadot/node/network/bridge/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1.79" futures = "0.3.30" gum = { package = "tracing-gum", path = "../../gum" } polkadot-primitives = { path = "../../../primitives" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sc-network = { path = "../../../../substrate/client/network" } sp-consensus = { path = "../../../../substrate/primitives/consensus/common" } polkadot-node-metrics = { path = "../../metrics" } @@ -24,7 +24,7 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-overseer = { path = "../../overseer" } parking_lot = "0.12.1" bytes = "1" -fatality = "0.0.6" +fatality = "0.1.1" thiserror = { workspace = true } [dev-dependencies] diff --git a/polkadot/node/network/bridge/src/network.rs b/polkadot/node/network/bridge/src/network.rs index 5691c8413ad997daf80fcd551b4265031d563d88..17d6676b8430d8252cf5a8816a8117a80d0411df 100644 --- a/polkadot/node/network/bridge/src/network.rs +++ b/polkadot/node/network/bridge/src/network.rs @@ -177,7 +177,7 @@ fn send_message( // network used `Bytes` this would not be necessary. // // peer may have gotten disconnect by the time `send_message()` is called - // at which point the the sink is not available. + // at which point the sink is not available. let last_peer = peers.pop(); peers.into_iter().for_each(|peer| { if let Some(sink) = notification_sinks.get(&(peer_set, peer)) { diff --git a/polkadot/node/network/bridge/src/tx/mod.rs b/polkadot/node/network/bridge/src/tx/mod.rs index d5be6f01c33737a2b09bd39f40640d29c99ca94c..7b6dea748572ba1c24633b047227b92a9890c12c 100644 --- a/polkadot/node/network/bridge/src/tx/mod.rs +++ b/polkadot/node/network/bridge/src/tx/mod.rs @@ -301,7 +301,15 @@ where for req in reqs { match req { - Requests::ChunkFetchingV1(_) => metrics.on_message("chunk_fetching_v1"), + Requests::ChunkFetching(ref req) => { + // This is not the actual request that will succeed, as we don't know yet + // what that will be. It's only the primary request we tried. + if req.fallback_request.is_some() { + metrics.on_message("chunk_fetching_v2") + } else { + metrics.on_message("chunk_fetching_v1") + } + }, Requests::AvailableDataFetchingV1(_) => metrics.on_message("available_data_fetching_v1"), Requests::CollationFetchingV1(_) => metrics.on_message("collation_fetching_v1"), diff --git a/polkadot/node/network/collator-protocol/Cargo.toml b/polkadot/node/network/collator-protocol/Cargo.toml index 2c7135742f56890a7ad147e95c545cbebde04c9b..c02999a59b5a976748a7afe641b069851f6eb3c8 100644 --- a/polkadot/node/network/collator-protocol/Cargo.toml +++ b/polkadot/node/network/collator-protocol/Cargo.toml @@ -24,7 +24,7 @@ polkadot-node-network-protocol = { path = "../protocol" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-subsystem = { path = "../../subsystem" } -fatality = "0.0.6" +fatality = "0.1.1" thiserror = { workspace = true } tokio-util = "0.7.1" @@ -32,12 +32,13 @@ tokio-util = "0.7.1" log = { workspace = true, default-features = true } env_logger = "0.11" assert_matches = "1.4.0" +rstest = "0.18.2" sp-core = { path = "../../../../substrate/primitives/core", features = ["std"] } sp-keyring = { path = "../../../../substrate/primitives/keyring" } sc-keystore = { path = "../../../../substrate/client/keystore" } sc-network = { path = "../../../../substrate/client/network" } -parity-scale-codec = { version = "3.6.1", features = ["std"] } +parity-scale-codec = { version = "3.6.12", features = ["std"] } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index 879caf923285b3341a0bc28bc52371fb9c81ff69..88375d58309047286dd082759bfb063aa02e7304 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -261,10 +261,12 @@ struct State { /// `active_leaves`, the opposite doesn't hold true. /// /// Relay-chain blocks which don't support prospective parachains are - /// never included in the fragment trees of active leaves which do. In + /// never included in the fragment chains of active leaves which do. In /// particular, this means that if a given relay parent belongs to implicit /// ancestry of some active leaf, then it does support prospective parachains. - implicit_view: ImplicitView, + /// + /// It's `None` if the collator is not yet collating for a paraid. + implicit_view: Option, /// All active leaves observed by us, including both that do and do not /// support prospective parachains. This mapping works as a replacement for @@ -334,7 +336,7 @@ impl State { metrics, collating_on: Default::default(), peer_data: Default::default(), - implicit_view: Default::default(), + implicit_view: None, active_leaves: Default::default(), per_relay_parent: Default::default(), span_per_relay_parent: Default::default(), @@ -531,7 +533,7 @@ async fn distribute_collation( // Otherwise, it should be present in allowed ancestry of some leaf. // // It's collation-producer responsibility to verify that there exists - // a hypothetical membership in a fragment tree for candidate. + // a hypothetical membership in a fragment chain for the candidate. let interested = state .peer_data @@ -539,11 +541,12 @@ async fn distribute_collation( .filter(|(_, PeerData { view: v, .. })| match relay_parent_mode { ProspectiveParachainsMode::Disabled => v.contains(&candidate_relay_parent), ProspectiveParachainsMode::Enabled { .. } => v.iter().any(|block_hash| { - state - .implicit_view - .known_allowed_relay_parents_under(block_hash, Some(id)) - .unwrap_or_default() - .contains(&candidate_relay_parent) + state.implicit_view.as_ref().map(|implicit_view| { + implicit_view + .known_allowed_relay_parents_under(block_hash, Some(id)) + .unwrap_or_default() + .contains(&candidate_relay_parent) + }) == Some(true) }), }); @@ -830,6 +833,7 @@ async fn process_msg( match msg { CollateOn(id) => { state.collating_on = Some(id); + state.implicit_view = Some(ImplicitView::new(Some(id))); }, DistributeCollation { candidate_receipt, @@ -894,7 +898,7 @@ async fn process_msg( ); } }, - msg @ (ReportCollator(..) | Invalid(..) | Seconded(..) | Backed { .. }) => { + msg @ (ReportCollator(..) | Invalid(..) | Seconded(..)) => { gum::warn!( target: LOG_TARGET, "{:?} message is not expected on the collator side of the protocol", @@ -1215,7 +1219,10 @@ async fn handle_peer_view_change( Some(ProspectiveParachainsMode::Disabled) => std::slice::from_ref(&added), Some(ProspectiveParachainsMode::Enabled { .. }) => state .implicit_view - .known_allowed_relay_parents_under(&added, state.collating_on) + .as_ref() + .and_then(|implicit_view| { + implicit_view.known_allowed_relay_parents_under(&added, state.collating_on) + }) .unwrap_or_default(), None => { gum::trace!( @@ -1353,21 +1360,22 @@ where state.per_relay_parent.insert(*leaf, PerRelayParent::new(mode)); if mode.is_enabled() { - state - .implicit_view - .activate_leaf(sender, *leaf) - .await - .map_err(Error::ImplicitViewFetchError)?; + if let Some(ref mut implicit_view) = state.implicit_view { + implicit_view + .activate_leaf(sender, *leaf) + .await + .map_err(Error::ImplicitViewFetchError)?; - let allowed_ancestry = state - .implicit_view - .known_allowed_relay_parents_under(leaf, state.collating_on) - .unwrap_or_default(); - for block_hash in allowed_ancestry { - state - .per_relay_parent - .entry(*block_hash) - .or_insert_with(|| PerRelayParent::new(mode)); + let allowed_ancestry = implicit_view + .known_allowed_relay_parents_under(leaf, state.collating_on) + .unwrap_or_default(); + + for block_hash in allowed_ancestry { + state + .per_relay_parent + .entry(*block_hash) + .or_insert_with(|| PerRelayParent::new(mode)); + } } } } @@ -1378,7 +1386,11 @@ where // of implicit ancestry. Only update the state after the hash is actually // pruned from the block info storage. let pruned = if mode.is_enabled() { - state.implicit_view.deactivate_leaf(*leaf) + state + .implicit_view + .as_mut() + .map(|view| view.deactivate_leaf(*leaf)) + .unwrap_or_default() } else { vec![*leaf] }; diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs index 707053545630a0a11603ccda030200eed7b5cfe2..2a147aef69e2ff404f5270d9d3949ba533e766f8 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs @@ -18,7 +18,7 @@ use super::*; -use polkadot_node_subsystem::messages::{ChainApiMessage, ProspectiveParachainsMessage}; +use polkadot_node_subsystem::messages::ChainApiMessage; use polkadot_primitives::{AsyncBackingParams, Header, OccupiedCore}; const ASYNC_BACKING_PARAMETERS: AsyncBackingParams = @@ -31,7 +31,6 @@ fn get_parent_hash(hash: Hash) -> Hash { /// Handle a view update. async fn update_view( virtual_overseer: &mut VirtualOverseer, - test_state: &TestState, new_view: Vec<(Hash, u32)>, // Hash and block number. activated: u8, // How many new heads does this update contain? ) { @@ -61,21 +60,88 @@ async fn update_view( let min_number = leaf_number.saturating_sub(ASYNC_BACKING_PARAMETERS.allowed_ancestry_len); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx), - ) if parent == leaf_hash => { - tx.send(vec![(test_state.para_id, min_number)]).unwrap(); - } - ); - let ancestry_len = leaf_number + 1 - min_number; let ancestry_hashes = std::iter::successors(Some(leaf_hash), |h| Some(get_parent_hash(*h))) .take(ancestry_len as usize); let ancestry_numbers = (min_number..=leaf_number).rev(); let mut ancestry_iter = ancestry_hashes.clone().zip(ancestry_numbers).peekable(); + if let Some((hash, number)) = ancestry_iter.next() { + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::ChainApi(ChainApiMessage::BlockHeader(.., tx)) => { + let header = Header { + parent_hash: get_parent_hash(hash), + number, + state_root: Hash::zero(), + extrinsics_root: Hash::zero(), + digest: Default::default(), + }; + + tx.send(Ok(Some(header))).unwrap(); + } + ); + + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + .., + RuntimeApiRequest::AsyncBackingParams( + tx + ) + ) + ) => { + tx.send(Ok(ASYNC_BACKING_PARAMETERS)).unwrap(); + } + ); + + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + .., + RuntimeApiRequest::SessionIndexForChild( + tx + ) + ) + ) => { + tx.send(Ok(1)).unwrap(); + } + ); + + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::ChainApi( + ChainApiMessage::Ancestors { + k, + response_channel: tx, + .. + } + ) => { + assert_eq!(k, ASYNC_BACKING_PARAMETERS.allowed_ancestry_len as usize); + + tx.send(Ok(ancestry_hashes.clone().skip(1).into_iter().collect())).unwrap(); + } + ); + } + + for _ in ancestry_iter.clone() { + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + .., + RuntimeApiRequest::SessionIndexForChild( + tx + ) + ) + ) => { + tx.send(Ok(1)).unwrap(); + } + ); + } + while let Some((hash, number)) = ancestry_iter.next() { // May be `None` for the last element. let parent_hash = @@ -195,7 +261,7 @@ fn distribute_collation_from_implicit_view() { overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) .await; // Activated leaf is `b`, but the collation will be based on `c`. - update_view(virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; + update_view(virtual_overseer, vec![(head_b, head_b_num)], 1).await; let validator_peer_ids = test_state.current_group_validator_peer_ids(); for (val, peer) in test_state @@ -258,7 +324,7 @@ fn distribute_collation_from_implicit_view() { // Head `c` goes out of view. // Build a different candidate for this relay parent and attempt to distribute it. - update_view(virtual_overseer, &test_state, vec![(head_a, head_a_num)], 1).await; + update_view(virtual_overseer, vec![(head_a, head_a_num)], 1).await; let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; let parent_head_data_hash = Hash::repeat_byte(0xBB); @@ -318,7 +384,7 @@ fn distribute_collation_up_to_limit() { overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) .await; // Activated leaf is `a`, but the collation will be based on `b`. - update_view(virtual_overseer, &test_state, vec![(head_a, head_a_num)], 1).await; + update_view(virtual_overseer, vec![(head_a, head_a_num)], 1).await; for i in 0..(ASYNC_BACKING_PARAMETERS.max_candidate_depth + 1) { let pov = PoV { block_data: BlockData(vec![i as u8]) }; @@ -402,7 +468,7 @@ fn send_parent_head_data_for_elastic_scaling() { CollatorProtocolMessage::CollateOn(test_state.para_id), ) .await; - update_view(&mut virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; + update_view(&mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; let pov_data = PoV { block_data: BlockData(vec![1 as u8]) }; let candidate = TestCandidateBuilder { @@ -517,8 +583,8 @@ fn advertise_and_send_collation_by_hash() { CollatorProtocolMessage::CollateOn(test_state.para_id), ) .await; - update_view(&mut virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; - update_view(&mut virtual_overseer, &test_state, vec![(head_a, head_a_num)], 1).await; + update_view(&mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; + update_view(&mut virtual_overseer, vec![(head_a, head_a_num)], 1).await; let candidates: Vec<_> = (0..2) .map(|i| { @@ -638,7 +704,7 @@ fn advertise_core_occupied() { overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) .await; // Activated leaf is `a`, but the collation will be based on `b`. - update_view(virtual_overseer, &test_state, vec![(head_a, head_a_num)], 1).await; + update_view(virtual_overseer, vec![(head_a, head_a_num)], 1).await; let pov = PoV { block_data: BlockData(vec![1, 2, 3]) }; let candidate = TestCandidateBuilder { diff --git a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs index 8c3889a3554865c919f2eb33a8f86cce15317ff3..001df1fb3da9b24a3c1acffc049cc7433903aea8 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs @@ -121,19 +121,15 @@ impl PendingCollation { } } -/// v2 or v3 advertisement that was rejected by the backing -/// subsystem. Validator may fetch it later if its fragment -/// membership gets recognized before relay parent goes out of view. -#[derive(Debug, Clone)] -pub struct BlockedAdvertisement { - /// Peer that advertised the collation. - pub peer_id: PeerId, - /// Collator id. - pub collator_id: CollatorId, - /// The relay-parent of the candidate. - pub candidate_relay_parent: Hash, - /// Hash of the candidate. - pub candidate_hash: CandidateHash, +/// An identifier for a fetched collation that was blocked from being seconded because we don't have +/// access to the parent's HeadData. Can be retried once the candidate outputting this head data is +/// seconded. +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct BlockedCollationId { + /// Para id. + pub para_id: ParaId, + /// Hash of the parent head data. + pub parent_head_data_hash: Hash, } /// Performs a sanity check between advertised and fetched collations. diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index ac8c060827f5a4519cd8e4930d1447a8bf4cbe47..9f037a983e51c33cb734ee65fc496541d1082bf2 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -59,15 +59,17 @@ use polkadot_primitives::{ use crate::error::{Error, FetchError, Result, SecondingError}; +use self::collation::BlockedCollationId; + use super::{modify_reputation, tick_stream, LOG_TARGET}; mod collation; mod metrics; use collation::{ - fetched_collation_sanity_check, BlockedAdvertisement, CollationEvent, CollationFetchError, - CollationFetchRequest, CollationStatus, Collations, FetchedCollation, PendingCollation, - PendingCollationFetch, ProspectiveCandidate, + fetched_collation_sanity_check, CollationEvent, CollationFetchError, CollationFetchRequest, + CollationStatus, Collations, FetchedCollation, PendingCollation, PendingCollationFetch, + ProspectiveCandidate, }; #[cfg(test)] @@ -388,7 +390,7 @@ struct State { /// `active_leaves`, the opposite doesn't hold true. /// /// Relay-chain blocks which don't support prospective parachains are - /// never included in the fragment trees of active leaves which do. In + /// never included in the fragment chains of active leaves which do. In /// particular, this means that if a given relay parent belongs to implicit /// ancestry of some active leaf, then it does support prospective parachains. implicit_view: ImplicitView, @@ -421,14 +423,6 @@ struct State { /// Span per relay parent. span_per_relay_parent: HashMap, - /// Advertisements that were accepted as valid by collator protocol but rejected by backing. - /// - /// It's only legal to fetch collations that are either built on top of the root - /// of some fragment tree or have a parent node which represents backed candidate. - /// Otherwise, a validator will keep such advertisement in the memory and re-trigger - /// requests to backing on new backed candidates and activations. - blocked_advertisements: HashMap<(ParaId, Hash), Vec>, - /// When a timer in this `FuturesUnordered` triggers, we should dequeue the next request /// attempt in the corresponding `collations_per_relay_parent`. /// @@ -441,6 +435,12 @@ struct State { /// on validation. fetched_candidates: HashMap, + /// Collations which we haven't been able to second due to their parent not being known by + /// prospective-parachains. Mapped from the paraid and parent_head_hash to the fetched + /// collation data. Only needed for async backing. For elastic scaling, the fetched collation + /// must contain the full parent head data. + blocked_from_seconding: HashMap>, + /// Aggregated reputation change reputation: ReputationAggregator, } @@ -953,6 +953,8 @@ enum AdvertisementError { /// Advertisement is invalid. #[allow(dead_code)] Invalid(InsertAdvertisementError), + /// Seconding not allowed by backing subsystem + BlockedByBacking, } impl AdvertisementError { @@ -962,7 +964,7 @@ impl AdvertisementError { InvalidAssignment => Some(COST_WRONG_PARA), ProtocolMisuse => Some(COST_PROTOCOL_MISUSE), RelayParentUnknown | UndeclaredCollator | Invalid(_) => Some(COST_UNEXPECTED_MESSAGE), - UnknownPeer | SecondedLimitReached => None, + UnknownPeer | SecondedLimitReached | BlockedByBacking => None, } } } @@ -1001,57 +1003,55 @@ where }) } -/// Checks whether any of the advertisements are unblocked and attempts to fetch them. -async fn request_unblocked_collations(sender: &mut Sender, state: &mut State, blocked: I) -where - Sender: CollatorProtocolSenderTrait, - I: IntoIterator)>, -{ - let _timer = state.metrics.time_request_unblocked_collations(); +// Try seconding any collations which were waiting on the validation of their parent +#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)] +async fn second_unblocked_collations( + ctx: &mut Context, + state: &mut State, + para_id: ParaId, + head_data: HeadData, + head_data_hash: Hash, +) { + if let Some(unblocked_collations) = state + .blocked_from_seconding + .remove(&BlockedCollationId { para_id, parent_head_data_hash: head_data_hash }) + { + if !unblocked_collations.is_empty() { + gum::debug!( + target: LOG_TARGET, + "Candidate outputting head data with hash {} unblocked {} collations for seconding.", + head_data_hash, + unblocked_collations.len() + ); + } - for (key, mut value) in blocked { - let (para_id, para_head) = key; - let blocked = std::mem::take(&mut value); - for blocked in blocked { - let is_seconding_allowed = can_second( - sender, - para_id, - blocked.candidate_relay_parent, - blocked.candidate_hash, - para_head, - ) - .await; + for mut unblocked_collation in unblocked_collations { + unblocked_collation.maybe_parent_head_data = Some(head_data.clone()); + let peer_id = unblocked_collation.collation_event.pending_collation.peer_id; + let relay_parent = unblocked_collation.candidate_receipt.descriptor.relay_parent; - if is_seconding_allowed { - let result = enqueue_collation( - sender, - state, - blocked.candidate_relay_parent, - para_id, - blocked.peer_id, - blocked.collator_id, - Some((blocked.candidate_hash, para_head)), - ) - .await; - if let Err(fetch_error) = result { - gum::debug!( - target: LOG_TARGET, - relay_parent = ?blocked.candidate_relay_parent, - para_id = ?para_id, - peer_id = ?blocked.peer_id, - error = %fetch_error, - "Failed to request unblocked collation", - ); + if let Err(err) = kick_off_seconding(ctx, state, unblocked_collation).await { + gum::warn!( + target: LOG_TARGET, + ?relay_parent, + ?para_id, + ?peer_id, + error = %err, + "Seconding aborted due to an error", + ); + + if err.is_malicious() { + // Report malicious peer. + modify_reputation( + &mut state.reputation, + ctx.sender(), + peer_id, + COST_REPORT_BAD, + ) + .await; } - } else { - // Keep the advertisement. - value.push(blocked); } } - - if !value.is_empty() { - state.blocked_advertisements.insert(key, value); - } } } @@ -1110,10 +1110,10 @@ where } if let Some((candidate_hash, parent_head_data_hash)) = prospective_candidate { - // We need to queue the advertisement if we are not allowed to second it. + // Check if backing subsystem allows to second this candidate. // - // This is also only important when async backing is enabled. - let queue_advertisement = relay_parent_mode.is_enabled() && + // This is also only important when async backing or elastic scaling is enabled. + let seconding_not_allowed = relay_parent_mode.is_enabled() && !can_second( sender, collator_para_id, @@ -1123,26 +1123,8 @@ where ) .await; - if queue_advertisement { - gum::debug!( - target: LOG_TARGET, - relay_parent = ?relay_parent, - para_id = ?para_id, - ?candidate_hash, - "Seconding is not allowed by backing, queueing advertisement", - ); - state - .blocked_advertisements - .entry((collator_para_id, parent_head_data_hash)) - .or_default() - .push(BlockedAdvertisement { - peer_id, - collator_id: collator_id.clone(), - candidate_relay_parent: relay_parent, - candidate_hash, - }); - - return Ok(()) + if seconding_not_allowed { + return Err(AdvertisementError::BlockedByBacking) } } @@ -1358,20 +1340,17 @@ where state.span_per_relay_parent.remove(&removed); } } - // Remove blocked advertisements that left the view. - state.blocked_advertisements.retain(|_, ads| { - ads.retain(|ad| state.per_relay_parent.contains_key(&ad.candidate_relay_parent)); - !ads.is_empty() + // Remove blocked seconding requests that left the view. + state.blocked_from_seconding.retain(|_, collations| { + collations.retain(|collation| { + state + .per_relay_parent + .contains_key(&collation.candidate_receipt.descriptor.relay_parent) + }); + + !collations.is_empty() }); - // Re-trigger previously failed requests again. - // - // This makes sense for several reasons, one simple example: if a hypothetical depth - // for an advertisement initially exceeded the limit and the candidate was included - // in a new leaf. - let maybe_unblocked = std::mem::take(&mut state.blocked_advertisements); - // Could be optimized to only sanity check new leaves. - request_unblocked_collations(sender, state, maybe_unblocked).await; for (peer_id, peer_data) in state.peer_data.iter_mut() { peer_data.prune_old_advertisements( @@ -1508,6 +1487,8 @@ async fn process_msg( return }, }; + let output_head_data = receipt.commitments.head_data.clone(); + let output_head_data_hash = receipt.descriptor.para_head; let fetched_collation = FetchedCollation::from(&receipt.to_plain()); if let Some(CollationEvent { collator_id, pending_collation, .. }) = state.fetched_candidates.remove(&fetched_collation) @@ -1536,6 +1517,17 @@ async fn process_msg( rp_state.collations.status = CollationStatus::Seconded; rp_state.collations.note_seconded(); } + + // See if we've unblocked other collations for seconding. + second_unblocked_collations( + ctx, + state, + fetched_collation.para_id, + output_head_data, + output_head_data_hash, + ) + .await; + // If async backing is enabled, make an attempt to fetch next collation. let maybe_candidate_hash = prospective_candidate.as_ref().map(ProspectiveCandidate::candidate_hash); @@ -1554,11 +1546,13 @@ async fn process_msg( ); } }, - Backed { para_id, para_head } => { - let maybe_unblocked = state.blocked_advertisements.remove_entry(&(para_id, para_head)); - request_unblocked_collations(ctx.sender(), state, maybe_unblocked).await; - }, Invalid(parent, candidate_receipt) => { + // Remove collations which were blocked from seconding and had this candidate as parent. + state.blocked_from_seconding.remove(&BlockedCollationId { + para_id: candidate_receipt.descriptor.para_id, + parent_head_data_hash: candidate_receipt.descriptor.para_head, + }); + let fetched_collation = FetchedCollation::from(&candidate_receipt); let candidate_hash = fetched_collation.candidate_hash; let id = match state.fetched_candidates.entry(fetched_collation) { @@ -1668,29 +1662,45 @@ async fn run_inner( }; let CollationEvent {collator_id, pending_collation, .. } = res.collation_event.clone(); - if let Err(err) = kick_off_seconding(&mut ctx, &mut state, res).await { - gum::warn!( - target: LOG_TARGET, - relay_parent = ?pending_collation.relay_parent, - para_id = ?pending_collation.para_id, - peer_id = ?pending_collation.peer_id, - error = %err, - "Seconding aborted due to an error", - ); - if err.is_malicious() { - // Report malicious peer. - modify_reputation(&mut state.reputation, ctx.sender(), pending_collation.peer_id, COST_REPORT_BAD).await; + match kick_off_seconding(&mut ctx, &mut state, res).await { + Err(err) => { + gum::warn!( + target: LOG_TARGET, + relay_parent = ?pending_collation.relay_parent, + para_id = ?pending_collation.para_id, + peer_id = ?pending_collation.peer_id, + error = %err, + "Seconding aborted due to an error", + ); + + if err.is_malicious() { + // Report malicious peer. + modify_reputation(&mut state.reputation, ctx.sender(), pending_collation.peer_id, COST_REPORT_BAD).await; + } + let maybe_candidate_hash = + pending_collation.prospective_candidate.as_ref().map(ProspectiveCandidate::candidate_hash); + dequeue_next_collation_and_fetch( + &mut ctx, + &mut state, + pending_collation.relay_parent, + (collator_id, maybe_candidate_hash), + ) + .await; + }, + Ok(false) => { + // No hard error occurred, but we can try fetching another collation. + let maybe_candidate_hash = + pending_collation.prospective_candidate.as_ref().map(ProspectiveCandidate::candidate_hash); + dequeue_next_collation_and_fetch( + &mut ctx, + &mut state, + pending_collation.relay_parent, + (collator_id, maybe_candidate_hash), + ) + .await; } - let maybe_candidate_hash = - pending_collation.prospective_candidate.as_ref().map(ProspectiveCandidate::candidate_hash); - dequeue_next_collation_and_fetch( - &mut ctx, - &mut state, - pending_collation.relay_parent, - (collator_id, maybe_candidate_hash), - ) - .await; + Ok(true) => {} } } res = state.collation_fetch_timeouts.select_next_some() => { @@ -1800,12 +1810,13 @@ where } /// Handle a fetched collation result. +/// Returns whether or not seconding has begun. #[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)] async fn kick_off_seconding( ctx: &mut Context, state: &mut State, PendingCollationFetch { mut collation_event, candidate_receipt, pov, maybe_parent_head_data }: PendingCollationFetch, -) -> std::result::Result<(), SecondingError> { +) -> std::result::Result { let pending_collation = collation_event.pending_collation; let relay_parent = pending_collation.relay_parent; @@ -1818,7 +1829,7 @@ async fn kick_off_seconding( relay_parent = ?relay_parent, "Fetched collation for a parent out of view", ); - return Ok(()) + return Ok(false) }, }; let collations = &mut per_relay_parent.collations; @@ -1828,7 +1839,7 @@ async fn kick_off_seconding( collation_event.pending_collation.commitments_hash = Some(candidate_receipt.commitments_hash); - let (maybe_pvd, maybe_parent_head_and_hash) = match ( + let (maybe_pvd, maybe_parent_head, maybe_parent_head_hash) = match ( collation_event.collator_protocol_version, collation_event.pending_collation.prospective_candidate, ) { @@ -1844,7 +1855,7 @@ async fn kick_off_seconding( ) .await?; - (pvd, maybe_parent_head_data.map(|head_data| (head_data, parent_head_data_hash))) + (pvd, maybe_parent_head_data, Some(parent_head_data_hash)) }, // Support V2 collators without async backing enabled. (CollationVersion::V2, Some(_)) | (CollationVersion::V1, _) => { @@ -1854,20 +1865,60 @@ async fn kick_off_seconding( candidate_receipt.descriptor().para_id, ) .await?; - (pvd, None) + ( + Some(pvd.ok_or(SecondingError::PersistedValidationDataNotFound)?), + maybe_parent_head_data, + None, + ) }, _ => { // `handle_advertisement` checks for protocol mismatch. - return Ok(()) + return Ok(false) + }, + }; + + let pvd = match (maybe_pvd, maybe_parent_head.clone(), maybe_parent_head_hash) { + (Some(pvd), _, _) => pvd, + (None, None, Some(parent_head_data_hash)) => { + // In this case, the collator did not supply the head data and neither could + // prospective-parachains. We add this to the blocked_from_seconding collection + // until we second its parent. + let blocked_collation = PendingCollationFetch { + collation_event, + candidate_receipt, + pov, + maybe_parent_head_data: None, + }; + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?blocked_collation.candidate_receipt.hash(), + relay_parent = ?blocked_collation.candidate_receipt.descriptor.relay_parent, + "Collation having parent head data hash {} is blocked from seconding. Waiting on its parent to be validated.", + parent_head_data_hash + ); + state + .blocked_from_seconding + .entry(BlockedCollationId { + para_id: blocked_collation.candidate_receipt.descriptor.para_id, + parent_head_data_hash, + }) + .or_insert_with(Vec::new) + .push(blocked_collation); + + return Ok(false) + }, + (None, _, _) => { + // Even though we already have the parent head data, the pvd fetching failed. We + // don't need to wait for seconding another collation outputting this head data. + return Err(SecondingError::PersistedValidationDataNotFound) }, }; - let pvd = maybe_pvd.ok_or(SecondingError::PersistedValidationDataNotFound)?; fetched_collation_sanity_check( &collation_event.pending_collation, &candidate_receipt, &pvd, - maybe_parent_head_and_hash, + maybe_parent_head.and_then(|head| maybe_parent_head_hash.map(|hash| (head, hash))), )?; ctx.send_message(CandidateBackingMessage::Second( @@ -1882,7 +1933,7 @@ async fn kick_off_seconding( collations.status = CollationStatus::WaitingOnValidation; entry.insert(collation_event); - Ok(()) + Ok(true) } else { Err(SecondingError::Duplicate) } diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs index eaa725f2642ed38e3a6f222f9624dd6e2bc4fcce..178dcb85e035f05c4136f7d7d7e2433a3713d00c 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs @@ -23,6 +23,7 @@ use polkadot_primitives::{ AsyncBackingParams, BlockNumber, CandidateCommitments, CommittedCandidateReceipt, Header, SigningContext, ValidatorId, }; +use rstest::rstest; const ASYNC_BACKING_PARAMETERS: AsyncBackingParams = AsyncBackingParams { max_candidate_depth: 4, allowed_ancestry_len: 3 }; @@ -115,15 +116,6 @@ pub(super) async fn update_view( let min_number = leaf_number.saturating_sub(ASYNC_BACKING_PARAMETERS.allowed_ancestry_len); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx), - ) if parent == leaf_hash => { - tx.send(test_state.chain_ids.iter().map(|para_id| (*para_id, min_number)).collect()).unwrap(); - } - ); - let ancestry_len = leaf_number + 1 - min_number; let ancestry_hashes = std::iter::successors(Some(leaf_hash), |h| Some(get_parent_hash(*h))) .take(ancestry_len as usize); @@ -165,6 +157,17 @@ pub(super) async fn update_view( } ); + if requested_len == 0 { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx), + ) if parent == leaf_hash => { + tx.send(test_state.chain_ids.iter().map(|para_id| (*para_id, min_number)).collect()).unwrap(); + } + ); + } + requested_len += 1; } } @@ -262,6 +265,48 @@ async fn assert_collation_seconded( } } +/// Assert that the next message is a persisted validation data request and respond with the +/// supplied PVD. +async fn assert_persisted_validation_data( + virtual_overseer: &mut VirtualOverseer, + version: CollationVersion, + expected_relay_parent: Hash, + expected_para_id: ParaId, + expected_parent_head_data_hash: Option, + pvd: Option, +) { + // Depending on relay parent mode pvd will be either requested + // from the Runtime API or Prospective Parachains. + let msg = overseer_recv(virtual_overseer).await; + match version { + CollationVersion::V1 => assert_matches!( + msg, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::PersistedValidationData(para_id, assumption, tx), + )) => { + assert_eq!(expected_relay_parent, hash); + assert_eq!(expected_para_id, para_id); + assert_eq!(OccupiedCoreAssumption::Free, assumption); + tx.send(Ok(pvd)).unwrap(); + } + ), + CollationVersion::V2 => assert_matches!( + msg, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::GetProspectiveValidationData(request, tx), + ) => { + assert_eq!(expected_relay_parent, request.candidate_relay_parent); + assert_eq!(expected_para_id, request.para_id); + if let Some(expected_parent_head_data_hash) = expected_parent_head_data_hash { + assert_eq!(expected_parent_head_data_hash, request.parent_head_data.hash()); + } + tx.send(pvd).unwrap(); + } + ), + } +} + #[test] fn v1_advertisement_accepted_and_seconded() { let test_state = TestState::default(); @@ -946,56 +991,73 @@ fn advertisement_spam_protection() { }); } -#[test] -fn backed_candidate_unblocks_advertisements() { +#[rstest] +#[case(true)] +#[case(false)] +fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { let test_state = TestState::default(); test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { - let TestHarness { mut virtual_overseer, .. } = test_harness; + let TestHarness { mut virtual_overseer, keystore } = test_harness; - let pair_a = CollatorPair::generate().0; - let pair_b = CollatorPair::generate().0; + let pair = CollatorPair::generate().0; + // Grandparent of head `a`. let head_b = Hash::from_low_u64_be(128); let head_b_num: u32 = 2; - let head_c = get_parent_hash(head_b); // Grandparent of head `b`. - // Group rotation frequency is 1 by default, at `d` we're assigned + // Group rotation frequency is 1 by default, at `c` we're assigned // to the first para. - let head_d = get_parent_hash(head_c); + let head_c = Hash::from_low_u64_be(130); // Activated leaf is `b`, but the collation will be based on `c`. update_view(&mut virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - // Accept both collators from the implicit view. connect_and_declare_collator( &mut virtual_overseer, peer_a, - pair_a.clone(), + pair.clone(), test_state.chain_ids[0], CollationVersion::V2, ) .await; - connect_and_declare_collator( - &mut virtual_overseer, - peer_b, - pair_b.clone(), - test_state.chain_ids[1], - CollationVersion::V2, - ) - .await; - let candidate_hash = CandidateHash::default(); - let parent_head_data_hash = Hash::zero(); + // Candidate A transitions from head data 0 to 1. + // Candidate B transitions from head data 1 to 2. + + // Candidate B is advertised and fetched before candidate A. + + let mut candidate_b = dummy_candidate_receipt_bad_sig(head_c, Some(Default::default())); + candidate_b.descriptor.para_id = test_state.chain_ids[0]; + candidate_b.descriptor.para_head = HeadData(vec![2]).hash(); + candidate_b.descriptor.persisted_validation_data_hash = + PersistedValidationData:: { + parent_head: HeadData(vec![1]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + } + .hash(); + let candidate_b_commitments = CandidateCommitments { + head_data: HeadData(vec![2]), + horizontal_messages: Default::default(), + upward_messages: Default::default(), + new_validation_code: None, + processed_downward_messages: 0, + hrmp_watermark: 0, + }; + candidate_b.commitments_hash = candidate_b_commitments.hash(); + + let candidate_b_hash = candidate_b.hash(); + advertise_collation( &mut virtual_overseer, - peer_b, + peer_a, head_c, - Some((candidate_hash, parent_head_data_hash)), + Some((candidate_b_hash, HeadData(vec![1]).hash())), ) .await; assert_matches!( @@ -1003,40 +1065,73 @@ fn backed_candidate_unblocks_advertisements() { AllMessages::CandidateBacking( CandidateBackingMessage::CanSecond(request, tx), ) => { - assert_eq!(request.candidate_hash, candidate_hash); - assert_eq!(request.candidate_para_id, test_state.chain_ids[1]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); - // Reject it. - tx.send(false).expect("receiving side should be alive"); + assert_eq!(request.candidate_hash, candidate_b_hash); + assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); + assert_eq!(request.parent_head_data_hash, HeadData(vec![1]).hash()); + tx.send(true).expect("receiving side should be alive"); } ); - // Advertise with different para. - advertise_collation( + let response_channel = assert_fetch_collation_request( &mut virtual_overseer, - peer_a, - head_d, // Note different relay parent. - Some((candidate_hash, parent_head_data_hash)), + head_c, + test_state.chain_ids[0], + Some(candidate_b_hash), ) .await; - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidate_hash); - assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); - tx.send(false).expect("receiving side should be alive"); + + response_channel + .send(Ok(( + request_v2::CollationFetchingResponse::Collation( + candidate_b.clone(), + PoV { block_data: BlockData(vec![1]) }, + ) + .encode(), + ProtocolName::from(""), + ))) + .expect("Sending response should succeed"); + + // Persisted validation data of candidate B is not found. + assert_persisted_validation_data( + &mut virtual_overseer, + CollationVersion::V2, + head_c, + test_state.chain_ids[0], + Some(HeadData(vec![1]).hash()), + None, + ) + .await; + + // Now advertise, fetch and validate candidate A, which is the parent of B. + + let mut candidate_a = dummy_candidate_receipt_bad_sig(head_c, Some(Default::default())); + candidate_a.descriptor.para_id = test_state.chain_ids[0]; + candidate_a.descriptor.para_head = HeadData(vec![1]).hash(); + candidate_a.descriptor.persisted_validation_data_hash = + PersistedValidationData:: { + parent_head: HeadData(vec![0]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), } - ); + .hash(); + let candidate_a_commitments = CandidateCommitments { + head_data: HeadData(vec![1]), + horizontal_messages: Default::default(), + upward_messages: Default::default(), + new_validation_code: None, + processed_downward_messages: 0, + hrmp_watermark: 0, + }; + candidate_a.commitments_hash = candidate_a_commitments.hash(); + + let candidate_a_hash = candidate_a.hash(); - overseer_send( + advertise_collation( &mut virtual_overseer, - CollatorProtocolMessage::Backed { - para_id: test_state.chain_ids[0], - para_head: parent_head_data_hash, - }, + peer_a, + head_c, + Some((candidate_a_hash, HeadData(vec![0]).hash())), ) .await; assert_matches!( @@ -1044,174 +1139,155 @@ fn backed_candidate_unblocks_advertisements() { AllMessages::CandidateBacking( CandidateBackingMessage::CanSecond(request, tx), ) => { - assert_eq!(request.candidate_hash, candidate_hash); + assert_eq!(request.candidate_hash, candidate_a_hash); assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); + assert_eq!(request.parent_head_data_hash, HeadData(vec![0]).hash()); tx.send(true).expect("receiving side should be alive"); } ); - assert_fetch_collation_request( + + let response_channel = assert_fetch_collation_request( &mut virtual_overseer, - head_d, + head_c, test_state.chain_ids[0], - Some(candidate_hash), + Some(candidate_a_hash), ) .await; - virtual_overseer - }); -} -#[test] -fn active_leave_unblocks_advertisements() { - let mut test_state = TestState::default(); - test_state.group_rotation_info.group_rotation_frequency = 100; + response_channel + .send(Ok(( + request_v2::CollationFetchingResponse::Collation( + candidate_a.clone(), + PoV { block_data: BlockData(vec![2]) }, + ) + .encode(), + ProtocolName::from(""), + ))) + .expect("Sending response should succeed"); - test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { - let TestHarness { mut virtual_overseer, .. } = test_harness; + assert_persisted_validation_data( + &mut virtual_overseer, + CollationVersion::V2, + head_c, + test_state.chain_ids[0], + Some(HeadData(vec![0]).hash()), + Some(PersistedValidationData:: { + parent_head: HeadData(vec![0]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }), + ) + .await; - let head_b = Hash::from_low_u64_be(128); - let head_b_num: u32 = 0; + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateBacking(CandidateBackingMessage::Second( + relay_parent, + candidate_receipt, + received_pvd, + incoming_pov, + )) => { + assert_eq!(head_c, relay_parent); + assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id); + assert_eq!(PoV { block_data: BlockData(vec![2]) }, incoming_pov); + assert_eq!(PersistedValidationData:: { + parent_head: HeadData(vec![0]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }, received_pvd); + candidate_receipt + } + ); - update_view(&mut virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; + // If candidate A is valid, proceed with seconding B. + if valid_parent { + send_seconded_statement( + &mut virtual_overseer, + keystore.clone(), + &CommittedCandidateReceipt { + descriptor: candidate_a.descriptor, + commitments: candidate_a_commitments, + }, + ) + .await; - let peers: Vec = (0..3).map(|_| CollatorPair::generate().0).collect(); - let peer_ids: Vec = (0..3).map(|_| PeerId::random()).collect(); - let candidates: Vec = - (0u8..3).map(|i| CandidateHash(Hash::repeat_byte(i))).collect(); + assert_collation_seconded(&mut virtual_overseer, head_c, peer_a, CollationVersion::V2) + .await; - for (peer, peer_id) in peers.iter().zip(&peer_ids) { - connect_and_declare_collator( + // Now that candidate A has been seconded, candidate B can be seconded as well. + + assert_persisted_validation_data( &mut virtual_overseer, - *peer_id, - peer.clone(), - test_state.chain_ids[0], CollationVersion::V2, + head_c, + test_state.chain_ids[0], + Some(HeadData(vec![1]).hash()), + Some(PersistedValidationData:: { + parent_head: HeadData(vec![1]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }), ) .await; - } - let parent_head_data_hash = Hash::zero(); - for (peer, candidate) in peer_ids.iter().zip(&candidates).take(2) { - advertise_collation( + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateBacking(CandidateBackingMessage::Second( + relay_parent, + candidate_receipt, + received_pvd, + incoming_pov, + )) => { + assert_eq!(head_c, relay_parent); + assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id); + assert_eq!(PoV { block_data: BlockData(vec![1]) }, incoming_pov); + assert_eq!(PersistedValidationData:: { + parent_head: HeadData(vec![1]), + relay_parent_number: 5, + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }, received_pvd); + candidate_receipt + } + ); + + send_seconded_statement( + &mut virtual_overseer, + keystore.clone(), + &CommittedCandidateReceipt { + descriptor: candidate_b.descriptor, + commitments: candidate_b_commitments, + }, + ) + .await; + + assert_collation_seconded(&mut virtual_overseer, head_c, peer_a, CollationVersion::V2) + .await; + } else { + // If candidate A is invalid, B won't be seconded. + overseer_send( &mut virtual_overseer, - *peer, - head_b, - Some((*candidate, parent_head_data_hash)), + CollatorProtocolMessage::Invalid(head_c, candidate_a), ) .await; assert_matches!( overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), + AllMessages::NetworkBridgeTx( + NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(peer, rep)), ) => { - assert_eq!(request.candidate_hash, *candidate); - assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); - // Send false. - tx.send(false).expect("receiving side should be alive"); + assert_eq!(peer, peer_a); + assert_eq!(rep.value, COST_REPORT_BAD.cost_or_benefit()); } ); } - let head_c = Hash::from_low_u64_be(127); - let head_c_num: u32 = 1; - - let next_overseer_message = - update_view(&mut virtual_overseer, &test_state, vec![(head_c, head_c_num)], 1) - .await - .expect("should've sent request to backing"); - - // Unblock first request. - assert_matches!( - next_overseer_message, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidates[0]); - assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); - tx.send(true).expect("receiving side should be alive"); - } - ); - - assert_fetch_collation_request( - &mut virtual_overseer, - head_b, - test_state.chain_ids[0], - Some(candidates[0]), - ) - .await; - - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidates[1]); - assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); - assert_eq!(request.parent_head_data_hash, parent_head_data_hash); - tx.send(false).expect("receiving side should be alive"); - } - ); - - // Collation request was discarded. test_helpers::Yield::new().await; assert_matches!(virtual_overseer.recv().now_or_never(), None); - advertise_collation( - &mut virtual_overseer, - peer_ids[2], - head_c, - Some((candidates[2], parent_head_data_hash)), - ) - .await; - - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidates[2]); - tx.send(false).expect("receiving side should be alive"); - } - ); - - let head_d = Hash::from_low_u64_be(126); - let head_d_num: u32 = 2; - - let next_overseer_message = - update_view(&mut virtual_overseer, &test_state, vec![(head_d, head_d_num)], 1) - .await - .expect("should've sent request to backing"); - - // Reject 2, accept 3. - assert_matches!( - next_overseer_message, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidates[1]); - tx.send(false).expect("receiving side should be alive"); - } - ); - assert_matches!( - overseer_recv(&mut virtual_overseer).await, - AllMessages::CandidateBacking( - CandidateBackingMessage::CanSecond(request, tx), - ) => { - assert_eq!(request.candidate_hash, candidates[2]); - tx.send(true).expect("receiving side should be alive"); - } - ); - assert_fetch_collation_request( - &mut virtual_overseer, - head_c, - test_state.chain_ids[0], - Some(candidates[2]), - ) - .await; - virtual_overseer }); } diff --git a/polkadot/node/network/dispute-distribution/Cargo.toml b/polkadot/node/network/dispute-distribution/Cargo.toml index ff9c302c73146d501114728c4a483e4465d199a9..dff285590d97cd4f47a00a6141b5c8a07315e35e 100644 --- a/polkadot/node/network/dispute-distribution/Cargo.toml +++ b/polkadot/node/network/dispute-distribution/Cargo.toml @@ -14,7 +14,7 @@ futures = "0.3.30" futures-timer = "3.0.2" gum = { package = "tracing-gum", path = "../../gum" } derive_more = "0.99.17" -parity-scale-codec = { version = "3.6.1", features = ["std"] } +parity-scale-codec = { version = "3.6.12", features = ["std"] } polkadot-primitives = { path = "../../../primitives" } polkadot-erasure-coding = { path = "../../../erasure-coding" } polkadot-node-subsystem = { path = "../../subsystem" } @@ -25,7 +25,7 @@ sc-network = { path = "../../../../substrate/client/network" } sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto" } sp-keystore = { path = "../../../../substrate/primitives/keystore" } thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" schnellru = "0.2.1" indexmap = "2.0.0" diff --git a/polkadot/node/network/dispute-distribution/src/receiver/mod.rs b/polkadot/node/network/dispute-distribution/src/receiver/mod.rs index 2b3fc45983a98f67954a16fd342d76ac8068ae07..2409e6994f604ecfa905c5300fe7d59c6d9974fa 100644 --- a/polkadot/node/network/dispute-distribution/src/receiver/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/receiver/mod.rs @@ -132,7 +132,7 @@ enum MuxedMessage { /// A new request has arrived and should be handled. NewRequest(IncomingRequest), - /// Rate limit timer hit - is is time to process one row of messages. + /// Rate limit timer hit - is time to process one row of messages. /// /// This is the result of calling `self.peer_queues.pop_reqs()`. WakePeerQueuesPopReqs(Vec>), diff --git a/polkadot/node/network/protocol/Cargo.toml b/polkadot/node/network/protocol/Cargo.toml index 0408e673791114793da1b231baa7448f185b0db6..c5015b8c64504b2712c9713463ab78af2f265948 100644 --- a/polkadot/node/network/protocol/Cargo.toml +++ b/polkadot/node/network/protocol/Cargo.toml @@ -16,7 +16,7 @@ hex = "0.4.3" polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-jaeger = { path = "../../jaeger" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sc-network = { path = "../../../../substrate/client/network" } sc-network-types = { path = "../../../../substrate/client/network/types" } sc-authority-discovery = { path = "../../../../substrate/client/authority-discovery" } @@ -24,7 +24,7 @@ sp-runtime = { path = "../../../../substrate/primitives/runtime" } strum = { version = "0.26.2", features = ["derive"] } futures = "0.3.30" thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" rand = "0.8" derive_more = "0.99" gum = { package = "tracing-gum", path = "../../gum" } diff --git a/polkadot/node/network/protocol/src/request_response/mod.rs b/polkadot/node/network/protocol/src/request_response/mod.rs index cab02bb88a00b429a80ce25e342fd38e25b3f3d5..fe06593bd7a0f58202471483cc06980ee35a2926 100644 --- a/polkadot/node/network/protocol/src/request_response/mod.rs +++ b/polkadot/node/network/protocol/src/request_response/mod.rs @@ -98,6 +98,10 @@ pub enum Protocol { /// Protocol for requesting candidates with attestations in statement distribution /// when async backing is enabled. AttestedCandidateV2, + + /// Protocol for chunk fetching version 2, used by availability distribution and availability + /// recovery. + ChunkFetchingV2, } /// Minimum bandwidth we expect for validators - 500Mbit/s is the recommendation, so approximately @@ -209,7 +213,7 @@ impl Protocol { let name = req_protocol_names.get_name(self); let legacy_names = self.get_legacy_name().into_iter().map(Into::into).collect(); match self { - Protocol::ChunkFetchingV1 => N::request_response_config( + Protocol::ChunkFetchingV1 | Protocol::ChunkFetchingV2 => N::request_response_config( name, legacy_names, 1_000, @@ -292,7 +296,7 @@ impl Protocol { // times (due to network delays), 100 seems big enough to accommodate for "bursts", // assuming we can service requests relatively quickly, which would need to be measured // as well. - Protocol::ChunkFetchingV1 => 100, + Protocol::ChunkFetchingV1 | Protocol::ChunkFetchingV2 => 100, // 10 seems reasonable, considering group sizes of max 10 validators. Protocol::CollationFetchingV1 | Protocol::CollationFetchingV2 => 10, // 10 seems reasonable, considering group sizes of max 10 validators. @@ -362,6 +366,7 @@ impl Protocol { // Introduced after legacy names became legacy. Protocol::AttestedCandidateV2 => None, Protocol::CollationFetchingV2 => None, + Protocol::ChunkFetchingV2 => None, } } } @@ -412,6 +417,7 @@ impl ReqProtocolNames { }; let short_name = match protocol { + // V1: Protocol::ChunkFetchingV1 => "/req_chunk/1", Protocol::CollationFetchingV1 => "/req_collation/1", Protocol::PoVFetchingV1 => "/req_pov/1", @@ -419,8 +425,10 @@ impl ReqProtocolNames { Protocol::StatementFetchingV1 => "/req_statement/1", Protocol::DisputeSendingV1 => "/send_dispute/1", + // V2: Protocol::CollationFetchingV2 => "/req_collation/2", Protocol::AttestedCandidateV2 => "/req_attested_candidate/2", + Protocol::ChunkFetchingV2 => "/req_chunk/2", }; format!("{}{}", prefix, short_name).into() diff --git a/polkadot/node/network/protocol/src/request_response/outgoing.rs b/polkadot/node/network/protocol/src/request_response/outgoing.rs index 96ef4a6ab25dcc13949e6b3dfbc0e8c6856393f5..f578c4ffded34b7ee20a1398925e34b0c7a02bc3 100644 --- a/polkadot/node/network/protocol/src/request_response/outgoing.rs +++ b/polkadot/node/network/protocol/src/request_response/outgoing.rs @@ -30,7 +30,7 @@ use super::{v1, v2, IsRequest, Protocol}; #[derive(Debug)] pub enum Requests { /// Request an availability chunk from a node. - ChunkFetchingV1(OutgoingRequest), + ChunkFetching(OutgoingRequest), /// Fetch a collation from a collator which previously announced it. CollationFetchingV1(OutgoingRequest), /// Fetch a PoV from a validator which previously sent out a seconded statement. @@ -59,7 +59,7 @@ impl Requests { /// contained in the `enum`. pub fn encode_request(self) -> (Protocol, OutgoingRequest>) { match self { - Self::ChunkFetchingV1(r) => r.encode_request(), + Self::ChunkFetching(r) => r.encode_request(), Self::CollationFetchingV1(r) => r.encode_request(), Self::CollationFetchingV2(r) => r.encode_request(), Self::PoVFetchingV1(r) => r.encode_request(), @@ -164,24 +164,20 @@ where /// /// Returns a raw `Vec` response over the channel. Use the associated `ProtocolName` to know /// which request was the successful one and appropriately decode the response. - // WARNING: This is commented for now because it's not used yet. - // If you need it, make sure to test it. You may need to enable the V1 substream upgrade - // protocol, unless libp2p was in the meantime updated to a version that fixes the problem - // described in https://github.com/libp2p/rust-libp2p/issues/5074 - // pub fn new_with_fallback( - // peer: Recipient, - // payload: Req, - // fallback_request: FallbackReq, - // ) -> (Self, impl Future, ProtocolName)>>) { - // let (tx, rx) = oneshot::channel(); - // let r = Self { - // peer, - // payload, - // pending_response: tx, - // fallback_request: Some((fallback_request, FallbackReq::PROTOCOL)), - // }; - // (r, async { Ok(rx.await??) }) - // } + pub fn new_with_fallback( + peer: Recipient, + payload: Req, + fallback_request: FallbackReq, + ) -> (Self, impl Future, ProtocolName)>>) { + let (tx, rx) = oneshot::channel(); + let r = Self { + peer, + payload, + pending_response: tx, + fallback_request: Some((fallback_request, FallbackReq::PROTOCOL)), + }; + (r, async { Ok(rx.await??) }) + } /// Encode a request into a `Vec`. /// diff --git a/polkadot/node/network/protocol/src/request_response/v1.rs b/polkadot/node/network/protocol/src/request_response/v1.rs index 60eecb69f738912ddb0240c890e2283db7f91a72..c503c6e4df03bd679242083bb4db082489bf8653 100644 --- a/polkadot/node/network/protocol/src/request_response/v1.rs +++ b/polkadot/node/network/protocol/src/request_response/v1.rs @@ -33,7 +33,8 @@ use super::{IsRequest, Protocol}; pub struct ChunkFetchingRequest { /// Hash of candidate we want a chunk for. pub candidate_hash: CandidateHash, - /// The index of the chunk to fetch. + /// The validator index we are requesting from. This must be identical to the index of the + /// chunk we'll receive. For v2, this may not be the case. pub index: ValidatorIndex, } @@ -57,6 +58,15 @@ impl From> for ChunkFetchingResponse { } } +impl From for Option { + fn from(x: ChunkFetchingResponse) -> Self { + match x { + ChunkFetchingResponse::Chunk(c) => Some(c), + ChunkFetchingResponse::NoSuchChunk => None, + } + } +} + /// Skimmed down variant of `ErasureChunk`. /// /// Instead of transmitting a full `ErasureChunk` we transmit `ChunkResponse` in @@ -80,7 +90,7 @@ impl From for ChunkResponse { impl ChunkResponse { /// Re-build an `ErasureChunk` from response and request. pub fn recombine_into_chunk(self, req: &ChunkFetchingRequest) -> ErasureChunk { - ErasureChunk { chunk: self.chunk, proof: self.proof, index: req.index } + ErasureChunk { chunk: self.chunk, proof: self.proof, index: req.index.into() } } } diff --git a/polkadot/node/network/protocol/src/request_response/v2.rs b/polkadot/node/network/protocol/src/request_response/v2.rs index 6b90c579237fbff95496035f461c5cc4c5202984..7e1a2d989168c1c8ed11d10d8871f3f7c514a64d 100644 --- a/polkadot/node/network/protocol/src/request_response/v2.rs +++ b/polkadot/node/network/protocol/src/request_response/v2.rs @@ -18,12 +18,13 @@ use parity_scale_codec::{Decode, Encode}; +use polkadot_node_primitives::ErasureChunk; use polkadot_primitives::{ CandidateHash, CommittedCandidateReceipt, Hash, Id as ParaId, PersistedValidationData, - UncheckedSignedStatement, + UncheckedSignedStatement, ValidatorIndex, }; -use super::{IsRequest, Protocol}; +use super::{v1, IsRequest, Protocol}; use crate::v2::StatementFilter; /// Request a candidate with statements. @@ -78,3 +79,60 @@ impl IsRequest for CollationFetchingRequest { type Response = CollationFetchingResponse; const PROTOCOL: Protocol = Protocol::CollationFetchingV2; } + +/// Request an availability chunk. +#[derive(Debug, Copy, Clone, Encode, Decode)] +pub struct ChunkFetchingRequest { + /// Hash of candidate we want a chunk for. + pub candidate_hash: CandidateHash, + /// The validator index we are requesting from. This may not be identical to the index of the + /// chunk we'll receive. It's up to the caller to decide whether they need to validate they got + /// the chunk they were expecting. + pub index: ValidatorIndex, +} + +/// Receive a requested erasure chunk. +#[derive(Debug, Clone, Encode, Decode)] +pub enum ChunkFetchingResponse { + /// The requested chunk data. + #[codec(index = 0)] + Chunk(ErasureChunk), + /// Node was not in possession of the requested chunk. + #[codec(index = 1)] + NoSuchChunk, +} + +impl From> for ChunkFetchingResponse { + fn from(x: Option) -> Self { + match x { + Some(c) => ChunkFetchingResponse::Chunk(c), + None => ChunkFetchingResponse::NoSuchChunk, + } + } +} + +impl From for Option { + fn from(x: ChunkFetchingResponse) -> Self { + match x { + ChunkFetchingResponse::Chunk(c) => Some(c), + ChunkFetchingResponse::NoSuchChunk => None, + } + } +} + +impl From for ChunkFetchingRequest { + fn from(v1::ChunkFetchingRequest { candidate_hash, index }: v1::ChunkFetchingRequest) -> Self { + Self { candidate_hash, index } + } +} + +impl From for v1::ChunkFetchingRequest { + fn from(ChunkFetchingRequest { candidate_hash, index }: ChunkFetchingRequest) -> Self { + Self { candidate_hash, index } + } +} + +impl IsRequest for ChunkFetchingRequest { + type Response = ChunkFetchingResponse; + const PROTOCOL: Protocol = Protocol::ChunkFetchingV2; +} diff --git a/polkadot/node/network/statement-distribution/Cargo.toml b/polkadot/node/network/statement-distribution/Cargo.toml index d8ae031cbf36dabf2899e61574958ffdbde62921..65224f9e2be620cdf862a5da3b7486b17cfb6534 100644 --- a/polkadot/node/network/statement-distribution/Cargo.toml +++ b/polkadot/node/network/statement-distribution/Cargo.toml @@ -22,9 +22,9 @@ polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-network-protocol = { path = "../protocol" } arrayvec = "0.7.4" indexmap = "2.0.0" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" bitvec = "1" [dev-dependencies] @@ -42,3 +42,13 @@ sc-network = { path = "../../../../substrate/client/network" } futures-timer = "3.0.2" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } rand_chacha = "0.3" +polkadot-subsystem-bench = { path = "../../subsystem-bench" } + +[[bench]] +name = "statement-distribution-regression-bench" +path = "benches/statement-distribution-regression-bench.rs" +harness = false +required-features = ["subsystem-benchmarks"] + +[features] +subsystem-benchmarks = [] diff --git a/polkadot/node/network/statement-distribution/benches/statement-distribution-regression-bench.rs b/polkadot/node/network/statement-distribution/benches/statement-distribution-regression-bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..9cbe385e3f42ee5be7dc0e5cda44bdbc92930828 --- /dev/null +++ b/polkadot/node/network/statement-distribution/benches/statement-distribution-regression-bench.rs @@ -0,0 +1,74 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! statement-distribution regression tests +//! +//! Statement distribution benchmark based on Kusama parameters and scale. + +use polkadot_subsystem_bench::{ + configuration::TestConfiguration, + statement::{benchmark_statement_distribution, prepare_test, TestState}, + usage::BenchmarkUsage, + utils::save_to_file, +}; +use std::io::Write; + +const BENCH_COUNT: usize = 50; + +fn main() -> Result<(), String> { + let mut messages = vec![]; + let mut config = TestConfiguration::default(); + config.n_cores = 100; + config.n_validators = 500; + config.num_blocks = 10; + config.connectivity = 100; + config.generate_pov_sizes(); + let state = TestState::new(&config); + + println!("Benchmarking..."); + let usages: Vec = (0..BENCH_COUNT) + .map(|n| { + print!("\r[{}{}]", "#".repeat(n), "_".repeat(BENCH_COUNT - n)); + std::io::stdout().flush().unwrap(); + let (mut env, _cfgs) = prepare_test(&state, false); + env.runtime().block_on(benchmark_statement_distribution(&mut env, &state)) + }) + .collect(); + println!("\rDone!{}", " ".repeat(BENCH_COUNT)); + + let average_usage = BenchmarkUsage::average(&usages); + save_to_file( + "charts/statement-distribution-regression-bench.json", + average_usage.to_chart_json().map_err(|e| e.to_string())?, + ) + .map_err(|e| e.to_string())?; + println!("{}", average_usage); + + // We expect no variance for received and sent + // but use 0.001 because we operate with floats + messages.extend(average_usage.check_network_usage(&[ + ("Received from peers", 106.4000, 0.001), + ("Sent to peers", 127.9100, 0.001), + ])); + messages.extend(average_usage.check_cpu_usage(&[("statement-distribution", 0.0390, 0.1)])); + + if messages.is_empty() { + Ok(()) + } else { + eprintln!("{}", messages.join("\n")); + Err("Regressions found".to_string()) + } +} diff --git a/polkadot/node/network/statement-distribution/src/lib.rs b/polkadot/node/network/statement-distribution/src/lib.rs index 7e91d2849120283c3fcefc4193a6e3d8bff809a1..4d56c795f13b29949a7a3b3e7f9bfc85e89ab274 100644 --- a/polkadot/node/network/statement-distribution/src/lib.rs +++ b/polkadot/node/network/statement-distribution/src/lib.rs @@ -19,7 +19,6 @@ //! This is responsible for distributing signed statements about candidate //! validity among validators. -#![deny(unused_crate_dependencies)] #![warn(missing_docs)] use error::{log_error, FatalResult}; @@ -207,6 +206,7 @@ impl StatementDistributionSubsystem { v2::respond_task( self.req_receiver.take().expect("Mandatory argument to new. qed"), res_sender.clone(), + self.metrics.clone(), ) .boxed(), ) diff --git a/polkadot/node/network/statement-distribution/src/metrics.rs b/polkadot/node/network/statement-distribution/src/metrics.rs index b9a51dc89d61afd9d2805f294b208f92572dd754..1bc994174263905d3058154ead29eaaa16bd2ad4 100644 --- a/polkadot/node/network/statement-distribution/src/metrics.rs +++ b/polkadot/node/network/statement-distribution/src/metrics.rs @@ -24,14 +24,19 @@ const HISTOGRAM_LATENCY_BUCKETS: &[f64] = &[ #[derive(Clone)] struct MetricsInner { + // V1 statements_distributed: prometheus::Counter, sent_requests: prometheus::Counter, received_responses: prometheus::CounterVec, - active_leaves_update: prometheus::Histogram, - share: prometheus::Histogram, network_bridge_update: prometheus::HistogramVec, statements_unexpected: prometheus::CounterVec, created_message_size: prometheus::Gauge, + // V1+ + active_leaves_update: prometheus::Histogram, + share: prometheus::Histogram, + // V2+ + peer_rate_limit_request_drop: prometheus::Counter, + max_parallel_requests_reached: prometheus::Counter, } /// Statement Distribution metrics. @@ -114,6 +119,23 @@ impl Metrics { metrics.created_message_size.set(size as u64); } } + + /// Update sent dropped requests counter when request dropped because + /// of peer rate limit + pub fn on_request_dropped_peer_rate_limit(&self) { + if let Some(metrics) = &self.0 { + metrics.peer_rate_limit_request_drop.inc(); + } + } + + /// Update max parallel requests reached counter + /// This counter is updated when the maximum number of parallel requests is reached + /// and we are waiting for one of the requests to finish + pub fn on_max_parallel_requests_reached(&self) { + if let Some(metrics) = &self.0 { + metrics.max_parallel_requests_reached.inc(); + } + } } impl metrics::Metrics for Metrics { @@ -193,6 +215,20 @@ impl metrics::Metrics for Metrics { ))?, registry, )?, + peer_rate_limit_request_drop: prometheus::register( + prometheus::Counter::new( + "polkadot_parachain_statement_distribution_peer_rate_limit_request_drop_total", + "Number of statement distribution requests dropped because of the peer rate limiting.", + )?, + registry, + )?, + max_parallel_requests_reached: prometheus::register( + prometheus::Counter::new( + "polkadot_parachain_statement_distribution_max_parallel_requests_reached_total", + "Number of times the maximum number of parallel requests was reached.", + )?, + registry, + )?, }; Ok(Metrics(Some(metrics))) } diff --git a/polkadot/node/network/statement-distribution/src/v2/candidates.rs b/polkadot/node/network/statement-distribution/src/v2/candidates.rs index ad56ad4a2365b94e6ced0e43ce0747d99fb6a80d..a4f2455c28401f536d449268591e2f9746a9db81 100644 --- a/polkadot/node/network/statement-distribution/src/v2/candidates.rs +++ b/polkadot/node/network/statement-distribution/src/v2/candidates.rs @@ -243,12 +243,12 @@ impl Candidates { /// Whether statements from a candidate are importable. /// /// This is only true when the candidate is known, confirmed, - /// and is importable in a fragment tree. + /// and is importable in a fragment chain. pub fn is_importable(&self, candidate_hash: &CandidateHash) -> bool { self.get_confirmed(candidate_hash).map_or(false, |c| c.is_importable(None)) } - /// Note that a candidate is importable in a fragment tree indicated by the given + /// Note that a candidate is importable in a fragment chain indicated by the given /// leaf hash. pub fn note_importable_under(&mut self, candidate: &HypotheticalCandidate, leaf_hash: Hash) { match candidate { diff --git a/polkadot/node/network/statement-distribution/src/v2/grid.rs b/polkadot/node/network/statement-distribution/src/v2/grid.rs index 24d846c840e00c49446a0525b3768353f56ae524..b6e4163090c4d5fe00a22c61b50d99b74e69c8bd 100644 --- a/polkadot/node/network/statement-distribution/src/v2/grid.rs +++ b/polkadot/node/network/statement-distribution/src/v2/grid.rs @@ -46,10 +46,8 @@ //! - Request/response for the candidate + votes. //! - Ignore if they are inconsistent with the manifest. //! - A malicious backing group is capable of producing an unbounded number of backed candidates. -//! - We request the candidate only if the candidate has a hypothetical depth in any of our -//! fragment trees, and: -//! - the seconding validators have not seconded any other candidates at that depth in any of -//! those fragment trees +//! - We request the candidate only if the candidate is a hypothetical member in any of our +//! fragment chains, and: //! - All members of the group attempt to circulate all statements (in compact form) from the rest //! of the group on candidates that have already been backed. //! - They do this via the grid topology. diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs index 118e34e92063e5571f637d9e44460b5b78c4fd8a..961ec45bdada037885fb5ea43858e4e1522fac2c 100644 --- a/polkadot/node/network/statement-distribution/src/v2/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs @@ -37,7 +37,7 @@ use polkadot_node_primitives::{ use polkadot_node_subsystem::{ messages::{ network_bridge_event::NewGossipTopology, CandidateBackingMessage, HypotheticalCandidate, - HypotheticalFrontierRequest, NetworkBridgeEvent, NetworkBridgeTxMessage, + HypotheticalMembershipRequest, NetworkBridgeEvent, NetworkBridgeTxMessage, ProspectiveParachainsMessage, }, overseer, ActivatedLeaf, @@ -59,6 +59,8 @@ use sp_keystore::KeystorePtr; use fatality::Nested; use futures::{ channel::{mpsc, oneshot}, + future::FutureExt, + select, stream::FuturesUnordered, SinkExt, StreamExt, }; @@ -73,6 +75,7 @@ use std::{ use crate::{ error::{JfyiError, JfyiErrorResult}, + metrics::Metrics, LOG_TARGET, }; use candidates::{BadAdvertisement, Candidates, PostConfirmation}; @@ -750,7 +753,7 @@ pub(crate) async fn handle_active_leaves_update( } } - new_leaf_fragment_tree_updates(ctx, state, activated.hash).await; + new_leaf_fragment_chain_updates(ctx, state, activated.hash).await; Ok(()) } @@ -2213,7 +2216,7 @@ async fn determine_groups_per_para( } #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] -async fn fragment_tree_update_inner( +async fn fragment_chain_update_inner( ctx: &mut Context, state: &mut State, active_leaf_hash: Option, @@ -2227,31 +2230,34 @@ async fn fragment_tree_update_inner( }; // 2. find out which are in the frontier - let frontier = { + gum::debug!( + target: LOG_TARGET, + "Calling getHypotheticalMembership from statement distribution" + ); + let candidate_memberships = { let (tx, rx) = oneshot::channel(); - ctx.send_message(ProspectiveParachainsMessage::GetHypotheticalFrontier( - HypotheticalFrontierRequest { + ctx.send_message(ProspectiveParachainsMessage::GetHypotheticalMembership( + HypotheticalMembershipRequest { candidates: hypotheticals, - fragment_tree_relay_parent: active_leaf_hash, - backed_in_path_only: false, + fragment_chain_relay_parent: active_leaf_hash, }, tx, )) .await; match rx.await { - Ok(frontier) => frontier, + Ok(candidate_memberships) => candidate_memberships, Err(oneshot::Canceled) => return, } }; // 3. note that they are importable under a given leaf hash. - for (hypo, membership) in frontier { - // skip parablocks outside of the frontier + for (hypo, membership) in candidate_memberships { + // skip parablocks which aren't potential candidates if membership.is_empty() { continue } - for (leaf_hash, _) in membership { + for leaf_hash in membership { state.candidates.note_importable_under(&hypo, leaf_hash); } @@ -2295,31 +2301,31 @@ async fn fragment_tree_update_inner( } #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] -async fn new_leaf_fragment_tree_updates( +async fn new_leaf_fragment_chain_updates( ctx: &mut Context, state: &mut State, leaf_hash: Hash, ) { - fragment_tree_update_inner(ctx, state, Some(leaf_hash), None, None).await + fragment_chain_update_inner(ctx, state, Some(leaf_hash), None, None).await } #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] -async fn prospective_backed_notification_fragment_tree_updates( +async fn prospective_backed_notification_fragment_chain_updates( ctx: &mut Context, state: &mut State, para_id: ParaId, para_head: Hash, ) { - fragment_tree_update_inner(ctx, state, None, Some((para_head, para_id)), None).await + fragment_chain_update_inner(ctx, state, None, Some((para_head, para_id)), None).await } #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] -async fn new_confirmed_candidate_fragment_tree_updates( +async fn new_confirmed_candidate_fragment_chain_updates( ctx: &mut Context, state: &mut State, candidate: HypotheticalCandidate, ) { - fragment_tree_update_inner(ctx, state, None, None, Some(vec![candidate])).await + fragment_chain_update_inner(ctx, state, None, None, Some(vec![candidate])).await } struct ManifestImportSuccess<'a> { @@ -2862,7 +2868,7 @@ pub(crate) async fn handle_backed_candidate_message( .await; // Search for children of the backed candidate to request. - prospective_backed_notification_fragment_tree_updates( + prospective_backed_notification_fragment_chain_updates( ctx, state, confirmed.para_id(), @@ -2953,7 +2959,8 @@ async fn apply_post_confirmation( post_confirmation.hypothetical.relay_parent(), ) .await; - new_confirmed_candidate_fragment_tree_updates(ctx, state, post_confirmation.hypothetical).await; + new_confirmed_candidate_fragment_chain_updates(ctx, state, post_confirmation.hypothetical) + .await; } /// Dispatch pending requests for candidate data & statements. @@ -3182,8 +3189,8 @@ pub(crate) async fn handle_response( let confirmed = state.candidates.get_confirmed(&candidate_hash).expect("just confirmed; qed"); - // Although the candidate is confirmed, it isn't yet on the - // hypothetical frontier of the fragment tree. Later, when it is, + // Although the candidate is confirmed, it isn't yet a + // hypothetical member of the fragment chain. Later, when it is, // we will import statements. if !confirmed.is_importable(None) { return @@ -3423,35 +3430,61 @@ pub(crate) struct ResponderMessage { pub(crate) async fn respond_task( mut receiver: IncomingRequestReceiver, mut sender: mpsc::Sender, + metrics: Metrics, ) { let mut pending_out = FuturesUnordered::new(); + let mut active_peers = HashSet::new(); + loop { - // Ensure we are not handling too many requests in parallel. - if pending_out.len() >= MAX_PARALLEL_ATTESTED_CANDIDATE_REQUESTS as usize { - // Wait for one to finish: - pending_out.next().await; - } + select! { + // New request + request_result = receiver.recv(|| vec![COST_INVALID_REQUEST]).fuse() => { + let request = match request_result.into_nested() { + Ok(Ok(v)) => v, + Err(fatal) => { + gum::debug!(target: LOG_TARGET, error = ?fatal, "Shutting down request responder"); + return + }, + Ok(Err(jfyi)) => { + gum::debug!(target: LOG_TARGET, error = ?jfyi, "Decoding request failed"); + continue + }, + }; - let req = match receiver.recv(|| vec![COST_INVALID_REQUEST]).await.into_nested() { - Ok(Ok(v)) => v, - Err(fatal) => { - gum::debug!(target: LOG_TARGET, error = ?fatal, "Shutting down request responder"); - return + // If peer currently being served drop request + if active_peers.contains(&request.peer) { + gum::trace!(target: LOG_TARGET, "Peer already being served, dropping request"); + metrics.on_request_dropped_peer_rate_limit(); + continue + } + + // If we are over parallel limit wait for one to finish + if pending_out.len() >= MAX_PARALLEL_ATTESTED_CANDIDATE_REQUESTS as usize { + gum::trace!(target: LOG_TARGET, "Over max parallel requests, waiting for one to finish"); + metrics.on_max_parallel_requests_reached(); + let (_, peer) = pending_out.select_next_some().await; + active_peers.remove(&peer); + } + + // Start serving the request + let (pending_sent_tx, pending_sent_rx) = oneshot::channel(); + let peer = request.peer; + if let Err(err) = sender + .feed(ResponderMessage { request, sent_feedback: pending_sent_tx }) + .await + { + gum::debug!(target: LOG_TARGET, ?err, "Shutting down responder"); + return + } + let future_with_peer = pending_sent_rx.map(move |result| (result, peer)); + pending_out.push(future_with_peer); + active_peers.insert(peer); }, - Ok(Err(jfyi)) => { - gum::debug!(target: LOG_TARGET, error = ?jfyi, "Decoding request failed"); - continue + // Request served/finished + result = pending_out.select_next_some() => { + let (_, peer) = result; + active_peers.remove(&peer); }, - }; - - let (pending_sent_tx, pending_sent_rx) = oneshot::channel(); - if let Err(err) = sender - .feed(ResponderMessage { request: req, sent_feedback: pending_sent_tx }) - .await - { - gum::debug!(target: LOG_TARGET, ?err, "Shutting down responder"); - return } - pending_out.push(pending_sent_rx); } } diff --git a/polkadot/node/network/statement-distribution/src/v2/requests.rs b/polkadot/node/network/statement-distribution/src/v2/requests.rs index 1ed18ffd42a9fa6eca92284b097f69b9caa12bb1..b8ed34d26c8a5272273297203b82e9ce263a107c 100644 --- a/polkadot/node/network/statement-distribution/src/v2/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/requests.rs @@ -366,6 +366,7 @@ impl RequestManager { id, &props, &peer_advertised, + &response_manager, ) { None => continue, Some(t) => t, @@ -387,14 +388,17 @@ impl RequestManager { ); let stored_id = id.clone(); - response_manager.push(Box::pin(async move { - TaggedResponse { - identifier: stored_id, - requested_peer: target, - props, - response: response_fut.await, - } - })); + response_manager.push( + Box::pin(async move { + TaggedResponse { + identifier: stored_id, + requested_peer: target, + props, + response: response_fut.await, + } + }), + target, + ); entry.in_flight = true; @@ -422,28 +426,35 @@ impl RequestManager { /// A manager for pending responses. pub struct ResponseManager { pending_responses: FuturesUnordered>, + active_peers: HashSet, } impl ResponseManager { pub fn new() -> Self { - Self { pending_responses: FuturesUnordered::new() } + Self { pending_responses: FuturesUnordered::new(), active_peers: HashSet::new() } } /// Await the next incoming response to a sent request, or immediately /// return `None` if there are no pending responses. pub async fn incoming(&mut self) -> Option { - self.pending_responses - .next() - .await - .map(|response| UnhandledResponse { response }) + self.pending_responses.next().await.map(|response| { + self.active_peers.remove(&response.requested_peer); + UnhandledResponse { response } + }) } fn len(&self) -> usize { self.pending_responses.len() } - fn push(&mut self, response: BoxFuture<'static, TaggedResponse>) { + fn push(&mut self, response: BoxFuture<'static, TaggedResponse>, target: PeerId) { self.pending_responses.push(response); + self.active_peers.insert(target); + } + + /// Returns true if we are currently sending a request to the peer. + fn is_sending_to(&self, peer: &PeerId) -> bool { + self.active_peers.contains(peer) } } @@ -471,10 +482,16 @@ fn find_request_target_with_update( candidate_identifier: &CandidateIdentifier, props: &RequestProperties, peer_advertised: impl Fn(&CandidateIdentifier, &PeerId) -> Option, + response_manager: &ResponseManager, ) -> Option { let mut prune = Vec::new(); let mut target = None; for (i, p) in known_by.iter().enumerate() { + // If we are already sending to that peer, skip for now + if response_manager.is_sending_to(p) { + continue + } + let mut filter = match peer_advertised(candidate_identifier, p) { None => { prune.push(i); @@ -1002,7 +1019,8 @@ mod tests { candidate_receipt.descriptor.persisted_validation_data_hash = persisted_validation_data.hash(); let candidate = candidate_receipt.hash(); - let requested_peer = PeerId::random(); + let requested_peer_1 = PeerId::random(); + let requested_peer_2 = PeerId::random(); let identifier1 = request_manager .get_or_insert(relay_parent, candidate, 1.into()) @@ -1010,14 +1028,14 @@ mod tests { .clone(); request_manager .get_or_insert(relay_parent, candidate, 1.into()) - .add_peer(requested_peer); + .add_peer(requested_peer_1); let identifier2 = request_manager .get_or_insert(relay_parent, candidate, 2.into()) .identifier .clone(); request_manager .get_or_insert(relay_parent, candidate, 2.into()) - .add_peer(requested_peer); + .add_peer(requested_peer_2); assert_ne!(identifier1, identifier2); assert_eq!(request_manager.requests.len(), 2); @@ -1053,7 +1071,7 @@ mod tests { let response = UnhandledResponse { response: TaggedResponse { identifier: identifier1, - requested_peer, + requested_peer: requested_peer_1, props: request_properties.clone(), response: Ok(AttestedCandidateResponse { candidate_receipt: candidate_receipt.clone(), @@ -1076,13 +1094,13 @@ mod tests { assert_eq!( output, ResponseValidationOutput { - requested_peer, + requested_peer: requested_peer_1, request_status: CandidateRequestStatus::Complete { candidate: candidate_receipt.clone(), persisted_validation_data: persisted_validation_data.clone(), statements, }, - reputation_changes: vec![(requested_peer, BENEFIT_VALID_RESPONSE)], + reputation_changes: vec![(requested_peer_1, BENEFIT_VALID_RESPONSE)], } ); } @@ -1093,7 +1111,7 @@ mod tests { let response = UnhandledResponse { response: TaggedResponse { identifier: identifier2, - requested_peer, + requested_peer: requested_peer_2, props: request_properties, response: Ok(AttestedCandidateResponse { candidate_receipt: candidate_receipt.clone(), @@ -1115,12 +1133,14 @@ mod tests { assert_eq!( output, ResponseValidationOutput { - requested_peer, + requested_peer: requested_peer_2, request_status: CandidateRequestStatus::Outdated, reputation_changes: vec![], } ); } + + assert_eq!(request_manager.requests.len(), 0); } // Test case where we had a request in-flight and the request entry was garbage-collected on @@ -1293,4 +1313,140 @@ mod tests { assert_eq!(request_manager.requests.len(), 0); assert_eq!(request_manager.by_priority.len(), 0); } + + // Test case where we queue 2 requests to be sent to the same peer and 1 request to another + // peer. Same peer requests should be served one at a time but they should not block the other + // peer request. + #[test] + fn rate_limit_requests_to_same_peer() { + let mut request_manager = RequestManager::new(); + let mut response_manager = ResponseManager::new(); + + let relay_parent = Hash::from_low_u64_le(1); + + // Create 3 candidates + let mut candidate_receipt_1 = test_helpers::dummy_committed_candidate_receipt(relay_parent); + let persisted_validation_data_1 = dummy_pvd(); + candidate_receipt_1.descriptor.persisted_validation_data_hash = + persisted_validation_data_1.hash(); + let candidate_1 = candidate_receipt_1.hash(); + + let mut candidate_receipt_2 = test_helpers::dummy_committed_candidate_receipt(relay_parent); + let persisted_validation_data_2 = dummy_pvd(); + candidate_receipt_2.descriptor.persisted_validation_data_hash = + persisted_validation_data_2.hash(); + let candidate_2 = candidate_receipt_2.hash(); + + let mut candidate_receipt_3 = test_helpers::dummy_committed_candidate_receipt(relay_parent); + let persisted_validation_data_3 = dummy_pvd(); + candidate_receipt_3.descriptor.persisted_validation_data_hash = + persisted_validation_data_3.hash(); + let candidate_3 = candidate_receipt_3.hash(); + + // Create 2 peers + let requested_peer_1 = PeerId::random(); + let requested_peer_2 = PeerId::random(); + + let group_size = 3; + let group = &[ValidatorIndex(0), ValidatorIndex(1), ValidatorIndex(2)]; + let unwanted_mask = StatementFilter::blank(group_size); + let disabled_mask: BitVec = Default::default(); + let request_properties = RequestProperties { unwanted_mask, backing_threshold: None }; + let request_props = |_identifier: &CandidateIdentifier| Some((&request_properties).clone()); + let peer_advertised = + |_identifier: &CandidateIdentifier, _peer: &_| Some(StatementFilter::full(group_size)); + + // Add request for candidate 1 from peer 1 + let identifier1 = request_manager + .get_or_insert(relay_parent, candidate_1, 1.into()) + .identifier + .clone(); + request_manager + .get_or_insert(relay_parent, candidate_1, 1.into()) + .add_peer(requested_peer_1); + + // Add request for candidate 3 from peer 2 (this one can be served in parallel) + let _identifier3 = request_manager + .get_or_insert(relay_parent, candidate_3, 1.into()) + .identifier + .clone(); + request_manager + .get_or_insert(relay_parent, candidate_3, 1.into()) + .add_peer(requested_peer_2); + + // Successfully dispatch request for candidate 1 from peer 1 and candidate 3 from peer 2 + for _ in 0..2 { + let outgoing = + request_manager.next_request(&mut response_manager, request_props, peer_advertised); + assert!(outgoing.is_some()); + } + assert_eq!(response_manager.active_peers.len(), 2); + assert!(response_manager.is_sending_to(&requested_peer_1)); + assert!(response_manager.is_sending_to(&requested_peer_2)); + assert_eq!(request_manager.requests.len(), 2); + + // Add request for candidate 2 from peer 1 + let _identifier2 = request_manager + .get_or_insert(relay_parent, candidate_2, 1.into()) + .identifier + .clone(); + request_manager + .get_or_insert(relay_parent, candidate_2, 1.into()) + .add_peer(requested_peer_1); + + // Do not dispatch the request for the second candidate from peer 1 (already serving that + // peer) + let outgoing = + request_manager.next_request(&mut response_manager, request_props, peer_advertised); + assert!(outgoing.is_none()); + assert_eq!(response_manager.active_peers.len(), 2); + assert!(response_manager.is_sending_to(&requested_peer_1)); + assert!(response_manager.is_sending_to(&requested_peer_2)); + assert_eq!(request_manager.requests.len(), 3); + + // Manually mark response received (response future resolved) + response_manager.active_peers.remove(&requested_peer_1); + response_manager.pending_responses = FuturesUnordered::new(); + + // Validate first response (candidate 1 from peer 1) + { + let statements = vec![]; + let response = UnhandledResponse { + response: TaggedResponse { + identifier: identifier1, + requested_peer: requested_peer_1, + props: request_properties.clone(), + response: Ok(AttestedCandidateResponse { + candidate_receipt: candidate_receipt_1.clone(), + persisted_validation_data: persisted_validation_data_1.clone(), + statements, + }), + }, + }; + let validator_key_lookup = |_v| None; + let allowed_para_lookup = |_para, _g_index| true; + let _output = response.validate_response( + &mut request_manager, + group, + 0, + validator_key_lookup, + allowed_para_lookup, + disabled_mask.clone(), + ); + + // First request served successfully + assert_eq!(request_manager.requests.len(), 2); + assert_eq!(response_manager.active_peers.len(), 1); + assert!(response_manager.is_sending_to(&requested_peer_2)); + } + + // Check if the request that was ignored previously will be served now + let outgoing = + request_manager.next_request(&mut response_manager, request_props, peer_advertised); + assert!(outgoing.is_some()); + assert_eq!(response_manager.active_peers.len(), 2); + assert!(response_manager.is_sending_to(&requested_peer_1)); + assert!(response_manager.is_sending_to(&requested_peer_2)); + assert_eq!(request_manager.requests.len(), 2); + } } diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs b/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs index 4fb033e08ce3af0724d5a8770bdb0abf942e38a5..fe51f953e244a560d7fe2e0bf414279fd0b8bf89 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs @@ -111,8 +111,8 @@ fn share_seconded_circulated_to_cluster() { ); // sharing a `Seconded` message confirms a candidate, which leads to new - // fragment tree updates. - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + // fragment chain updates. + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer }); @@ -509,7 +509,7 @@ fn seconded_statement_leads_to_request() { if p == peer_a && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer }); @@ -583,7 +583,7 @@ fn cluster_statements_shared_seconded_first() { .await; // result of new confirmed candidate. - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer .send(FromOrchestra::Communication { @@ -717,8 +717,8 @@ fn cluster_accounts_for_implicit_view() { ); // sharing a `Seconded` message confirms a candidate, which leads to new - // fragment tree updates. - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + // fragment chain updates. + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; // activate new leaf, which has relay-parent in implicit view. let next_relay_parent = Hash::repeat_byte(2); @@ -855,7 +855,7 @@ fn cluster_messages_imported_after_confirmed_candidate_importable_check() { ); } - answer_expected_hypothetical_depth_request( + answer_expected_hypothetical_membership_request( &mut overseer, vec![( HypotheticalCandidate::Complete { @@ -863,7 +863,7 @@ fn cluster_messages_imported_after_confirmed_candidate_importable_check() { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }, - vec![(relay_parent, vec![0])], + vec![relay_parent], )], ) .await; @@ -978,7 +978,7 @@ fn cluster_messages_imported_after_new_leaf_importable_check() { ); } - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; let next_relay_parent = Hash::repeat_byte(2); let mut next_test_leaf = state.make_dummy_leaf(next_relay_parent); @@ -996,7 +996,7 @@ fn cluster_messages_imported_after_new_leaf_importable_check() { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }, - vec![(relay_parent, vec![0])], + vec![relay_parent], )], ) .await; @@ -1113,7 +1113,7 @@ fn ensure_seconding_limit_is_respected() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Candidate 2. @@ -1139,7 +1139,7 @@ fn ensure_seconding_limit_is_respected() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send first statement from peer A. diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs b/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs index 9d00a92e742bb6a304004ed74eb59ea8b6c5440c..d2bf031368c14a13f5da44dd29ba28376109f9bf 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs @@ -129,7 +129,7 @@ fn backed_candidate_leads_to_advertisement() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send enough statements to make candidate backable, make sure announcements are sent. @@ -224,7 +224,7 @@ fn backed_candidate_leads_to_advertisement() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -384,7 +384,7 @@ fn received_advertisement_before_confirmation_leads_to_request() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -515,7 +515,7 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() { assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT); assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_RESPONSE); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive Backed message. @@ -546,7 +546,7 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive a manifest about the same candidate from peer D. @@ -720,7 +720,7 @@ fn received_acknowledgements_for_locally_confirmed() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive an unexpected acknowledgement from peer D. @@ -785,7 +785,7 @@ fn received_acknowledgements_for_locally_confirmed() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive an unexpected acknowledgement from peer D. @@ -918,7 +918,7 @@ fn received_acknowledgements_for_externally_confirmed() { assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT); assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_RESPONSE); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } let ack = BackedCandidateAcknowledgement { @@ -1101,7 +1101,7 @@ fn received_advertisement_after_confirmation_before_backing() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive advertisement from peer D (after confirmation but before backing). @@ -1272,9 +1272,12 @@ fn additional_statements_are_shared_after_manifest_exchange() { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }; - let membership = vec![(relay_parent, vec![0])]; - answer_expected_hypothetical_depth_request(&mut overseer, vec![(hypothetical, membership)]) - .await; + let membership = vec![relay_parent]; + answer_expected_hypothetical_membership_request( + &mut overseer, + vec![(hypothetical, membership)], + ) + .await; // Statements are sent to the Backing subsystem. { @@ -1338,7 +1341,7 @@ fn additional_statements_are_shared_after_manifest_exchange() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive a manifest about the same candidate from peer D. Contains different statements. @@ -1507,7 +1510,7 @@ fn advertisement_sent_when_peer_enters_relay_parent_view() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send enough statements to make candidate backable, make sure announcements are sent. @@ -1574,7 +1577,7 @@ fn advertisement_sent_when_peer_enters_relay_parent_view() { }) .await; - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; // Relay parent enters view of peer C. { @@ -1721,7 +1724,7 @@ fn advertisement_not_re_sent_when_peer_re_enters_view() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send enough statements to make candidate backable, make sure announcements are sent. @@ -1816,7 +1819,7 @@ fn advertisement_not_re_sent_when_peer_re_enters_view() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Peer leaves view. @@ -1982,9 +1985,12 @@ fn inner_grid_statements_imported_to_backing(groups_for_first_para: usize) { receipt: Arc::new(candidate.clone()), persisted_validation_data: pvd.clone(), }; - let membership = vec![(relay_parent, vec![0])]; - answer_expected_hypothetical_depth_request(&mut overseer, vec![(hypothetical, membership)]) - .await; + let membership = vec![relay_parent]; + answer_expected_hypothetical_membership_request( + &mut overseer, + vec![(hypothetical, membership)], + ) + .await; // Receive messages from Backing subsystem. { @@ -2616,7 +2622,7 @@ fn peer_reported_for_advertisement_conflicting_with_confirmed_candidate() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Receive conflicting advertisement from peer C after confirmation. @@ -2763,7 +2769,7 @@ fn inactive_local_participates_in_grid() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r))) if p == peer_a && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer }); diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs index 3d987d3fc433fbf62c1b05675da864b82f019536..f9a484f47a94c37fb909cdb640b5886ec12e2b2b 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs @@ -26,8 +26,8 @@ use polkadot_node_network_protocol::{ }; use polkadot_node_primitives::Statement; use polkadot_node_subsystem::messages::{ - network_bridge_event::NewGossipTopology, AllMessages, ChainApiMessage, FragmentTreeMembership, - HypotheticalCandidate, NetworkBridgeEvent, ProspectiveParachainsMessage, ReportPeerMessage, + network_bridge_event::NewGossipTopology, AllMessages, ChainApiMessage, HypotheticalCandidate, + HypotheticalMembership, NetworkBridgeEvent, ProspectiveParachainsMessage, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest, }; use polkadot_node_subsystem_test_helpers as test_helpers; @@ -539,7 +539,7 @@ async fn activate_leaf( leaf: &TestLeaf, test_state: &TestState, is_new_session: bool, - hypothetical_frontier: Vec<(HypotheticalCandidate, FragmentTreeMembership)>, + hypothetical_memberships: Vec<(HypotheticalCandidate, HypotheticalMembership)>, ) { let activated = new_leaf(leaf.hash, leaf.number); @@ -554,7 +554,7 @@ async fn activate_leaf( leaf, test_state, is_new_session, - hypothetical_frontier, + hypothetical_memberships, ) .await; } @@ -564,7 +564,7 @@ async fn handle_leaf_activation( leaf: &TestLeaf, test_state: &TestState, is_new_session: bool, - hypothetical_frontier: Vec<(HypotheticalCandidate, FragmentTreeMembership)>, + hypothetical_memberships: Vec<(HypotheticalCandidate, HypotheticalMembership)>, ) { let TestLeaf { number, @@ -586,19 +586,6 @@ async fn handle_leaf_activation( } ); - let mrp_response: Vec<(ParaId, BlockNumber)> = para_data - .iter() - .map(|(para_id, data)| (*para_id, data.min_relay_parent)) - .collect(); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx) - ) if parent == *hash => { - tx.send(mrp_response).unwrap(); - } - ); - let header = Header { parent_hash: *parent_hash, number: *number, @@ -615,6 +602,19 @@ async fn handle_leaf_activation( } ); + let mrp_response: Vec<(ParaId, BlockNumber)> = para_data + .iter() + .map(|(para_id, data)| (*para_id, data.min_relay_parent)) + .collect(); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::GetMinimumRelayParents(parent, tx) + ) if parent == *hash => { + tx.send(mrp_response).unwrap(); + } + ); + loop { match virtual_overseer.recv().await { AllMessages::RuntimeApi(RuntimeApiMessage::Request( @@ -674,18 +674,17 @@ async fn handle_leaf_activation( tx.send(Ok((validator_groups, group_rotation_info))).unwrap(); }, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetHypotheticalFrontier(req, tx), + ProspectiveParachainsMessage::GetHypotheticalMembership(req, tx), ) => { - assert_eq!(req.fragment_tree_relay_parent, Some(*hash)); - assert!(!req.backed_in_path_only); - for (i, (candidate, _)) in hypothetical_frontier.iter().enumerate() { + assert_eq!(req.fragment_chain_relay_parent, Some(*hash)); + for (i, (candidate, _)) in hypothetical_memberships.iter().enumerate() { assert!( req.candidates.iter().any(|c| &c == &candidate), "did not receive request for hypothetical candidate {}", i, ); } - tx.send(hypothetical_frontier).unwrap(); + tx.send(hypothetical_memberships).unwrap(); // this is the last expected runtime api call break }, @@ -727,17 +726,16 @@ async fn handle_sent_request( ); } -async fn answer_expected_hypothetical_depth_request( +async fn answer_expected_hypothetical_membership_request( virtual_overseer: &mut VirtualOverseer, - responses: Vec<(HypotheticalCandidate, FragmentTreeMembership)>, + responses: Vec<(HypotheticalCandidate, HypotheticalMembership)>, ) { assert_matches!( virtual_overseer.recv().await, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetHypotheticalFrontier(req, tx) + ProspectiveParachainsMessage::GetHypotheticalMembership(req, tx) ) => { - assert_eq!(req.fragment_tree_relay_parent, None); - assert!(!req.backed_in_path_only); + assert_eq!(req.fragment_chain_relay_parent, None); for (i, (candidate, _)) in responses.iter().enumerate() { assert!( req.candidates.iter().any(|c| &c == &candidate), diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs b/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs index 8cf139802148c0a6e720f6918c61824d5ef96575..38d7a10b86527c153f4a369beb8bbe86da05d582 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs @@ -169,7 +169,7 @@ fn cluster_peer_allowed_to_send_incomplete_statements() { ); } - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer }); @@ -339,7 +339,7 @@ fn peer_reported_for_providing_statements_meant_to_be_masked_out() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Peer C advertises candidate 2. @@ -411,7 +411,7 @@ fn peer_reported_for_providing_statements_meant_to_be_masked_out() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Peer C sends an announcement for candidate 3. Should hit seconding limit for validator 1. @@ -634,7 +634,7 @@ fn peer_reported_for_not_enough_statements() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -789,7 +789,7 @@ fn peer_reported_for_duplicate_statements() { ); } - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; overseer }); @@ -919,7 +919,7 @@ fn peer_reported_for_providing_statements_with_invalid_signatures() { if p == peer_a && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -1049,7 +1049,7 @@ fn peer_reported_for_providing_statements_with_wrong_validator_id() { if p == peer_a && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -1215,7 +1215,7 @@ fn disabled_validators_added_to_unwanted_mask() { assert_eq!(statement, seconded_b); } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -1372,7 +1372,7 @@ fn when_validator_disabled_after_sending_the_request() { assert_eq!(statement, seconded_b); } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer @@ -1475,7 +1475,7 @@ fn no_response_for_grid_request_not_meeting_quorum() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send enough statements to make candidate backable, make sure announcements are sent. @@ -1572,7 +1572,7 @@ fn no_response_for_grid_request_not_meeting_quorum() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } let mask = StatementFilter { @@ -1720,7 +1720,7 @@ fn disabling_works_from_the_latest_state_not_relay_parent() { if p == peer_disabled && r == BENEFIT_VALID_RESPONSE.into() => { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } activate_leaf(&mut overseer, &leaf_2, &state, false, vec![]).await; @@ -1862,7 +1862,7 @@ fn local_node_sanity_checks_incoming_requests() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Should drop requests from unknown peers. @@ -1891,7 +1891,7 @@ fn local_node_sanity_checks_incoming_requests() { let mask = StatementFilter::blank(state.config.group_size + 1); let response = state .send_request( - peer_c, + peer_a, request_v2::AttestedCandidateRequest { candidate_hash: candidate.hash(), mask }, ) .await @@ -2036,7 +2036,7 @@ fn local_node_checks_that_peer_can_request_before_responding() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; // Local node should respond to requests from peers in the same group // which appear to not have already seen the candidate @@ -2248,7 +2248,7 @@ fn local_node_respects_statement_mask() { AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a] ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Send enough statements to make candidate backable, make sure announcements are sent. @@ -2347,7 +2347,7 @@ fn local_node_respects_statement_mask() { } ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // `1` indicates statements NOT to request. @@ -2600,7 +2600,7 @@ fn should_delay_before_retrying_dropped_requests() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } // Sleep for the given amount of time. This should reset the delay for the first candidate. @@ -2691,7 +2691,7 @@ fn should_delay_before_retrying_dropped_requests() { if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() ); - answer_expected_hypothetical_depth_request(&mut overseer, vec![]).await; + answer_expected_hypothetical_membership_request(&mut overseer, vec![]).await; } overseer diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 55a6bdb74ba73c04bc66847a1b04ff6175608fa7..87484914ef9756017aa2a5c420f5853fbabd1ed3 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -856,6 +856,7 @@ fn test_availability_recovery_msg() -> AvailabilityRecoveryMessage { dummy_candidate_receipt(dummy_hash()), Default::default(), None, + None, sender, ) } diff --git a/polkadot/node/primitives/Cargo.toml b/polkadot/node/primitives/Cargo.toml index a4bbd824e6712e001f1df1cd9d66f835d02822fb..526d4e480bb05d745aad137f94b611f4cf91c838 100644 --- a/polkadot/node/primitives/Cargo.toml +++ b/polkadot/node/primitives/Cargo.toml @@ -13,7 +13,7 @@ workspace = true bounded-vec = "0.7" futures = "0.3.30" polkadot-primitives = { path = "../../primitives" } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sp-core = { path = "../../../substrate/primitives/core" } sp-application-crypto = { path = "../../../substrate/primitives/application-crypto" } sp-consensus-babe = { path = "../../../substrate/primitives/consensus/babe" } diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index 375aacd583267ef7e86f7888a9e3e17599e7414d..5f007bc8d67d9c07c5c202d8115e8a594f9ec721 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -30,13 +30,14 @@ use parity_scale_codec::{Decode, Encode, Error as CodecError, Input}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use polkadot_primitives::{ - BlakeTwo256, BlockNumber, CandidateCommitments, CandidateHash, CollatorPair, + BlakeTwo256, BlockNumber, CandidateCommitments, CandidateHash, ChunkIndex, CollatorPair, CommittedCandidateReceipt, CompactStatement, CoreIndex, EncodeAs, Hash, HashT, HeadData, Id as ParaId, PersistedValidationData, SessionIndex, Signed, UncheckedSigned, ValidationCode, - ValidationCodeHash, ValidatorIndex, MAX_CODE_SIZE, MAX_POV_SIZE, + ValidationCodeHash, MAX_CODE_SIZE, MAX_POV_SIZE, }; pub use sp_consensus_babe::{ AllowedSlots as BabeAllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, + Randomness as BabeRandomness, }; pub use polkadot_parachain_primitives::primitives::{ @@ -58,7 +59,7 @@ pub use disputes::{ /// relatively rare. /// /// The associated worker binaries should use the same version as the node that spawns them. -pub const NODE_VERSION: &'static str = "1.10.0"; +pub const NODE_VERSION: &'static str = "1.12.0"; // For a 16-ary Merkle Prefix Trie, we can expect at most 16 32-byte hashes per node // plus some overhead: @@ -639,7 +640,7 @@ pub struct ErasureChunk { /// The erasure-encoded chunk of data belonging to the candidate block. pub chunk: Vec, /// The index of this erasure-encoded chunk of data. - pub index: ValidatorIndex, + pub index: ChunkIndex, /// Proof for this chunk's branch in the Merkle tree. pub proof: Proof, } diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 9688ab556473131d6e90075de9b6f69ba4f244e5..37836f134bda646e632a6f472f6416ee8ea03081 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -67,6 +67,7 @@ sp-version = { path = "../../../substrate/primitives/version" } pallet-babe = { path = "../../../substrate/frame/babe" } pallet-staking = { path = "../../../substrate/frame/staking" } pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/transaction-payment/rpc/runtime-api" } +frame-metadata-hash-extension = { path = "../../../substrate/frame/metadata-hash-extension", optional = true } frame-system = { path = "../../../substrate/frame/system" } # Substrate Other @@ -90,7 +91,7 @@ thiserror = { workspace = true } kvdb = "0.13.0" kvdb-rocksdb = { version = "0.19.0", optional = true } parity-db = { version = "0.4.12", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } parking_lot = "0.12.1" bitvec = { version = "1.0.1", optional = true } @@ -187,8 +188,18 @@ full-node = [ ] # Configure the native runtimes to use. -westend-native = ["bitvec", "westend-runtime", "westend-runtime-constants"] -rococo-native = ["bitvec", "rococo-runtime", "rococo-runtime-constants"] +westend-native = [ + "bitvec", + "frame-metadata-hash-extension", + "westend-runtime", + "westend-runtime-constants", +] +rococo-native = [ + "bitvec", + "frame-metadata-hash-extension", + "rococo-runtime", + "rococo-runtime-constants", +] runtime-benchmarks = [ "frame-benchmarking-cli/runtime-benchmarks", @@ -206,6 +217,7 @@ runtime-benchmarks = [ "service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "westend-runtime?/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", diff --git a/polkadot/node/service/chain-specs/kusama.json b/polkadot/node/service/chain-specs/kusama.json index 490b39ee696930bafc9af4c139339a9974dffff9..899b302155f79c2e889ca8300f9cf277059bd3d4 100644 --- a/polkadot/node/service/chain-specs/kusama.json +++ b/polkadot/node/service/chain-specs/kusama.json @@ -18,11 +18,11 @@ "/dns/kusama.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWLx6nsj6Fpd8biP1VDyuCUjazvRiGWyBam8PsqRJkbUb9", "/dns/kusama.bootnodes.polkadotters.com/tcp/30311/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", "/dns/kusama.bootnodes.polkadotters.com/tcp/30313/wss/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", - "/dns/boot-cr.gatotech.network/tcp/33200/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", - "/dns/boot-cr.gatotech.network/tcp/35200/wss/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", - "/dns/boot-kusama.metaspan.io/tcp/23012/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", - "/dns/boot-kusama.metaspan.io/tcp/23015/ws/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", - "/dns/boot-kusama.metaspan.io/tcp/23016/wss/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", + "/dns/boot.gatotech.network/tcp/33200/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", + "/dns/boot.gatotech.network/tcp/35200/wss/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", + "/dns/boot.metaspan.io/tcp/23012/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", + "/dns/boot.metaspan.io/tcp/23015/ws/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", + "/dns/boot.metaspan.io/tcp/23016/wss/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", "/dns/kusama-bootnode.turboflakes.io/tcp/30305/p2p/12D3KooWR6cMhCYRhbJdqYZfzWZT6bcck3unpRLk8GBQGmHBgPwu", "/dns/kusama-bootnode.turboflakes.io/tcp/30405/wss/p2p/12D3KooWR6cMhCYRhbJdqYZfzWZT6bcck3unpRLk8GBQGmHBgPwu", "/dns/kusama-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWLswepVYVdCNduvWRTyNTaDMXEBcmvJdZ9Bhw3u2Jhad2", @@ -36,7 +36,8 @@ "/dns/ksm14.rotko.net/tcp/33224/p2p/12D3KooWAa5THTw8HPfnhEei23HdL8P9McBXdozG2oTtMMksjZkK", "/dns/ibp-boot-kusama.luckyfriday.io/tcp/30333/p2p/12D3KooW9vu1GWHBuxyhm7rZgD3fhGZpNajPXFexadvhujWMgwfT", "/dns/boot-kusama.luckyfriday.io/tcp/443/wss/p2p/12D3KooWS1Lu6DmK8YHSvkErpxpcXmk14vG6y4KVEFEkd9g62PP8", - "/dns/ibp-boot-kusama.luckyfriday.io/tcp/30334/wss/p2p/12D3KooW9vu1GWHBuxyhm7rZgD3fhGZpNajPXFexadvhujWMgwfT" + "/dns/ibp-boot-kusama.luckyfriday.io/tcp/30334/wss/p2p/12D3KooW9vu1GWHBuxyhm7rZgD3fhGZpNajPXFexadvhujWMgwfT", + "/dns4/kusama-0.boot.onfinality.io/tcp/27682/ws/p2p/12D3KooWFrwFo7ry3dEuFwhehGSSN96a5Xdzxot7SWfXeSbhELAe" ], "telemetryEndpoints": [ [ diff --git a/polkadot/node/service/chain-specs/paseo.json b/polkadot/node/service/chain-specs/paseo.json index 19eefd328994ed67c269fafc06acefaf28c751bf..5a67ddcd4c4361f4f1fc4e87ac6ffdf649e06feb 100644 --- a/polkadot/node/service/chain-specs/paseo.json +++ b/polkadot/node/service/chain-specs/paseo.json @@ -17,6 +17,8 @@ "/dns/boot.gatotech.network/tcp/35400/wss/p2p/12D3KooWEvz5Ygv3MhCUNTVQbUTVhzhvf4KKcNoe5M5YbVLPBeeW", "/dns/paseo-bootnode.turboflakes.io/tcp/30630/p2p/12D3KooWMjCN2CrnN71hAdehn6M2iYKeGdGbZ1A3SKhf4hxrgG9e", "/dns/paseo-bootnode.turboflakes.io/tcp/30730/wss/p2p/12D3KooWMjCN2CrnN71hAdehn6M2iYKeGdGbZ1A3SKhf4hxrgG9e", + "/dns/pso16.rotko.net/tcp/33246/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", + "/dns/pso16.rotko.net/tcp/35246/wss/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", "/dns/paseo-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWBLLFKDGBxCwq3QmU3YwWKXUx953WwprRshJQicYu4Cfr", "/dns/paseo-boot-ng.dwellir.com/tcp/30354/p2p/12D3KooWBLLFKDGBxCwq3QmU3YwWKXUx953WwprRshJQicYu4Cfr" ], diff --git a/polkadot/node/service/chain-specs/polkadot.json b/polkadot/node/service/chain-specs/polkadot.json index 035705437072f2bbf87c2e1790f97e15d302a85a..04def54f794cbc6381c3b2aadaa3e2d02763b6f2 100644 --- a/polkadot/node/service/chain-specs/polkadot.json +++ b/polkadot/node/service/chain-specs/polkadot.json @@ -19,11 +19,11 @@ "/dns/polkadot.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWAsuCEVCzUVUrtib8W82Yne3jgVGhQZN3hizko5FTnDg3", "/dns/polkadot.bootnodes.polkadotters.com/tcp/30314/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", "/dns/polkadot.bootnodes.polkadotters.com/tcp/30316/wss/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", - "/dns/boot-cr.gatotech.network/tcp/33100/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", - "/dns/boot-cr.gatotech.network/tcp/35100/wss/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", - "/dns/boot-polkadot.metaspan.io/tcp/13012/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", - "/dns/boot-polkadot.metaspan.io/tcp/13015/ws/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", - "/dns/boot-polkadot.metaspan.io/tcp/13016/wss/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", + "/dns/boot.gatotech.network/tcp/33100/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", + "/dns/boot.gatotech.network/tcp/35100/wss/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", + "/dns/boot.metaspan.io/tcp/13012/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", + "/dns/boot.metaspan.io/tcp/13015/ws/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", + "/dns/boot.metaspan.io/tcp/13016/wss/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", "/dns/polkadot-bootnode.turboflakes.io/tcp/30300/p2p/12D3KooWHJBMZgt7ymAdTRtadPcGXpJw79vBGe8z53r9JMkZW7Ha", "/dns/polkadot-bootnode.turboflakes.io/tcp/30400/wss/p2p/12D3KooWHJBMZgt7ymAdTRtadPcGXpJw79vBGe8z53r9JMkZW7Ha", "/dns/polkadot-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWFFqjBKoSdQniRpw1Y8W6kkV7takWv1DU2ZMkaA81PYVq", diff --git a/polkadot/node/service/chain-specs/westend.json b/polkadot/node/service/chain-specs/westend.json index 775f3e72ac75578a0f0166cba96531244af760c9..16bc7ff07b0fdd4805b7ffb3a4099c5b0c728363 100644 --- a/polkadot/node/service/chain-specs/westend.json +++ b/polkadot/node/service/chain-specs/westend.json @@ -16,11 +16,11 @@ "/dns/westend.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWJ5y9ZgVepBQNW4aabrxgmnrApdVnscqgKWiUu4BNJbC8", "/dns/westend.bootnodes.polkadotters.com/tcp/30308/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", "/dns/westend.bootnodes.polkadotters.com/tcp/30310/wss/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", - "/dns/boot-cr.gatotech.network/tcp/33300/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", - "/dns/boot-cr.gatotech.network/tcp/35300/wss/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", - "/dns/boot-westend.metaspan.io/tcp/33012/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", - "/dns/boot-westend.metaspan.io/tcp/33015/ws/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", - "/dns/boot-westend.metaspan.io/tcp/33016/wss/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", + "/dns/boot.gatotech.network/tcp/33300/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", + "/dns/boot.gatotech.network/tcp/35300/wss/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", + "/dns/boot.metaspan.io/tcp/33012/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", + "/dns/boot.metaspan.io/tcp/33015/ws/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", + "/dns/boot.metaspan.io/tcp/33016/wss/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", "/dns/westend-bootnode.turboflakes.io/tcp/30310/p2p/12D3KooWJvPDCZmReU46ghpCMJCPVUvUCav4WQdKtXQhZgJdH6tZ", "/dns/westend-bootnode.turboflakes.io/tcp/30410/wss/p2p/12D3KooWJvPDCZmReU46ghpCMJCPVUvUCav4WQdKtXQhZgJdH6tZ", "/dns/westend-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWJifoDhCL3swAKt7MWhFb7wLRFD9oG33AL3nAathmU24x", diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index a0c4d3b04469b1bcf85990d4f6f62922f09bf88a..4dcff2078419c9161ec752dc269f3f6a919748a2 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -201,6 +201,7 @@ fn westend_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), ); let payload = runtime::SignedPayload::from_raw( @@ -215,6 +216,7 @@ fn westend_sign_call( (), (), (), + None, ), ); @@ -253,6 +255,7 @@ fn rococo_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), ); let payload = runtime::SignedPayload::from_raw( @@ -267,6 +270,7 @@ fn rococo_sign_call( (), (), (), + None, ), ); diff --git a/polkadot/node/service/src/chain_spec.rs b/polkadot/node/service/src/chain_spec.rs index 1b990af2394b6fba31b0c8ddb2c1839cb2c09fb0..c7019e3f0b22b3bf1793a41f25dc447adfa2cf70 100644 --- a/polkadot/node/service/src/chain_spec.rs +++ b/polkadot/node/service/src/chain_spec.rs @@ -70,11 +70,11 @@ pub struct Extensions { } // Generic chain spec, in case when we don't have the native runtime. -pub type GenericChainSpec = service::GenericChainSpec<(), Extensions>; +pub type GenericChainSpec = service::GenericChainSpec; /// The `ChainSpec` parameterized for the westend runtime. #[cfg(feature = "westend-native")] -pub type WestendChainSpec = service::GenericChainSpec<(), Extensions>; +pub type WestendChainSpec = service::GenericChainSpec; /// The `ChainSpec` parameterized for the westend runtime. // Dummy chain spec, but that is fine when we don't have the native runtime. @@ -83,7 +83,7 @@ pub type WestendChainSpec = GenericChainSpec; /// The `ChainSpec` parameterized for the rococo runtime. #[cfg(feature = "rococo-native")] -pub type RococoChainSpec = service::GenericChainSpec<(), Extensions>; +pub type RococoChainSpec = service::GenericChainSpec; /// The `ChainSpec` parameterized for the rococo runtime. // Dummy chain spec, but that is fine when we don't have the native runtime. diff --git a/polkadot/node/service/src/fake_runtime_api.rs b/polkadot/node/service/src/fake_runtime_api.rs index 89613040dca1fe306aa9734c149f79dad8bbff57..03c4836020d98cdd15719619856db0be38dae66b 100644 --- a/polkadot/node/service/src/fake_runtime_api.rs +++ b/polkadot/node/service/src/fake_runtime_api.rs @@ -272,11 +272,11 @@ sp_api::impl_runtime_apis! { fn generate_proof( _: Vec, _: Option, - ) -> Result<(Vec, sp_mmr_primitives::Proof), sp_mmr_primitives::Error> { + ) -> Result<(Vec, sp_mmr_primitives::LeafProof), sp_mmr_primitives::Error> { unimplemented!() } - fn verify_proof(_: Vec, _: sp_mmr_primitives::Proof) + fn verify_proof(_: Vec, _: sp_mmr_primitives::LeafProof) -> Result<(), sp_mmr_primitives::Error> { unimplemented!() @@ -285,7 +285,7 @@ sp_api::impl_runtime_apis! { fn verify_proof_stateless( _: Hash, _: Vec, - _: sp_mmr_primitives::Proof + _: sp_mmr_primitives::LeafProof ) -> Result<(), sp_mmr_primitives::Error> { unimplemented!() } @@ -398,20 +398,30 @@ sp_api::impl_runtime_apis! { } } - impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { - fn query_acceptable_payment_assets(_: xcm::Version) -> Result, xcm_fee_payment_runtime_api::Error> { + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(_: xcm::Version) -> Result, xcm_fee_payment_runtime_api::fees::Error> { unimplemented!() } - fn query_weight_to_asset_fee(_: Weight, _: VersionedAssetId) -> Result { + fn query_weight_to_asset_fee(_: Weight, _: VersionedAssetId) -> Result { unimplemented!() } - fn query_xcm_weight(_: VersionedXcm<()>) -> Result { + fn query_xcm_weight(_: VersionedXcm<()>) -> Result { unimplemented!() } - fn query_delivery_fees(_: VersionedLocation, _: VersionedXcm<()>) -> Result { + fn query_delivery_fees(_: VersionedLocation, _: VersionedXcm<()>) -> Result { + unimplemented!() + } + } + + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(_: ::Extrinsic) -> Result, xcm_fee_payment_runtime_api::dry_run::Error> { + unimplemented!() + } + + fn dry_run_xcm(_: VersionedLocation, _: VersionedXcm<()>) -> Result, xcm_fee_payment_runtime_api::dry_run::Error> { unimplemented!() } } diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index e5c29172099b4d7b73b4da089a901c63ee0e3a43..7c9b9e05d62c3c72c7a86976ac54490fba426ca5 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -100,8 +100,8 @@ pub use sc_executor::NativeExecutionDispatch; use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; pub use service::{ config::{DatabaseSource, PrometheusConfig}, - ChainSpec, Configuration, Error as SubstrateServiceError, PruningMode, Role, RuntimeGenesis, - TFullBackend, TFullCallExecutor, TFullClient, TaskManager, TransactionPoolOptions, + ChainSpec, Configuration, Error as SubstrateServiceError, PruningMode, Role, TFullBackend, + TFullCallExecutor, TFullClient, TaskManager, TransactionPoolOptions, }; pub use sp_api::{ApiRef, ConstructRuntimeApi, Core as CoreApi, ProvideRuntimeApi}; pub use sp_runtime::{ @@ -750,6 +750,7 @@ pub fn new_full< prepare_workers_hard_max_num, }: NewFullParams, ) -> Result { + use polkadot_availability_recovery::FETCH_CHUNKS_THRESHOLD; use polkadot_node_network_protocol::request_response::IncomingRequest; use sc_network_sync::WarpSyncParams; @@ -914,7 +915,10 @@ pub fn new_full< let (pov_req_receiver, cfg) = IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names); net_config.add_request_response_protocol(cfg); - let (chunk_req_receiver, cfg) = + let (chunk_req_v1_receiver, cfg) = + IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names); + net_config.add_request_response_protocol(cfg); + let (chunk_req_v2_receiver, cfg) = IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names); net_config.add_request_response_protocol(cfg); @@ -956,7 +960,7 @@ pub fn new_full< pvf_execute_workers_max_num: execute_workers_max_num.unwrap_or_else( || match config.chain_spec.identify_chain() { // The intention is to use this logic for gradual increasing from 2 to 4 - // of this configuration chain by chain untill it reaches production chain. + // of this configuration chain by chain until it reaches production chain. Chain::Polkadot | Chain::Kusama => 2, Chain::Rococo | Chain::Westend | Chain::Unknown => 4, }, @@ -988,19 +992,26 @@ pub fn new_full< stagnant_check_interval: Default::default(), stagnant_check_mode: chain_selection_subsystem::StagnantCheckMode::PruneOnly, }; + + // Kusama + testnets get a higher threshold, we are conservative on Polkadot for now. + let fetch_chunks_threshold = + if config.chain_spec.is_polkadot() { None } else { Some(FETCH_CHUNKS_THRESHOLD) }; + Some(ExtendedOverseerGenArgs { keystore, parachains_db, candidate_validation_config, availability_config: AVAILABILITY_CONFIG, pov_req_receiver, - chunk_req_receiver, + chunk_req_v1_receiver, + chunk_req_v2_receiver, statement_req_receiver, candidate_req_v2_receiver, approval_voting_config, dispute_req_receiver, dispute_coordinator_config, chain_selection_config, + fetch_chunks_threshold, }) }; diff --git a/polkadot/node/service/src/overseer.rs b/polkadot/node/service/src/overseer.rs index 26b1446bf515afa342bd53c6237a87e7e750022d..6f35718cd18f25ca6ae4f2c302f2035fa77153bc 100644 --- a/polkadot/node/service/src/overseer.rs +++ b/polkadot/node/service/src/overseer.rs @@ -119,8 +119,10 @@ pub struct ExtendedOverseerGenArgs { pub availability_config: AvailabilityConfig, /// POV request receiver. pub pov_req_receiver: IncomingRequestReceiver, - /// Erasure chunks request receiver. - pub chunk_req_receiver: IncomingRequestReceiver, + /// Erasure chunk request v1 receiver. + pub chunk_req_v1_receiver: IncomingRequestReceiver, + /// Erasure chunk request v2 receiver. + pub chunk_req_v2_receiver: IncomingRequestReceiver, /// Receiver for incoming large statement requests. pub statement_req_receiver: IncomingRequestReceiver, /// Receiver for incoming candidate requests. @@ -133,6 +135,10 @@ pub struct ExtendedOverseerGenArgs { pub dispute_coordinator_config: DisputeCoordinatorConfig, /// Configuration for the chain selection subsystem. pub chain_selection_config: ChainSelectionConfig, + /// Optional availability recovery fetch chunks threshold. If PoV size size is lower + /// than the value put in here we always try to recovery availability from backers. + /// The presence of this parameter here is needed to have different values per chain. + pub fetch_chunks_threshold: Option, } /// Obtain a prepared validator `Overseer`, that is initialized with all default values. @@ -159,13 +165,15 @@ pub fn validator_overseer_builder( candidate_validation_config, availability_config, pov_req_receiver, - chunk_req_receiver, + chunk_req_v1_receiver, + chunk_req_v2_receiver, statement_req_receiver, candidate_req_v2_receiver, approval_voting_config, dispute_req_receiver, dispute_coordinator_config, chain_selection_config, + fetch_chunks_threshold, }: ExtendedOverseerGenArgs, ) -> Result< InitializedOverseerBuilder< @@ -221,7 +229,7 @@ where network_service.clone(), authority_discovery_service.clone(), network_bridge_metrics.clone(), - req_protocol_names, + req_protocol_names.clone(), peerset_protocol_names.clone(), notification_sinks.clone(), )) @@ -236,11 +244,18 @@ where )) .availability_distribution(AvailabilityDistributionSubsystem::new( keystore.clone(), - IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, + IncomingRequestReceivers { + pov_req_receiver, + chunk_req_v1_receiver, + chunk_req_v2_receiver, + }, + req_protocol_names.clone(), Metrics::register(registry)?, )) - .availability_recovery(AvailabilityRecoverySubsystem::with_chunks_if_pov_large( + .availability_recovery(AvailabilityRecoverySubsystem::for_validator( + fetch_chunks_threshold, available_data_req_receiver, + &req_protocol_names, Metrics::register(registry)?, )) .availability_store(AvailabilityStoreSubsystem::new( @@ -385,7 +400,7 @@ pub fn collator_overseer_builder( DummySubsystem, DummySubsystem, DummySubsystem, - ProspectiveParachainsSubsystem, + DummySubsystem, >, Error, > @@ -406,7 +421,7 @@ where network_service.clone(), authority_discovery_service.clone(), network_bridge_metrics.clone(), - req_protocol_names, + req_protocol_names.clone(), peerset_protocol_names.clone(), notification_sinks.clone(), )) @@ -421,7 +436,9 @@ where )) .availability_distribution(DummySubsystem) .availability_recovery(AvailabilityRecoverySubsystem::for_collator( + None, available_data_req_receiver, + &req_protocol_names, Metrics::register(registry)?, )) .availability_store(DummySubsystem) @@ -462,7 +479,7 @@ where .dispute_coordinator(DummySubsystem) .dispute_distribution(DummySubsystem) .chain_selection(DummySubsystem) - .prospective_parachains(ProspectiveParachainsSubsystem::new(Metrics::register(registry)?)) + .prospective_parachains(DummySubsystem) .activation_external_listeners(Default::default()) .span_per_active_leaf(Default::default()) .active_leaves(Default::default()) diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index e534ac18e4b36bdb40737d4ad7052a008c0497e7..ebd9322e9f74a7b7f7d44399ac5ea5904629a97b 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -28,6 +28,7 @@ polkadot-primitives = { path = "../../primitives" } polkadot-node-network-protocol = { path = "../network/protocol" } polkadot-availability-recovery = { path = "../network/availability-recovery", features = ["subsystem-benchmarks"] } polkadot-availability-distribution = { path = "../network/availability-distribution" } +polkadot-statement-distribution = { path = "../network/statement-distribution" } polkadot-node-core-av-store = { path = "../core/av-store" } polkadot-node-core-chain-api = { path = "../core/chain-api" } polkadot-availability-bitfield-distribution = { path = "../network/bitfield-distribution" } @@ -55,7 +56,7 @@ rand_distr = "0.4.3" bitvec = "1.0.1" kvdb-memorydb = "0.13.0" -parity-scale-codec = { version = "3.6.1", features = ["derive", "std"] } +parity-scale-codec = { version = "3.6.12", features = ["derive", "std"] } tokio = { version = "1.24.2", features = ["parking_lot", "rt-multi-thread"] } clap-num = "1.0.2" polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } @@ -66,7 +67,7 @@ sc-network-types = { path = "../../../substrate/client/network/types" } sc-service = { path = "../../../substrate/client/service" } sp-consensus = { path = "../../../substrate/primitives/consensus/common" } polkadot-node-metrics = { path = "../metrics" } -itertools = "0.11.0" +itertools = "0.11" polkadot-primitives-test-helpers = { path = "../../primitives/test-helpers" } prometheus_endpoint = { package = "substrate-prometheus-endpoint", path = "../../../substrate/utils/prometheus" } prometheus = { version = "0.13.0", default-features = false } @@ -88,6 +89,7 @@ paste = "1.0.14" orchestra = { version = "0.3.5", default-features = false, features = ["futures_channel"] } pyroscope = "0.5.7" pyroscope_pprofrs = "0.2.7" +strum = { version = "0.24", features = ["derive"] } [features] default = [] diff --git a/polkadot/node/subsystem-bench/examples/availability_read.yaml b/polkadot/node/subsystem-bench/examples/availability_read.yaml index 82355b0e2973aaff490a5c2d3ed54d37c61430de..263a6988242e22c4c6f947dbd472a34167ef7453 100644 --- a/polkadot/node/subsystem-bench/examples/availability_read.yaml +++ b/polkadot/node/subsystem-bench/examples/availability_read.yaml @@ -1,8 +1,8 @@ TestConfiguration: # Test 1 - objective: !DataAvailabilityRead - fetch_from_backers: true - n_validators: 300 + strategy: FullFromBackers + n_validators: 500 n_cores: 20 min_pov_size: 5120 max_pov_size: 5120 @@ -16,7 +16,7 @@ TestConfiguration: # Test 2 - objective: !DataAvailabilityRead - fetch_from_backers: true + strategy: FullFromBackers n_validators: 500 n_cores: 20 min_pov_size: 5120 @@ -31,7 +31,7 @@ TestConfiguration: # Test 3 - objective: !DataAvailabilityRead - fetch_from_backers: true + strategy: FullFromBackers n_validators: 1000 n_cores: 20 min_pov_size: 5120 diff --git a/polkadot/node/subsystem-bench/examples/statement_distribution.yaml b/polkadot/node/subsystem-bench/examples/statement_distribution.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e86669ffefc356430c6ce4aa0ccd2ed5fca77474 --- /dev/null +++ b/polkadot/node/subsystem-bench/examples/statement_distribution.yaml @@ -0,0 +1,5 @@ +TestConfiguration: +- objective: StatementDistribution + num_blocks: 10 + n_cores: 100 + n_validators: 500 diff --git a/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs index 10953b6c7839d8ea2a4e0396a4ee37b9875828e9..346a058b9796e2ccfe0aab2b6fbbac6fb1f600d7 100644 --- a/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs +++ b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs @@ -20,7 +20,7 @@ use clap::Parser; use color_eyre::eyre; use colored::Colorize; -use polkadot_subsystem_bench::{approval, availability, configuration}; +use polkadot_subsystem_bench::{approval, availability, configuration, statement}; use pyroscope::PyroscopeAgent; use pyroscope_pprofrs::{pprof_backend, PprofConfig}; use serde::{Deserialize, Serialize}; @@ -40,6 +40,8 @@ pub enum TestObjective { DataAvailabilityWrite, /// Benchmark the approval-voting and approval-distribution subsystems. ApprovalVoting(approval::ApprovalsOptions), + // Benchmark the statement-distribution subsystem + StatementDistribution, } impl std::fmt::Display for TestObjective { @@ -51,6 +53,7 @@ impl std::fmt::Display for TestObjective { Self::DataAvailabilityRead(_) => "DataAvailabilityRead", Self::DataAvailabilityWrite => "DataAvailabilityWrite", Self::ApprovalVoting(_) => "ApprovalVoting", + Self::StatementDistribution => "StatementDistribution", } ) } @@ -142,11 +145,8 @@ impl BenchCli { availability::TestDataAvailability::Read(opts), true, ); - env.runtime().block_on(availability::benchmark_availability_read( - &benchmark_name, - &mut env, - &state, - )) + env.runtime() + .block_on(availability::benchmark_availability_read(&mut env, &state)) }, TestObjective::DataAvailabilityWrite => { let state = availability::TestState::new(&test_config); @@ -155,23 +155,22 @@ impl BenchCli { availability::TestDataAvailability::Write, true, ); - env.runtime().block_on(availability::benchmark_availability_write( - &benchmark_name, - &mut env, - &state, - )) + env.runtime() + .block_on(availability::benchmark_availability_write(&mut env, &state)) }, TestObjective::ApprovalVoting(ref options) => { let (mut env, state) = approval::prepare_test(test_config.clone(), options.clone(), true); - env.runtime().block_on(approval::bench_approvals( - &benchmark_name, - &mut env, - state, - )) + env.runtime().block_on(approval::bench_approvals(&mut env, state)) + }, + TestObjective::StatementDistribution => { + let state = statement::TestState::new(&test_config); + let (mut env, _protocol_config) = statement::prepare_test(&state, true); + env.runtime() + .block_on(statement::benchmark_statement_distribution(&mut env, &state)) }, }; - println!("{}", usage); + println!("\n{}\n{}", benchmark_name.purple(), usage); } if let Some(agent_running) = agent_running { diff --git a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs index 219b2cb515d7da5df52df9902c0da28e09838763..e4a6c207970febc06fc364237e8f277728ec905e 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs @@ -91,7 +91,7 @@ pub struct PeerMessagesGenerator { impl PeerMessagesGenerator { /// Generates messages by spawning a blocking task in the background which begins creating - /// the assignments/approvals and peer view changes at the begining of each block. + /// the assignments/approvals and peer view changes at the beginning of each block. pub fn generate_messages(mut self, spawn_task_handle: &SpawnTaskHandle) { spawn_task_handle.spawn("generate-messages", "generate-messages", async move { for block_info in &self.blocks { diff --git a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs index 6ab5b86baede30117489b892490dd14b415650e7..2e5831276ad3f3889e454fc89f378531d15db0f0 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs @@ -30,7 +30,7 @@ use crate::{ mock::{ chain_api::{ChainApiState, MockChainApi}, network_bridge::{MockNetworkBridgeRx, MockNetworkBridgeTx}, - runtime_api::MockRuntimeApi, + runtime_api::{MockRuntimeApi, MockRuntimeApiCoreState}, AlwaysSupportsParachains, TestSyncOracle, }, network::{ @@ -98,7 +98,7 @@ pub(crate) const TEST_CONFIG: ApprovalVotingConfig = ApprovalVotingConfig { const DATA_COL: u32 = 0; /// Start generating messages for a slot into the future, so that the -/// generation nevers falls behind the current slot. +/// generation never falls behind the current slot. const BUFFER_FOR_GENERATION_MILLIS: u64 = 30_000; /// Parameters specific to the approvals benchmark @@ -465,8 +465,9 @@ impl ApprovalTestState { } } +#[async_trait::async_trait] impl HandleNetworkMessage for ApprovalTestState { - fn handle( + async fn handle( &self, _message: crate::network::NetworkMessage, _node_sender: &mut futures::channel::mpsc::UnboundedSender, @@ -807,6 +808,7 @@ fn build_overseer( state.candidate_events_by_block(), Some(state.babe_epoch.clone()), 1, + MockRuntimeApiCoreState::Occupied, ); let mock_tx_bridge = MockNetworkBridgeTx::new( network.clone(), @@ -886,7 +888,6 @@ fn prepare_test_inner( } pub async fn bench_approvals( - benchmark_name: &str, env: &mut TestEnvironment, mut state: ApprovalTestState, ) -> BenchmarkUsage { @@ -898,12 +899,11 @@ pub async fn bench_approvals( env.registry().clone(), ) .await; - bench_approvals_run(benchmark_name, env, state, producer_rx).await + bench_approvals_run(env, state, producer_rx).await } /// Runs the approval benchmark. pub async fn bench_approvals_run( - benchmark_name: &str, env: &mut TestEnvironment, state: ApprovalTestState, producer_rx: oneshot::Receiver<()>, @@ -915,7 +915,9 @@ pub async fn bench_approvals_run( // First create the initialization messages that make sure that then node under // tests receives notifications about the topology used and the connected peers. - let mut initialization_messages = env.network().generate_peer_connected(); + let mut initialization_messages = env.network().generate_peer_connected(|e| { + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::NetworkBridgeUpdate(e)) + }); initialization_messages.extend(generate_new_session_topology( &state.test_authorities, ValidatorIndex(NODE_UNDER_TEST), @@ -1068,5 +1070,5 @@ pub async fn bench_approvals_run( state.total_unique_messages.load(std::sync::atomic::Ordering::SeqCst) ); - env.collect_resource_usage(benchmark_name, &["approval-distribution", "approval-voting"]) + env.collect_resource_usage(&["approval-distribution", "approval-voting"]) } diff --git a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs index 5b93c3d862de683ea35dde9f0a9e313b1a77ad4d..52944ffb08f3eff41915aa37b8661c68edd78dbf 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -17,12 +17,14 @@ use crate::{ availability::av_store_helpers::new_av_store, dummy_builder, - environment::{TestEnvironment, TestEnvironmentDependencies, GENESIS_HASH}, + environment::{TestEnvironment, TestEnvironmentDependencies}, mock::{ - av_store::{self, MockAvailabilityStore, NetworkAvailabilityState}, + av_store::{MockAvailabilityStore, NetworkAvailabilityState}, chain_api::{ChainApiState, MockChainApi}, network_bridge::{self, MockNetworkBridgeRx, MockNetworkBridgeTx}, - runtime_api::{self, MockRuntimeApi}, + runtime_api::{ + node_features_with_chunk_mapping_enabled, MockRuntimeApi, MockRuntimeApiCoreState, + }, AlwaysSupportsParachains, }, network::new_network, @@ -30,16 +32,17 @@ use crate::{ }; use colored::Colorize; use futures::{channel::oneshot, stream::FuturesUnordered, StreamExt}; + use parity_scale_codec::Encode; use polkadot_availability_bitfield_distribution::BitfieldDistribution; use polkadot_availability_distribution::{ AvailabilityDistributionSubsystem, IncomingRequestReceivers, }; -use polkadot_availability_recovery::AvailabilityRecoverySubsystem; +use polkadot_availability_recovery::{AvailabilityRecoverySubsystem, RecoveryStrategyKind}; use polkadot_node_core_av_store::AvailabilityStoreSubsystem; use polkadot_node_metrics::metrics::Metrics; use polkadot_node_network_protocol::{ - request_response::{IncomingRequest, ReqProtocolNames}, + request_response::{v1, v2, IncomingRequest}, OurView, }; use polkadot_node_subsystem::{ @@ -51,12 +54,13 @@ use polkadot_node_subsystem_types::{ Span, }; use polkadot_overseer::{metrics::Metrics as OverseerMetrics, Handle as OverseerHandle}; -use polkadot_primitives::{Block, GroupIndex, Hash}; +use polkadot_primitives::{Block, CoreIndex, GroupIndex, Hash}; use sc_network::request_responses::{IncomingRequest as RawIncomingRequest, ProtocolConfig}; +use std::{ops::Sub, sync::Arc, time::Instant}; +use strum::Display; use sc_service::SpawnTaskHandle; use serde::{Deserialize, Serialize}; -use std::{ops::Sub, sync::Arc, time::Instant}; pub use test_state::TestState; mod av_store_helpers; @@ -64,15 +68,26 @@ mod test_state; const LOG_TARGET: &str = "subsystem-bench::availability"; +#[derive(clap::ValueEnum, Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Display)] +#[value(rename_all = "kebab-case")] +#[strum(serialize_all = "kebab-case")] +pub enum Strategy { + /// Regular random chunk recovery. This is also the fallback for the next strategies. + Chunks, + /// Recovery from systematic chunks. Much faster than regular chunk recovery becasue it avoid + /// doing the reed-solomon reconstruction. + Systematic, + /// Fetch the full availability datafrom backers first. Saves CPU as we don't need to + /// re-construct from chunks. Typically this is only faster if nodes have enough bandwidth. + FullFromBackers, +} + #[derive(Debug, Clone, Serialize, Deserialize, clap::Parser)] #[clap(rename_all = "kebab-case")] #[allow(missing_docs)] pub struct DataAvailabilityReadOptions { - #[clap(short, long, default_value_t = false)] - /// Turbo boost AD Read by fetching the full availability datafrom backers first. Saves CPU as - /// we don't need to re-construct from chunks. Typically this is only faster if nodes have - /// enough bandwidth. - pub fetch_from_backers: bool, + #[clap(short, long, default_value_t = Strategy::Systematic)] + pub strategy: Strategy, } pub enum TestDataAvailability { @@ -84,7 +99,7 @@ fn build_overseer_for_availability_read( spawn_task_handle: SpawnTaskHandle, runtime_api: MockRuntimeApi, av_store: MockAvailabilityStore, - network_bridge: (MockNetworkBridgeTx, MockNetworkBridgeRx), + (network_bridge_tx, network_bridge_rx): (MockNetworkBridgeTx, MockNetworkBridgeRx), availability_recovery: AvailabilityRecoverySubsystem, dependencies: &TestEnvironmentDependencies, ) -> (Overseer, AlwaysSupportsParachains>, OverseerHandle) { @@ -95,8 +110,8 @@ fn build_overseer_for_availability_read( let builder = dummy .replace_runtime_api(|_| runtime_api) .replace_availability_store(|_| av_store) - .replace_network_bridge_tx(|_| network_bridge.0) - .replace_network_bridge_rx(|_| network_bridge.1) + .replace_network_bridge_tx(|_| network_bridge_tx) + .replace_network_bridge_rx(|_| network_bridge_rx) .replace_availability_recovery(|_| availability_recovery); let (overseer, raw_handle) = @@ -109,7 +124,7 @@ fn build_overseer_for_availability_read( fn build_overseer_for_availability_write( spawn_task_handle: SpawnTaskHandle, runtime_api: MockRuntimeApi, - network_bridge: (MockNetworkBridgeTx, MockNetworkBridgeRx), + (network_bridge_tx, network_bridge_rx): (MockNetworkBridgeTx, MockNetworkBridgeRx), availability_distribution: AvailabilityDistributionSubsystem, chain_api: MockChainApi, availability_store: AvailabilityStoreSubsystem, @@ -123,8 +138,8 @@ fn build_overseer_for_availability_write( let builder = dummy .replace_runtime_api(|_| runtime_api) .replace_availability_store(|_| availability_store) - .replace_network_bridge_tx(|_| network_bridge.0) - .replace_network_bridge_rx(|_| network_bridge.1) + .replace_network_bridge_tx(|_| network_bridge_tx) + .replace_network_bridge_rx(|_| network_bridge_rx) .replace_chain_api(|_| chain_api) .replace_bitfield_distribution(|_| bitfield_distribution) // This is needed to test own chunk recovery for `n_cores`. @@ -142,10 +157,14 @@ pub fn prepare_test( with_prometheus_endpoint: bool, ) -> (TestEnvironment, Vec) { let dependencies = TestEnvironmentDependencies::default(); + let availability_state = NetworkAvailabilityState { candidate_hashes: state.candidate_hashes.clone(), + candidate_hash_to_core_index: state.candidate_hash_to_core_index.clone(), available_data: state.available_data.clone(), chunks: state.chunks.clone(), + chunk_indices: state.chunk_indices.clone(), + req_protocol_names: state.req_protocol_names.clone(), }; let mut req_cfgs = Vec::new(); @@ -153,20 +172,31 @@ pub fn prepare_test( let (collation_req_receiver, collation_req_cfg) = IncomingRequest::get_config_receiver::< Block, sc_network::NetworkWorker, - >(&ReqProtocolNames::new(GENESIS_HASH, None)); + >(&state.req_protocol_names); req_cfgs.push(collation_req_cfg); let (pov_req_receiver, pov_req_cfg) = IncomingRequest::get_config_receiver::< Block, sc_network::NetworkWorker, - >(&ReqProtocolNames::new(GENESIS_HASH, None)); - - let (chunk_req_receiver, chunk_req_cfg) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker, - >(&ReqProtocolNames::new(GENESIS_HASH, None)); + >(&state.req_protocol_names); req_cfgs.push(pov_req_cfg); + let (chunk_req_v1_receiver, chunk_req_v1_cfg) = + IncomingRequest::::get_config_receiver::< + Block, + sc_network::NetworkWorker, + >(&state.req_protocol_names); + + // We won't use v1 chunk fetching requests, but we need to keep the inbound queue alive. + // Otherwise, av-distribution subsystem will terminate. + std::mem::forget(chunk_req_v1_cfg); + + let (chunk_req_v2_receiver, chunk_req_v2_cfg) = + IncomingRequest::::get_config_receiver::< + Block, + sc_network::NetworkWorker, + >(&state.req_protocol_names); + let (network, network_interface, network_receiver) = new_network( &state.config, &dependencies, @@ -180,37 +210,48 @@ pub fn prepare_test( state.test_authorities.clone(), ); let network_bridge_rx = - network_bridge::MockNetworkBridgeRx::new(network_receiver, Some(chunk_req_cfg)); + network_bridge::MockNetworkBridgeRx::new(network_receiver, Some(chunk_req_v2_cfg)); - let runtime_api = runtime_api::MockRuntimeApi::new( + let runtime_api = MockRuntimeApi::new( state.config.clone(), state.test_authorities.clone(), state.candidate_receipts.clone(), Default::default(), Default::default(), 0, + MockRuntimeApiCoreState::Occupied, ); let (overseer, overseer_handle) = match &mode { TestDataAvailability::Read(options) => { - let use_fast_path = options.fetch_from_backers; - - let subsystem = if use_fast_path { - AvailabilityRecoverySubsystem::with_fast_path( + let subsystem = match options.strategy { + Strategy::FullFromBackers => + AvailabilityRecoverySubsystem::with_recovery_strategy_kind( + collation_req_receiver, + &state.req_protocol_names, + Metrics::try_register(&dependencies.registry).unwrap(), + RecoveryStrategyKind::BackersFirstAlways, + ), + Strategy::Chunks => AvailabilityRecoverySubsystem::with_recovery_strategy_kind( collation_req_receiver, + &state.req_protocol_names, Metrics::try_register(&dependencies.registry).unwrap(), - ) - } else { - AvailabilityRecoverySubsystem::with_chunks_only( + RecoveryStrategyKind::ChunksAlways, + ), + Strategy::Systematic => AvailabilityRecoverySubsystem::with_recovery_strategy_kind( collation_req_receiver, + &state.req_protocol_names, Metrics::try_register(&dependencies.registry).unwrap(), - ) + RecoveryStrategyKind::SystematicChunks, + ), }; // Use a mocked av-store. - let av_store = av_store::MockAvailabilityStore::new( + let av_store = MockAvailabilityStore::new( state.chunks.clone(), + state.chunk_indices.clone(), state.candidate_hashes.clone(), + state.candidate_hash_to_core_index.clone(), ); build_overseer_for_availability_read( @@ -225,7 +266,12 @@ pub fn prepare_test( TestDataAvailability::Write => { let availability_distribution = AvailabilityDistributionSubsystem::new( state.test_authorities.keyring.keystore(), - IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, + IncomingRequestReceivers { + pov_req_receiver, + chunk_req_v1_receiver, + chunk_req_v2_receiver, + }, + state.req_protocol_names.clone(), Metrics::try_register(&dependencies.registry).unwrap(), ); @@ -261,7 +307,6 @@ pub fn prepare_test( } pub async fn benchmark_availability_read( - benchmark_name: &str, env: &mut TestEnvironment, state: &TestState, ) -> BenchmarkUsage { @@ -295,6 +340,7 @@ pub async fn benchmark_availability_read( Some(GroupIndex( candidate_num as u32 % (std::cmp::max(5, config.n_cores) / 5) as u32, )), + Some(*state.candidate_hash_to_core_index.get(&candidate.hash()).unwrap()), tx, ), ); @@ -326,11 +372,10 @@ pub async fn benchmark_availability_read( ); env.stop().await; - env.collect_resource_usage(benchmark_name, &["availability-recovery"]) + env.collect_resource_usage(&["availability-recovery"]) } pub async fn benchmark_availability_write( - benchmark_name: &str, env: &mut TestEnvironment, state: &TestState, ) -> BenchmarkUsage { @@ -340,7 +385,7 @@ pub async fn benchmark_availability_write( env.metrics().set_n_cores(config.n_cores); gum::info!(target: LOG_TARGET, "Seeding availability store with candidates ..."); - for backed_candidate in state.backed_candidates.clone() { + for (core_index, backed_candidate) in state.backed_candidates.clone().into_iter().enumerate() { let candidate_index = *state.candidate_hashes.get(&backed_candidate.hash()).unwrap(); let available_data = state.available_data[candidate_index].clone(); let (tx, rx) = oneshot::channel(); @@ -351,6 +396,8 @@ pub async fn benchmark_availability_write( available_data, expected_erasure_root: backed_candidate.descriptor().erasure_root, tx, + core_index: CoreIndex(core_index as u32), + node_features: node_features_with_chunk_mapping_enabled(), }, )) .await; @@ -459,8 +506,9 @@ pub async fn benchmark_availability_write( ); env.stop().await; - env.collect_resource_usage( - benchmark_name, - &["availability-distribution", "bitfield-distribution", "availability-store"], - ) + env.collect_resource_usage(&[ + "availability-distribution", + "bitfield-distribution", + "availability-store", + ]) } diff --git a/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs index c328ffedf916e1ae9ce7fcd05e25750e01dc7506..5d443734bb387fcdbdce68e03839b314a10106d0 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs @@ -14,22 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use crate::configuration::{TestAuthorities, TestConfiguration}; +use crate::{ + configuration::{TestAuthorities, TestConfiguration}, + environment::GENESIS_HASH, + mock::runtime_api::node_features_with_chunk_mapping_enabled, +}; use bitvec::bitvec; use colored::Colorize; use itertools::Itertools; use parity_scale_codec::Encode; use polkadot_node_network_protocol::{ - request_response::v1::ChunkFetchingRequest, Versioned, VersionedValidationProtocol, + request_response::{v2::ChunkFetchingRequest, ReqProtocolNames}, + Versioned, VersionedValidationProtocol, }; use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV}; use polkadot_node_subsystem_test_helpers::{ derive_erasure_chunks_with_proofs_and_root, mock::new_block_import_info, }; +use polkadot_node_subsystem_util::availability_chunks::availability_chunk_indices; use polkadot_overseer::BlockInfo; use polkadot_primitives::{ - AvailabilityBitfield, BlockNumber, CandidateHash, CandidateReceipt, Hash, HeadData, Header, - PersistedValidationData, Signed, SigningContext, ValidatorIndex, + AvailabilityBitfield, BlockNumber, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, + Hash, HeadData, Header, PersistedValidationData, Signed, SigningContext, ValidatorIndex, }; use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; use sp_core::H256; @@ -49,14 +55,20 @@ pub struct TestState { pub pov_size_to_candidate: HashMap, // Map from generated candidate hashes to candidate index in `available_data` and `chunks`. pub candidate_hashes: HashMap, + // Map from candidate hash to occupied core index. + pub candidate_hash_to_core_index: HashMap, // Per candidate index receipts. pub candidate_receipt_templates: Vec, // Per candidate index `AvailableData` pub available_data: Vec, - // Per candiadte index chunks + // Per candidate index chunks pub chunks: Vec>, + // Per-core ValidatorIndex -> ChunkIndex mapping + pub chunk_indices: Vec>, // Per relay chain block - candidate backed by our backing group pub backed_candidates: Vec, + // Request protcol names + pub req_protocol_names: ReqProtocolNames, // Relay chain block infos pub block_infos: Vec, // Chung fetching requests for backed candidates @@ -89,6 +101,9 @@ impl TestState { candidate_receipts: Default::default(), block_headers: Default::default(), test_authorities: config.generate_authorities(), + req_protocol_names: ReqProtocolNames::new(GENESIS_HASH, None), + chunk_indices: Default::default(), + candidate_hash_to_core_index: Default::default(), }; // we use it for all candidates. @@ -99,6 +114,17 @@ impl TestState { relay_parent_storage_root: Default::default(), }; + test_state.chunk_indices = (0..config.n_cores) + .map(|core_index| { + availability_chunk_indices( + Some(&node_features_with_chunk_mapping_enabled()), + config.n_validators, + CoreIndex(core_index as u32), + ) + .unwrap() + }) + .collect(); + // For each unique pov we create a candidate receipt. for (index, pov_size) in config.pov_sizes().iter().cloned().unique().enumerate() { gum::info!(target: LOG_TARGET, index, pov_size, "{}", "Generating template candidate".bright_blue()); @@ -167,6 +193,11 @@ impl TestState { // Store the new candidate in the state test_state.candidate_hashes.insert(candidate_receipt.hash(), candidate_index); + let core_index = (index % config.n_cores) as u32; + test_state + .candidate_hash_to_core_index + .insert(candidate_receipt.hash(), core_index.into()); + gum::debug!(target: LOG_TARGET, candidate_hash = ?candidate_receipt.hash(), "new candidate"); candidate_receipt diff --git a/polkadot/node/subsystem-bench/src/lib/configuration.rs b/polkadot/node/subsystem-bench/src/lib/configuration.rs index 1e0efb72a7dff163898bcf6974ce9bc048bfa086..f614a5e552a803f0a6e2d2475efc5a824b64e9a2 100644 --- a/polkadot/node/subsystem-bench/src/lib/configuration.rs +++ b/polkadot/node/subsystem-bench/src/lib/configuration.rs @@ -18,12 +18,13 @@ use crate::keyring::Keyring; use itertools::Itertools; -use polkadot_primitives::{AssignmentId, AuthorityDiscoveryId, ValidatorId}; +use polkadot_primitives::{AssignmentId, AuthorityDiscoveryId, ValidatorId, ValidatorPair}; use rand::thread_rng; use rand_distr::{Distribution, Normal, Uniform}; use sc_network_types::PeerId; use serde::{Deserialize, Serialize}; use sp_consensus_babe::AuthorityId; +use sp_core::Pair; use std::collections::HashMap; /// Peer networking latency configuration. @@ -89,6 +90,15 @@ fn default_n_delay_tranches() -> usize { fn default_no_show_slots() -> usize { 3 } +fn default_minimum_backing_votes() -> u32 { + 2 +} +fn default_max_candidate_depth() -> u32 { + 3 +} +fn default_allowed_ancestry_len() -> u32 { + 2 +} /// The test input parameters #[derive(Clone, Debug, Serialize, Deserialize)] @@ -137,6 +147,15 @@ pub struct TestConfiguration { pub connectivity: usize, /// Number of blocks to run the test for pub num_blocks: usize, + /// Number of minimum backing votes + #[serde(default = "default_minimum_backing_votes")] + pub minimum_backing_votes: u32, + /// Async Backing max_candidate_depth + #[serde(default = "default_max_candidate_depth")] + pub max_candidate_depth: u32, + /// Async Backing allowed_ancestry_len + #[serde(default = "default_allowed_ancestry_len")] + pub allowed_ancestry_len: u32, } impl Default for TestConfiguration { @@ -158,6 +177,9 @@ impl Default for TestConfiguration { latency: default_peer_latency(), connectivity: default_connectivity(), num_blocks: Default::default(), + minimum_backing_votes: default_minimum_backing_votes(), + max_candidate_depth: default_max_candidate_depth(), + allowed_ancestry_len: default_allowed_ancestry_len(), } } } @@ -208,6 +230,11 @@ impl TestConfiguration { .map(|(peer_id, authority_id)| (*peer_id, authority_id.clone())) .collect(); + let validator_pairs = key_seeds + .iter() + .map(|seed| ValidatorPair::from_string_with_seed(seed, None).unwrap().0) + .collect(); + TestAuthorities { keyring, validator_public, @@ -217,6 +244,7 @@ impl TestConfiguration { validator_assignment_id, key_seeds, peer_id_to_authority, + validator_pairs, } } } @@ -246,6 +274,7 @@ pub struct TestAuthorities { pub key_seeds: Vec, pub peer_ids: Vec, pub peer_id_to_authority: HashMap, + pub validator_pairs: Vec, } /// Sample latency (in milliseconds) from a normal distribution with parameters diff --git a/polkadot/node/subsystem-bench/src/lib/environment.rs b/polkadot/node/subsystem-bench/src/lib/environment.rs index 42955d0302232f35e387a044e34a0c7d665512e8..a63f90da50b3aabcacca38874d723e7166173842 100644 --- a/polkadot/node/subsystem-bench/src/lib/environment.rs +++ b/polkadot/node/subsystem-bench/src/lib/environment.rs @@ -351,13 +351,8 @@ impl TestEnvironment { } } - pub fn collect_resource_usage( - &self, - benchmark_name: &str, - subsystems_under_test: &[&str], - ) -> BenchmarkUsage { + pub fn collect_resource_usage(&self, subsystems_under_test: &[&str]) -> BenchmarkUsage { BenchmarkUsage { - benchmark_name: benchmark_name.to_string(), network_usage: self.network_usage(), cpu_usage: self.cpu_usage(subsystems_under_test), } diff --git a/polkadot/node/subsystem-bench/src/lib/lib.rs b/polkadot/node/subsystem-bench/src/lib/lib.rs index ef2724abc98920c79d8dd9d94f97bed32b0ab8e2..e18227af8be349debc38043529bd1649c67e1c56 100644 --- a/polkadot/node/subsystem-bench/src/lib/lib.rs +++ b/polkadot/node/subsystem-bench/src/lib/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -// The validator index that represent the node that is under test. +// The validator index that represents the node that is under test. pub const NODE_UNDER_TEST: u32 = 0; pub mod approval; @@ -25,5 +25,6 @@ pub(crate) mod environment; pub(crate) mod keyring; pub(crate) mod mock; pub(crate) mod network; +pub mod statement; pub mod usage; pub mod utils; diff --git a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs index fba33523be85dbfd241bc1fcf42d8f8069ebf95c..14ec4ccb4c32a1d0ffd3422bc61c5a87ac962dab 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs @@ -20,7 +20,7 @@ use crate::network::{HandleNetworkMessage, NetworkMessage}; use futures::{channel::oneshot, FutureExt}; use parity_scale_codec::Encode; use polkadot_node_network_protocol::request_response::{ - v1::{AvailableDataFetchingResponse, ChunkFetchingResponse, ChunkResponse}, + v1::AvailableDataFetchingResponse, v2::ChunkFetchingResponse, Protocol, ReqProtocolNames, Requests, }; use polkadot_node_primitives::{AvailableData, ErasureChunk}; @@ -28,13 +28,14 @@ use polkadot_node_subsystem::{ messages::AvailabilityStoreMessage, overseer, SpawnedSubsystem, SubsystemError, }; use polkadot_node_subsystem_types::OverseerSignal; -use polkadot_primitives::CandidateHash; -use sc_network::ProtocolName; +use polkadot_primitives::{CandidateHash, ChunkIndex, CoreIndex, ValidatorIndex}; use std::collections::HashMap; pub struct AvailabilityStoreState { candidate_hashes: HashMap, chunks: Vec>, + chunk_indices: Vec>, + candidate_hash_to_core_index: HashMap, } const LOG_TARGET: &str = "subsystem-bench::av-store-mock"; @@ -43,21 +44,25 @@ const LOG_TARGET: &str = "subsystem-bench::av-store-mock"; /// used in a test. #[derive(Clone)] pub struct NetworkAvailabilityState { + pub req_protocol_names: ReqProtocolNames, pub candidate_hashes: HashMap, pub available_data: Vec, pub chunks: Vec>, + pub chunk_indices: Vec>, + pub candidate_hash_to_core_index: HashMap, } // Implement access to the state. +#[async_trait::async_trait] impl HandleNetworkMessage for NetworkAvailabilityState { - fn handle( + async fn handle( &self, message: NetworkMessage, _node_sender: &mut futures::channel::mpsc::UnboundedSender, ) -> Option { match message { NetworkMessage::RequestFromNode(peer, request) => match request { - Requests::ChunkFetchingV1(outgoing_request) => { + Requests::ChunkFetching(outgoing_request) => { gum::debug!(target: LOG_TARGET, request = ?outgoing_request, "Received `RequestFromNode`"); let validator_index: usize = outgoing_request.payload.index.0 as usize; let candidate_hash = outgoing_request.payload.candidate_hash; @@ -68,11 +73,22 @@ impl HandleNetworkMessage for NetworkAvailabilityState { .expect("candidate was generated previously; qed"); gum::warn!(target: LOG_TARGET, ?candidate_hash, candidate_index, "Candidate mapped to index"); - let chunk: ChunkResponse = - self.chunks.get(*candidate_index).unwrap()[validator_index].clone().into(); + let candidate_chunks = self.chunks.get(*candidate_index).unwrap(); + let chunk_indices = self + .chunk_indices + .get( + self.candidate_hash_to_core_index.get(&candidate_hash).unwrap().0 + as usize, + ) + .unwrap(); + + let chunk = candidate_chunks + .get(chunk_indices.get(validator_index).unwrap().0 as usize) + .unwrap(); + let response = Ok(( - ChunkFetchingResponse::from(Some(chunk)).encode(), - ProtocolName::Static("dummy"), + ChunkFetchingResponse::from(Some(chunk.clone())).encode(), + self.req_protocol_names.get_name(Protocol::ChunkFetchingV2), )); if let Err(err) = outgoing_request.pending_response.send(response) { @@ -93,7 +109,7 @@ impl HandleNetworkMessage for NetworkAvailabilityState { let response = Ok(( AvailableDataFetchingResponse::from(Some(available_data)).encode(), - ProtocolName::Static("dummy"), + self.req_protocol_names.get_name(Protocol::AvailableDataFetchingV1), )); outgoing_request .pending_response @@ -118,16 +134,25 @@ pub struct MockAvailabilityStore { impl MockAvailabilityStore { pub fn new( chunks: Vec>, + chunk_indices: Vec>, candidate_hashes: HashMap, + candidate_hash_to_core_index: HashMap, ) -> MockAvailabilityStore { - Self { state: AvailabilityStoreState { chunks, candidate_hashes } } + Self { + state: AvailabilityStoreState { + chunks, + candidate_hashes, + chunk_indices, + candidate_hash_to_core_index, + }, + } } async fn respond_to_query_all_request( &self, candidate_hash: CandidateHash, - send_chunk: impl Fn(usize) -> bool, - tx: oneshot::Sender>, + send_chunk: impl Fn(ValidatorIndex) -> bool, + tx: oneshot::Sender>, ) { let candidate_index = self .state @@ -136,15 +161,27 @@ impl MockAvailabilityStore { .expect("candidate was generated previously; qed"); gum::debug!(target: LOG_TARGET, ?candidate_hash, candidate_index, "Candidate mapped to index"); - let v = self - .state - .chunks - .get(*candidate_index) - .unwrap() - .iter() - .filter(|c| send_chunk(c.index.0 as usize)) - .cloned() - .collect(); + let n_validators = self.state.chunks[0].len(); + let candidate_chunks = self.state.chunks.get(*candidate_index).unwrap(); + let core_index = self.state.candidate_hash_to_core_index.get(&candidate_hash).unwrap(); + // We'll likely only send our chunk, so use capacity 1. + let mut v = Vec::with_capacity(1); + + for validator_index in 0..n_validators { + if !send_chunk(ValidatorIndex(validator_index as u32)) { + continue; + } + let chunk_index = self + .state + .chunk_indices + .get(core_index.0 as usize) + .unwrap() + .get(validator_index) + .unwrap(); + + let chunk = candidate_chunks.get(chunk_index.0 as usize).unwrap().clone(); + v.push((ValidatorIndex(validator_index as u32), chunk.clone())); + } let _ = tx.send(v); } @@ -181,8 +218,12 @@ impl MockAvailabilityStore { AvailabilityStoreMessage::QueryAllChunks(candidate_hash, tx) => { // We always have our own chunk. gum::debug!(target: LOG_TARGET, candidate_hash = ?candidate_hash, "Responding to QueryAllChunks"); - self.respond_to_query_all_request(candidate_hash, |index| index == 0, tx) - .await; + self.respond_to_query_all_request( + candidate_hash, + |index| index == 0.into(), + tx, + ) + .await; }, AvailabilityStoreMessage::QueryChunkSize(candidate_hash, tx) => { gum::debug!(target: LOG_TARGET, candidate_hash = ?candidate_hash, "Responding to QueryChunkSize"); @@ -194,12 +235,29 @@ impl MockAvailabilityStore { .expect("candidate was generated previously; qed"); gum::debug!(target: LOG_TARGET, ?candidate_hash, candidate_index, "Candidate mapped to index"); - let chunk_size = - self.state.chunks.get(*candidate_index).unwrap()[0].encoded_size(); + let chunk_size = self + .state + .chunks + .get(*candidate_index) + .unwrap() + .first() + .unwrap() + .encoded_size(); let _ = tx.send(Some(chunk_size)); }, - AvailabilityStoreMessage::StoreChunk { candidate_hash, chunk, tx } => { - gum::debug!(target: LOG_TARGET, chunk_index = ?chunk.index ,candidate_hash = ?candidate_hash, "Responding to StoreChunk"); + AvailabilityStoreMessage::StoreChunk { + candidate_hash, + chunk, + tx, + validator_index, + } => { + gum::debug!( + target: LOG_TARGET, + chunk_index = ?chunk.index, + validator_index = ?validator_index, + candidate_hash = ?candidate_hash, + "Responding to StoreChunk" + ); let _ = tx.send(Ok(())); }, _ => { diff --git a/polkadot/node/subsystem-bench/src/lib/mock/candidate_backing.rs b/polkadot/node/subsystem-bench/src/lib/mock/candidate_backing.rs new file mode 100644 index 0000000000000000000000000000000000000000..51494016e185e5e04f00c264eb341bf25d8991dd --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/mock/candidate_backing.rs @@ -0,0 +1,171 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! A generic candidate backing subsystem mockup suitable to be used in benchmarks. + +use crate::{configuration::TestConfiguration, NODE_UNDER_TEST}; +use futures::FutureExt; +use polkadot_node_primitives::{SignedFullStatementWithPVD, Statement, StatementWithPVD}; +use polkadot_node_subsystem::{ + messages::CandidateBackingMessage, overseer, SpawnedSubsystem, SubsystemError, +}; +use polkadot_node_subsystem_types::OverseerSignal; +use polkadot_primitives::{ + CandidateHash, Hash, PersistedValidationData, SigningContext, ValidatorIndex, ValidatorPair, +}; +use sp_core::Pair; +use std::collections::HashMap; + +const LOG_TARGET: &str = "subsystem-bench::candidate-backing-mock"; + +struct MockCandidateBackingState { + pair: ValidatorPair, + pvd: PersistedValidationData, + own_backing_group: Vec, +} + +pub struct MockCandidateBacking { + config: TestConfiguration, + state: MockCandidateBackingState, +} + +impl MockCandidateBacking { + pub fn new( + config: TestConfiguration, + pair: ValidatorPair, + pvd: PersistedValidationData, + own_backing_group: Vec, + ) -> Self { + Self { config, state: MockCandidateBackingState { pair, pvd, own_backing_group } } + } + + fn handle_statement( + &self, + relay_parent: Hash, + statement: SignedFullStatementWithPVD, + statements_tracker: &mut HashMap, + ) -> Vec { + let mut messages = vec![]; + let validator_id = statement.validator_index(); + let is_own_backing_group = self.state.own_backing_group.contains(&validator_id); + + match statement.payload() { + StatementWithPVD::Seconded(receipt, _pvd) => { + let candidate_hash = receipt.hash(); + statements_tracker + .entry(candidate_hash) + .and_modify(|v| { + *v += 1; + }) + .or_insert(1); + + let statements_received_count = *statements_tracker.get(&candidate_hash).unwrap(); + if statements_received_count == (self.config.minimum_backing_votes - 1) && + is_own_backing_group + { + let statement = Statement::Valid(candidate_hash); + let context = SigningContext { parent_hash: relay_parent, session_index: 0 }; + let payload = statement.to_compact().signing_payload(&context); + let message = + polkadot_node_subsystem::messages::StatementDistributionMessage::Share( + relay_parent, + SignedFullStatementWithPVD::new( + statement.supply_pvd(self.state.pvd.clone()), + ValidatorIndex(NODE_UNDER_TEST), + self.state.pair.sign(&payload[..]), + &context, + &self.state.pair.public(), + ) + .unwrap(), + ); + messages.push(message); + } + + if statements_received_count == self.config.minimum_backing_votes { + let message = + polkadot_node_subsystem::messages::StatementDistributionMessage::Backed( + candidate_hash, + ); + messages.push(message); + } + }, + StatementWithPVD::Valid(candidate_hash) => { + statements_tracker + .entry(*candidate_hash) + .and_modify(|v| { + *v += 1; + }) + .or_insert(1); + + let statements_received_count = *statements_tracker.get(candidate_hash).unwrap(); + if statements_received_count == self.config.minimum_backing_votes { + let message = + polkadot_node_subsystem::messages::StatementDistributionMessage::Backed( + *candidate_hash, + ); + messages.push(message); + } + }, + } + + messages + } +} + +#[overseer::subsystem(CandidateBacking, error=SubsystemError, prefix=self::overseer)] +impl MockCandidateBacking { + fn start(self, ctx: Context) -> SpawnedSubsystem { + let future = self.run(ctx).map(|_| Ok(())).boxed(); + + SpawnedSubsystem { name: "test-environment", future } + } +} + +#[overseer::contextbounds(CandidateBacking, prefix = self::overseer)] +impl MockCandidateBacking { + async fn run(self, mut ctx: Context) { + let mut statements_tracker: HashMap = Default::default(); + + loop { + let msg = ctx.recv().await.expect("Overseer never fails us"); + match msg { + orchestra::FromOrchestra::Signal(signal) => + if signal == OverseerSignal::Conclude { + return + }, + orchestra::FromOrchestra::Communication { msg } => { + gum::trace!(target: LOG_TARGET, msg=?msg, "recv message"); + + match msg { + CandidateBackingMessage::Statement(relay_parent, statement) => { + let messages = self.handle_statement( + relay_parent, + statement, + &mut statements_tracker, + ); + for message in messages { + ctx.send_message(message).await; + } + }, + _ => { + unimplemented!("Unexpected candidate-backing message") + }, + } + }, + } + } + } +} diff --git a/polkadot/node/subsystem-bench/src/lib/mock/mod.rs b/polkadot/node/subsystem-bench/src/lib/mock/mod.rs index 6dda9a47d398f3e6e952cd054bce9769e8942e70..12766374bfa9f49ad67699173cdda512623c4b8b 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/mod.rs @@ -19,9 +19,11 @@ use polkadot_node_subsystem_types::Hash; use sp_consensus::SyncOracle; pub mod av_store; +pub mod candidate_backing; pub mod chain_api; pub mod dummy; pub mod network_bridge; +pub mod prospective_parachains; pub mod runtime_api; pub struct AlwaysSupportsParachains {} diff --git a/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs index ec66ad4e279c217f7510d4c09def128f41fbffe5..d70953926d130eabc7be096cab71ff59d6e91bc8 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs @@ -27,14 +27,19 @@ use polkadot_node_subsystem::{ messages::NetworkBridgeTxMessage, overseer, SpawnedSubsystem, SubsystemError, }; use polkadot_node_subsystem_types::{ - messages::{ApprovalDistributionMessage, BitfieldDistributionMessage, NetworkBridgeEvent}, + messages::{ + ApprovalDistributionMessage, BitfieldDistributionMessage, NetworkBridgeEvent, + StatementDistributionMessage, + }, OverseerSignal, }; use sc_network::{request_responses::ProtocolConfig, RequestFailure}; const LOG_TARGET: &str = "subsystem-bench::network-bridge"; -const CHUNK_REQ_PROTOCOL_NAME_V1: &str = - "/ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/req_chunk/1"; +const ALLOWED_PROTOCOLS: &[&str] = &[ + "/ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/req_chunk/2", + "/ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/req_attested_candidate/2", +]; /// A mock of the network bridge tx subsystem. pub struct MockNetworkBridgeTx { @@ -106,8 +111,15 @@ impl MockNetworkBridgeTx { NetworkBridgeTxMessage::SendRequests(requests, _if_disconnected) => { for request in requests { gum::debug!(target: LOG_TARGET, request = ?request, "Processing request"); - let peer_id = - request.authority_id().expect("all nodes are authorities").clone(); + let peer_id = match request.authority_id() { + Some(v) => v.clone(), + None => self + .test_authorities + .peer_id_to_authority + .get(request.peer_id().expect("Should exist")) + .expect("Should exist") + .clone(), + }; if !self.network.is_peer_connected(&peer_id) { // Attempting to send a request to a disconnected peer. @@ -141,7 +153,23 @@ impl MockNetworkBridgeTx { .expect("Should not fail"); } }, - _ => unimplemented!("Unexpected network bridge message"), + NetworkBridgeTxMessage::SendValidationMessages(messages) => { + for (peers, message) in messages { + for peer in peers { + self.to_network_interface + .unbounded_send(NetworkMessage::MessageFromNode( + self.test_authorities + .peer_id_to_authority + .get(&peer) + .unwrap() + .clone(), + message.clone(), + )) + .expect("Should not fail"); + } + } + }, + message => unimplemented!("Unexpected network bridge message {:?}", message), }, } } @@ -175,13 +203,20 @@ impl MockNetworkBridgeRx { ApprovalDistributionMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerMessage(peer_id, polkadot_node_network_protocol::Versioned::V3(msg))) ).await; } + Versioned::V3( + polkadot_node_network_protocol::v3::ValidationProtocol::StatementDistribution(msg) + ) => { + ctx.send_message( + StatementDistributionMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerMessage(peer_id, polkadot_node_network_protocol::Versioned::V3(msg))) + ).await; + } _ => { unimplemented!("We only talk v2 network protocol") }, }, NetworkMessage::RequestFromPeer(request) => { if let Some(protocol) = self.chunk_request_sender.as_mut() { - assert_eq!(&*protocol.name, CHUNK_REQ_PROTOCOL_NAME_V1); + assert!(ALLOWED_PROTOCOLS.contains(&&*protocol.name)); if let Some(inbound_queue) = protocol.inbound_queue.as_ref() { inbound_queue .send(request) diff --git a/polkadot/node/subsystem-bench/src/lib/mock/prospective_parachains.rs b/polkadot/node/subsystem-bench/src/lib/mock/prospective_parachains.rs new file mode 100644 index 0000000000000000000000000000000000000000..8a865af21a073aefe55b85b37e7ccd091e8a2f0f --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/mock/prospective_parachains.rs @@ -0,0 +1,74 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! A generic prospective parachains subsystem mockup suitable to be used in benchmarks. + +use futures::FutureExt; +use polkadot_node_subsystem::{ + messages::ProspectiveParachainsMessage, overseer, SpawnedSubsystem, SubsystemError, +}; +use polkadot_node_subsystem_types::OverseerSignal; +use polkadot_primitives::Hash; + +pub struct MockProspectiveParachains {} + +impl MockProspectiveParachains { + pub fn new() -> Self { + Self {} + } +} + +#[overseer::subsystem(ProspectiveParachains, error=SubsystemError, prefix=self::overseer)] +impl MockProspectiveParachains { + fn start(self, ctx: Context) -> SpawnedSubsystem { + let future = self.run(ctx).map(|_| Ok(())).boxed(); + + SpawnedSubsystem { name: "test-environment", future } + } +} + +#[overseer::contextbounds(ProspectiveParachains, prefix = self::overseer)] +impl MockProspectiveParachains { + async fn run(self, mut ctx: Context) { + loop { + let msg = ctx.recv().await.expect("Overseer never fails us"); + match msg { + orchestra::FromOrchestra::Signal(signal) => + if signal == OverseerSignal::Conclude { + return + }, + orchestra::FromOrchestra::Communication { msg } => match msg { + ProspectiveParachainsMessage::GetMinimumRelayParents(_relay_parent, tx) => { + tx.send(vec![]).unwrap(); + }, + ProspectiveParachainsMessage::GetHypotheticalMembership(req, tx) => { + tx.send( + req.candidates + .iter() + .cloned() + .map(|candidate| (candidate, vec![Hash::repeat_byte(0)])) + .collect(), + ) + .unwrap(); + }, + _ => { + unimplemented!("Unexpected chain-api message") + }, + }, + } + } + } +} diff --git a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs index b73d61321cd3b274915dda37233c1945240c2b11..be9dbd55cb6f9898a879e7bbaa6c5f5b9c303484 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs @@ -26,8 +26,9 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_types::OverseerSignal; use polkadot_primitives::{ - CandidateEvent, CandidateReceipt, CoreState, GroupIndex, IndexedVec, NodeFeatures, - OccupiedCore, SessionIndex, SessionInfo, ValidatorIndex, + node_features, AsyncBackingParams, CandidateEvent, CandidateReceipt, CoreState, GroupIndex, + GroupRotationInfo, IndexedVec, NodeFeatures, OccupiedCore, ScheduledCore, SessionIndex, + SessionInfo, ValidatorIndex, }; use sp_consensus_babe::Epoch as BabeEpoch; use sp_core::H256; @@ -40,6 +41,8 @@ const LOG_TARGET: &str = "subsystem-bench::runtime-api-mock"; pub struct RuntimeApiState { // All authorities in the test, authorities: TestAuthorities, + // Node features state in the runtime + node_features: NodeFeatures, // Candidate hashes per block candidate_hashes: HashMap>, // Included candidates per bock @@ -49,11 +52,20 @@ pub struct RuntimeApiState { session_index: SessionIndex, } +#[derive(Clone)] +pub enum MockRuntimeApiCoreState { + Occupied, + Scheduled, + #[allow(dead_code)] + Free, +} + /// A mocked `runtime-api` subsystem. #[derive(Clone)] pub struct MockRuntimeApi { state: RuntimeApiState, config: TestConfiguration, + core_state: MockRuntimeApiCoreState, } impl MockRuntimeApi { @@ -64,7 +76,11 @@ impl MockRuntimeApi { included_candidates: HashMap>, babe_epoch: Option, session_index: SessionIndex, + core_state: MockRuntimeApiCoreState, ) -> MockRuntimeApi { + // Enable chunk mapping feature to make systematic av-recovery possible. + let node_features = node_features_with_chunk_mapping_enabled(); + Self { state: RuntimeApiState { authorities, @@ -72,8 +88,10 @@ impl MockRuntimeApi { included_candidates, babe_epoch, session_index, + node_features, }, config, + core_state, } } @@ -156,15 +174,15 @@ impl MockRuntimeApi { }, RuntimeApiMessage::Request( _block_hash, - RuntimeApiRequest::SessionExecutorParams(_session_index, sender), + RuntimeApiRequest::NodeFeatures(_session_index, sender), ) => { - let _ = sender.send(Ok(Some(Default::default()))); + let _ = sender.send(Ok(self.state.node_features.clone())); }, RuntimeApiMessage::Request( - _request, - RuntimeApiRequest::NodeFeatures(_session_index, sender), + _block_hash, + RuntimeApiRequest::SessionExecutorParams(_session_index, sender), ) => { - let _ = sender.send(Ok(NodeFeatures::EMPTY)); + let _ = sender.send(Ok(Some(Default::default()))); }, RuntimeApiMessage::Request( _block_hash, @@ -198,16 +216,26 @@ impl MockRuntimeApi { // Ensure test breaks if badly configured. assert!(index < validator_group_count); - CoreState::Occupied(OccupiedCore { - next_up_on_available: None, - occupied_since: 0, - time_out_at: 0, - next_up_on_time_out: None, - availability: BitVec::default(), - group_responsible: GroupIndex(index as u32), - candidate_hash: candidate_receipt.hash(), - candidate_descriptor: candidate_receipt.descriptor.clone(), - }) + use MockRuntimeApiCoreState::*; + match self.core_state { + Occupied => CoreState::Occupied(OccupiedCore { + next_up_on_available: None, + occupied_since: 0, + time_out_at: 0, + next_up_on_time_out: None, + availability: BitVec::default(), + group_responsible: GroupIndex(index as u32), + candidate_hash: candidate_receipt.hash(), + candidate_descriptor: candidate_receipt + .descriptor + .clone(), + }), + Scheduled => CoreState::Scheduled(ScheduledCore { + para_id: (index + 1).into(), + collator: None, + }), + Free => todo!(), + } }) .collect::>(); @@ -223,6 +251,43 @@ impl MockRuntimeApi { .clone() .expect("Babe epoch unpopulated"))); }, + RuntimeApiMessage::Request( + _block_hash, + RuntimeApiRequest::AsyncBackingParams(sender), + ) => { + let _ = sender.send(Ok(AsyncBackingParams { + max_candidate_depth: self.config.max_candidate_depth, + allowed_ancestry_len: self.config.allowed_ancestry_len, + })); + }, + RuntimeApiMessage::Request(_parent, RuntimeApiRequest::Version(tx)) => { + tx.send(Ok(RuntimeApiRequest::DISABLED_VALIDATORS_RUNTIME_REQUIREMENT)) + .unwrap(); + }, + RuntimeApiMessage::Request( + _parent, + RuntimeApiRequest::DisabledValidators(tx), + ) => { + tx.send(Ok(vec![])).unwrap(); + }, + RuntimeApiMessage::Request( + _parent, + RuntimeApiRequest::MinimumBackingVotes(_session_index, tx), + ) => { + tx.send(Ok(self.config.minimum_backing_votes)).unwrap(); + }, + RuntimeApiMessage::Request( + _parent, + RuntimeApiRequest::ValidatorGroups(tx), + ) => { + let groups = self.session_info().validator_groups.to_vec(); + let group_rotation_info = GroupRotationInfo { + session_start_block: 1, + group_rotation_frequency: 12, + now: 1, + }; + tx.send(Ok((groups, group_rotation_info))).unwrap(); + }, // Long term TODO: implement more as needed. message => { unimplemented!("Unexpected runtime-api message: {:?}", message) @@ -233,3 +298,10 @@ impl MockRuntimeApi { } } } + +pub fn node_features_with_chunk_mapping_enabled() -> NodeFeatures { + let mut node_features = NodeFeatures::new(); + node_features.resize(node_features::FeatureIndex::AvailabilityChunkMapping as usize + 1, false); + node_features.set(node_features::FeatureIndex::AvailabilityChunkMapping as u8 as usize, true); + node_features +} diff --git a/polkadot/node/subsystem-bench/src/lib/network.rs b/polkadot/node/subsystem-bench/src/lib/network.rs index 9bf2415e5a864a9c4512350b9387b6c172b37114..775f881eaad84bc352e098487f720ddd390decb5 100644 --- a/polkadot/node/subsystem-bench/src/lib/network.rs +++ b/polkadot/node/subsystem-bench/src/lib/network.rs @@ -51,13 +51,14 @@ use futures::{ }; use itertools::Itertools; use net_protocol::{ - peer_set::{ProtocolVersion, ValidationVersion}, + peer_set::ValidationVersion, request_response::{Recipient, Requests, ResponseSender}, - ObservedRole, VersionedValidationProtocol, + ObservedRole, VersionedValidationProtocol, View, }; use parity_scale_codec::Encode; use polkadot_node_network_protocol::{self as net_protocol, Versioned}; -use polkadot_node_subsystem_types::messages::{ApprovalDistributionMessage, NetworkBridgeEvent}; +use polkadot_node_subsystem::messages::StatementDistributionMessage; +use polkadot_node_subsystem_types::messages::NetworkBridgeEvent; use polkadot_node_subsystem_util::metrics::prometheus::{ self, CounterVec, Opts, PrometheusError, Registry, }; @@ -437,6 +438,7 @@ pub struct EmulatedPeerHandle { /// Send actions to be performed by the peer. actions_tx: UnboundedSender, peer_id: PeerId, + authority_id: AuthorityDiscoveryId, } impl EmulatedPeerHandle { @@ -496,29 +498,31 @@ impl EmulatedPeer { } /// Interceptor pattern for handling messages. +#[async_trait::async_trait] pub trait HandleNetworkMessage { /// Returns `None` if the message was handled, or the `message` /// otherwise. /// /// `node_sender` allows sending of messages to the node in response /// to the handled message. - fn handle( + async fn handle( &self, message: NetworkMessage, node_sender: &mut UnboundedSender, ) -> Option; } +#[async_trait::async_trait] impl HandleNetworkMessage for Arc where - T: HandleNetworkMessage, + T: HandleNetworkMessage + Sync + Send, { - fn handle( + async fn handle( &self, message: NetworkMessage, node_sender: &mut UnboundedSender, ) -> Option { - self.as_ref().handle(message, node_sender) + T::handle(self, message, node_sender).await } } @@ -551,7 +555,7 @@ async fn emulated_peer_loop( for handler in handlers.iter() { // The check below guarantees that message is always `Some`: we are still // inside the loop. - message = handler.handle(message.unwrap(), &mut to_network_interface); + message = handler.handle(message.unwrap(), &mut to_network_interface).await; if message.is_none() { break } @@ -613,6 +617,7 @@ async fn emulated_peer_loop( } /// Creates a new peer emulator task and returns a handle to it. +#[allow(clippy::too_many_arguments)] pub fn new_peer( bandwidth: usize, spawn_task_handle: SpawnTaskHandle, @@ -621,6 +626,7 @@ pub fn new_peer( to_network_interface: UnboundedSender, latency_ms: usize, peer_id: PeerId, + authority_id: AuthorityDiscoveryId, ) -> EmulatedPeerHandle { let (messages_tx, messages_rx) = mpsc::unbounded::(); let (actions_tx, actions_rx) = mpsc::unbounded::(); @@ -649,7 +655,7 @@ pub fn new_peer( .boxed(), ); - EmulatedPeerHandle { messages_tx, actions_tx, peer_id } + EmulatedPeerHandle { messages_tx, actions_tx, peer_id, authority_id } } /// Book keeping of sent and received bytes. @@ -714,6 +720,18 @@ impl Peer { Peer::Disconnected(ref emulator) => emulator, } } + + pub fn authority_id(&self) -> AuthorityDiscoveryId { + match self { + Peer::Connected(handle) | Peer::Disconnected(handle) => handle.authority_id.clone(), + } + } + + pub fn peer_id(&self) -> PeerId { + match self { + Peer::Connected(handle) | Peer::Disconnected(handle) => handle.peer_id, + } + } } /// A ha emulated network implementation. @@ -728,21 +746,34 @@ pub struct NetworkEmulatorHandle { } impl NetworkEmulatorHandle { + pub fn generate_statement_distribution_peer_view_change(&self, view: View) -> Vec { + self.peers + .iter() + .filter(|peer| peer.is_connected()) + .map(|peer| { + AllMessages::StatementDistribution( + StatementDistributionMessage::NetworkBridgeUpdate( + NetworkBridgeEvent::PeerViewChange(peer.peer_id(), view.clone()), + ), + ) + }) + .collect_vec() + } + /// Generates peer_connected messages for all peers in `test_authorities` - pub fn generate_peer_connected(&self) -> Vec { + pub fn generate_peer_connected(&self, mapper: F) -> Vec + where + F: Fn(NetworkBridgeEvent) -> AllMessages, + { self.peers .iter() .filter(|peer| peer.is_connected()) .map(|peer| { - let network = NetworkBridgeEvent::PeerConnected( + mapper(NetworkBridgeEvent::PeerConnected( peer.handle().peer_id, - ObservedRole::Full, - ProtocolVersion::from(ValidationVersion::V3), - None, - ); - - AllMessages::ApprovalDistribution(ApprovalDistributionMessage::NetworkBridgeUpdate( - network, + ObservedRole::Authority, + ValidationVersion::V3.into(), + Some(vec![peer.authority_id()].into_iter().collect()), )) }) .collect_vec() @@ -772,7 +803,7 @@ pub fn new_network( let (stats, mut peers): (_, Vec<_>) = (0..n_peers) .zip(authorities.validator_authority_id.clone()) .map(|(peer_index, authority_id)| { - validator_authority_id_mapping.insert(authority_id, peer_index); + validator_authority_id_mapping.insert(authority_id.clone(), peer_index); let stats = Arc::new(PeerEmulatorStats::new(peer_index, metrics.clone())); ( stats.clone(), @@ -784,6 +815,7 @@ pub fn new_network( to_network_interface.clone(), random_latency(config.latency.as_ref()), *authorities.peer_ids.get(peer_index).unwrap(), + authority_id, )), ) }) @@ -971,6 +1003,8 @@ impl Metrics { pub trait RequestExt { /// Get the authority id if any from the request. fn authority_id(&self) -> Option<&AuthorityDiscoveryId>; + /// Get the peer id if any from the request. + fn peer_id(&self) -> Option<&PeerId>; /// Consume self and return the response sender. fn into_response_sender(self) -> ResponseSender; /// Allows to change the `ResponseSender` in place. @@ -982,7 +1016,7 @@ pub trait RequestExt { impl RequestExt for Requests { fn authority_id(&self) -> Option<&AuthorityDiscoveryId> { match self { - Requests::ChunkFetchingV1(request) => { + Requests::ChunkFetching(request) => { if let Recipient::Authority(authority_id) = &request.peer { Some(authority_id) } else { @@ -996,15 +1030,29 @@ impl RequestExt for Requests { None } }, + // Requested by PeerId + Requests::AttestedCandidateV2(_) => None, request => { unimplemented!("RequestAuthority not implemented for {:?}", request) }, } } + fn peer_id(&self) -> Option<&PeerId> { + match self { + Requests::AttestedCandidateV2(request) => match &request.peer { + Recipient::Authority(_) => None, + Recipient::Peer(peer_id) => Some(peer_id), + }, + request => { + unimplemented!("peer_id() is not implemented for {:?}", request) + }, + } + } + fn into_response_sender(self) -> ResponseSender { match self { - Requests::ChunkFetchingV1(outgoing_request) => outgoing_request.pending_response, + Requests::ChunkFetching(outgoing_request) => outgoing_request.pending_response, Requests::AvailableDataFetchingV1(outgoing_request) => outgoing_request.pending_response, _ => unimplemented!("unsupported request type"), @@ -1014,10 +1062,12 @@ impl RequestExt for Requests { /// Swaps the `ResponseSender` and returns the previous value. fn swap_response_sender(&mut self, new_sender: ResponseSender) -> ResponseSender { match self { - Requests::ChunkFetchingV1(outgoing_request) => + Requests::ChunkFetching(outgoing_request) => std::mem::replace(&mut outgoing_request.pending_response, new_sender), Requests::AvailableDataFetchingV1(outgoing_request) => std::mem::replace(&mut outgoing_request.pending_response, new_sender), + Requests::AttestedCandidateV2(outgoing_request) => + std::mem::replace(&mut outgoing_request.pending_response, new_sender), _ => unimplemented!("unsupported request type"), } } @@ -1025,9 +1075,11 @@ impl RequestExt for Requests { /// Returns the size in bytes of the request payload. fn size(&self) -> usize { match self { - Requests::ChunkFetchingV1(outgoing_request) => outgoing_request.payload.encoded_size(), + Requests::ChunkFetching(outgoing_request) => outgoing_request.payload.encoded_size(), Requests::AvailableDataFetchingV1(outgoing_request) => outgoing_request.payload.encoded_size(), + Requests::AttestedCandidateV2(outgoing_request) => + outgoing_request.payload.encoded_size(), _ => unimplemented!("received an unexpected request"), } } diff --git a/polkadot/node/subsystem-bench/src/lib/statement/mod.rs b/polkadot/node/subsystem-bench/src/lib/statement/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..bd47505f56aeabc201f0d57bec57fa6a3f3380d4 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/statement/mod.rs @@ -0,0 +1,449 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use crate::{ + configuration::TestAuthorities, + dummy_builder, + environment::{TestEnvironment, TestEnvironmentDependencies, GENESIS_HASH}, + mock::{ + candidate_backing::MockCandidateBacking, + chain_api::{ChainApiState, MockChainApi}, + network_bridge::{MockNetworkBridgeRx, MockNetworkBridgeTx}, + prospective_parachains::MockProspectiveParachains, + runtime_api::{MockRuntimeApi, MockRuntimeApiCoreState}, + AlwaysSupportsParachains, + }, + network::{new_network, NetworkEmulatorHandle, NetworkInterface, NetworkInterfaceReceiver}, + usage::BenchmarkUsage, + NODE_UNDER_TEST, +}; +use bitvec::vec::BitVec; +use colored::Colorize; +use itertools::Itertools; +use polkadot_node_metrics::metrics::Metrics; +use polkadot_node_network_protocol::{ + grid_topology::{SessionGridTopology, TopologyPeerInfo}, + request_response::{IncomingRequest, ReqProtocolNames}, + v3::{self, BackedCandidateManifest, StatementFilter}, + view, Versioned, View, +}; +use polkadot_node_subsystem::messages::{ + network_bridge_event::NewGossipTopology, AllMessages, NetworkBridgeEvent, + StatementDistributionMessage, +}; +use polkadot_overseer::{ + Handle as OverseerHandle, Overseer, OverseerConnector, OverseerMetrics, SpawnGlue, +}; +use polkadot_primitives::{ + AuthorityDiscoveryId, Block, GroupIndex, Hash, Id, ValidatorId, ValidatorIndex, +}; +use polkadot_statement_distribution::StatementDistributionSubsystem; +use rand::SeedableRng; +use sc_keystore::LocalKeystore; +use sc_network::request_responses::ProtocolConfig; +use sc_network_types::PeerId; +use sc_service::SpawnTaskHandle; +use sp_keystore::{Keystore, KeystorePtr}; +use sp_runtime::RuntimeAppPublic; +use std::{ + sync::{atomic::Ordering, Arc}, + time::{Duration, Instant}, +}; +pub use test_state::TestState; + +mod test_state; + +const LOG_TARGET: &str = "subsystem-bench::statement"; + +pub fn make_keystore() -> KeystorePtr { + let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); + Keystore::sr25519_generate_new(&*keystore, ValidatorId::ID, Some("//Node0")) + .expect("Insert key into keystore"); + Keystore::sr25519_generate_new(&*keystore, AuthorityDiscoveryId::ID, Some("//Node0")) + .expect("Insert key into keystore"); + keystore +} + +fn build_overseer( + state: &TestState, + network: NetworkEmulatorHandle, + network_interface: NetworkInterface, + network_receiver: NetworkInterfaceReceiver, + dependencies: &TestEnvironmentDependencies, +) -> ( + Overseer, AlwaysSupportsParachains>, + OverseerHandle, + Vec, +) { + let overseer_connector = OverseerConnector::with_event_capacity(64000); + let overseer_metrics = OverseerMetrics::try_register(&dependencies.registry).unwrap(); + let spawn_task_handle = dependencies.task_manager.spawn_handle(); + let mock_runtime_api = MockRuntimeApi::new( + state.config.clone(), + state.test_authorities.clone(), + state.candidate_receipts.clone(), + Default::default(), + Default::default(), + 0, + MockRuntimeApiCoreState::Scheduled, + ); + let chain_api_state = ChainApiState { block_headers: state.block_headers.clone() }; + let mock_chain_api = MockChainApi::new(chain_api_state); + let mock_prospective_parachains = MockProspectiveParachains::new(); + let mock_candidate_backing = MockCandidateBacking::new( + state.config.clone(), + state + .test_authorities + .validator_pairs + .get(NODE_UNDER_TEST as usize) + .unwrap() + .clone(), + state.pvd.clone(), + state.own_backing_group.clone(), + ); + let (statement_req_receiver, statement_req_cfg) = IncomingRequest::get_config_receiver::< + Block, + sc_network::NetworkWorker, + >(&ReqProtocolNames::new(GENESIS_HASH, None)); + let (candidate_req_receiver, candidate_req_cfg) = IncomingRequest::get_config_receiver::< + Block, + sc_network::NetworkWorker, + >(&ReqProtocolNames::new(GENESIS_HASH, None)); + let keystore = make_keystore(); + let subsystem = StatementDistributionSubsystem::new( + keystore.clone(), + statement_req_receiver, + candidate_req_receiver, + Metrics::try_register(&dependencies.registry).unwrap(), + rand::rngs::StdRng::from_entropy(), + ); + let network_bridge_tx = MockNetworkBridgeTx::new( + network, + network_interface.subsystem_sender(), + state.test_authorities.clone(), + ); + let network_bridge_rx = MockNetworkBridgeRx::new(network_receiver, Some(candidate_req_cfg)); + + let dummy = dummy_builder!(spawn_task_handle, overseer_metrics) + .replace_runtime_api(|_| mock_runtime_api) + .replace_chain_api(|_| mock_chain_api) + .replace_prospective_parachains(|_| mock_prospective_parachains) + .replace_candidate_backing(|_| mock_candidate_backing) + .replace_statement_distribution(|_| subsystem) + .replace_network_bridge_tx(|_| network_bridge_tx) + .replace_network_bridge_rx(|_| network_bridge_rx); + let (overseer, raw_handle) = dummy.build_with_connector(overseer_connector).unwrap(); + let overseer_handle = OverseerHandle::new(raw_handle); + + (overseer, overseer_handle, vec![statement_req_cfg]) +} + +pub fn prepare_test( + state: &TestState, + with_prometheus_endpoint: bool, +) -> (TestEnvironment, Vec) { + let dependencies = TestEnvironmentDependencies::default(); + let (network, network_interface, network_receiver) = new_network( + &state.config, + &dependencies, + &state.test_authorities, + vec![Arc::new(state.clone())], + ); + let (overseer, overseer_handle, cfg) = + build_overseer(state, network.clone(), network_interface, network_receiver, &dependencies); + + ( + TestEnvironment::new( + dependencies, + state.config.clone(), + network, + overseer, + overseer_handle, + state.test_authorities.clone(), + with_prometheus_endpoint, + ), + cfg, + ) +} + +pub fn generate_peer_view_change(block_hash: Hash, peer_id: PeerId) -> AllMessages { + let network = NetworkBridgeEvent::PeerViewChange(peer_id, View::new([block_hash], 0)); + + AllMessages::StatementDistribution(StatementDistributionMessage::NetworkBridgeUpdate(network)) +} + +pub fn generate_new_session_topology( + topology: &SessionGridTopology, + test_node: ValidatorIndex, +) -> Vec { + let event = NetworkBridgeEvent::NewGossipTopology(NewGossipTopology { + session: 0, + topology: topology.clone(), + local_index: Some(test_node), + }); + vec![AllMessages::StatementDistribution(StatementDistributionMessage::NetworkBridgeUpdate( + event, + ))] +} + +/// Generates a topology to be used for this benchmark. +pub fn generate_topology(test_authorities: &TestAuthorities) -> SessionGridTopology { + let keyrings = test_authorities + .validator_authority_id + .clone() + .into_iter() + .zip(test_authorities.peer_ids.clone()) + .collect_vec(); + + let topology = keyrings + .clone() + .into_iter() + .enumerate() + .map(|(index, (discovery_id, peer_id))| TopologyPeerInfo { + peer_ids: vec![peer_id], + validator_index: ValidatorIndex(index as u32), + discovery_id, + }) + .collect_vec(); + let shuffled = (0..keyrings.len()).collect_vec(); + + SessionGridTopology::new(shuffled, topology) +} + +pub async fn benchmark_statement_distribution( + env: &mut TestEnvironment, + state: &TestState, +) -> BenchmarkUsage { + state.reset_trackers(); + + let connected_validators = state + .test_authorities + .validator_authority_id + .iter() + .enumerate() + .filter_map(|(i, id)| if env.network().is_peer_connected(id) { Some(i) } else { None }) + .collect_vec(); + let seconding_validator_in_own_backing_group = state + .own_backing_group + .iter() + .find(|v| connected_validators.contains(&(v.0 as usize))) + .unwrap() + .to_owned(); + + let config = env.config().clone(); + let groups = state.session_info.validator_groups.clone(); + let own_backing_group_index = groups + .iter() + .position(|group| group.iter().any(|v| v.0 == NODE_UNDER_TEST)) + .unwrap(); + + env.metrics().set_n_validators(config.n_validators); + env.metrics().set_n_cores(config.n_cores); + + let topology = generate_topology(&state.test_authorities); + let peer_connected_messages = env.network().generate_peer_connected(|e| { + AllMessages::StatementDistribution(StatementDistributionMessage::NetworkBridgeUpdate(e)) + }); + let new_session_topology_messages = + generate_new_session_topology(&topology, ValidatorIndex(NODE_UNDER_TEST)); + for message in peer_connected_messages.into_iter().chain(new_session_topology_messages) { + env.send_message(message).await; + } + + let test_start = Instant::now(); + let mut candidates_advertised = 0; + for block_info in state.block_infos.iter() { + let block_num = block_info.number as usize; + gum::info!(target: LOG_TARGET, "Current block {}/{} {:?}", block_num, config.num_blocks, block_info.hash); + env.metrics().set_current_block(block_num); + env.import_block(block_info.clone()).await; + + for peer_view_change in env + .network() + .generate_statement_distribution_peer_view_change(view![block_info.hash]) + { + env.send_message(peer_view_change).await; + } + + let seconding_peer_id = *state + .test_authorities + .peer_ids + .get(seconding_validator_in_own_backing_group.0 as usize) + .unwrap(); + let candidate = state.candidate_receipts.get(&block_info.hash).unwrap().first().unwrap(); + let candidate_hash = candidate.hash(); + let statement = state + .statements + .get(&candidate_hash) + .unwrap() + .get(seconding_validator_in_own_backing_group.0 as usize) + .unwrap() + .clone(); + let message = AllMessages::StatementDistribution( + StatementDistributionMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerMessage( + seconding_peer_id, + Versioned::V3(v3::StatementDistributionMessage::Statement( + block_info.hash, + statement, + )), + )), + ); + env.send_message(message).await; + + let max_messages_per_candidate = state.config.max_candidate_depth + 1; + // One was just sent for the own backing group + let mut messages_tracker = (0..groups.len()) + .map(|i| if i == own_backing_group_index { max_messages_per_candidate } else { 0 }) + .collect_vec(); + + let neighbors = + topology.compute_grid_neighbors_for(ValidatorIndex(NODE_UNDER_TEST)).unwrap(); + let connected_neighbors_x = neighbors + .validator_indices_x + .iter() + .filter(|&v| connected_validators.contains(&(v.0 as usize))) + .cloned() + .collect_vec(); + let connected_neighbors_y = neighbors + .validator_indices_y + .iter() + .filter(|&v| connected_validators.contains(&(v.0 as usize))) + .cloned() + .collect_vec(); + let one_hop_peers_and_groups = connected_neighbors_x + .iter() + .chain(connected_neighbors_y.iter()) + .map(|validator_index| { + let peer_id = + *state.test_authorities.peer_ids.get(validator_index.0 as usize).unwrap(); + let group_index = + groups.iter().position(|group| group.contains(validator_index)).unwrap(); + (peer_id, group_index) + }) + .collect_vec(); + let two_hop_x_peers_and_groups = connected_neighbors_x + .iter() + .flat_map(|validator_index| { + let peer_id = + *state.test_authorities.peer_ids.get(validator_index.0 as usize).unwrap(); + topology + .compute_grid_neighbors_for(*validator_index) + .unwrap() + .validator_indices_y + .iter() + .map(|validator_neighbor| { + let group_index = groups + .iter() + .position(|group| group.contains(validator_neighbor)) + .unwrap(); + (peer_id, group_index) + }) + .collect_vec() + }) + .collect_vec(); + let two_hop_y_peers_and_groups = connected_neighbors_y + .iter() + .flat_map(|validator_index| { + let peer_id = + *state.test_authorities.peer_ids.get(validator_index.0 as usize).unwrap(); + topology + .compute_grid_neighbors_for(*validator_index) + .unwrap() + .validator_indices_x + .iter() + .map(|validator_neighbor| { + let group_index = groups + .iter() + .position(|group| group.contains(validator_neighbor)) + .unwrap(); + (peer_id, group_index) + }) + .collect_vec() + }) + .collect_vec(); + + for (seconding_peer_id, group_index) in one_hop_peers_and_groups + .into_iter() + .chain(two_hop_x_peers_and_groups) + .chain(two_hop_y_peers_and_groups) + { + let messages_sent_count = messages_tracker.get_mut(group_index).unwrap(); + if *messages_sent_count == max_messages_per_candidate { + continue + } + *messages_sent_count += 1; + + let candidate_hash = state + .candidate_receipts + .get(&block_info.hash) + .unwrap() + .get(group_index) + .unwrap() + .hash(); + let manifest = BackedCandidateManifest { + relay_parent: block_info.hash, + candidate_hash, + group_index: GroupIndex(group_index as u32), + para_id: Id::new(group_index as u32 + 1), + parent_head_data_hash: state.pvd.parent_head.hash(), + statement_knowledge: StatementFilter { + seconded_in_group: BitVec::from_iter( + groups.get(GroupIndex(group_index as u32)).unwrap().iter().map(|_| true), + ), + validated_in_group: BitVec::from_iter( + groups.get(GroupIndex(group_index as u32)).unwrap().iter().map(|_| false), + ), + }, + }; + let message = AllMessages::StatementDistribution( + StatementDistributionMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerMessage( + seconding_peer_id, + Versioned::V3(v3::StatementDistributionMessage::BackedCandidateManifest( + manifest, + )), + )), + ); + env.send_message(message).await; + } + + candidates_advertised += messages_tracker.iter().filter(|&&v| v > 0).collect_vec().len(); + + loop { + let manifests_count = state + .manifests_tracker + .values() + .filter(|v| v.load(Ordering::SeqCst)) + .collect::>() + .len(); + gum::debug!(target: LOG_TARGET, "{}/{} manifest exchanges", manifests_count, candidates_advertised); + + if manifests_count == candidates_advertised { + break; + } + tokio::time::sleep(Duration::from_millis(50)).await; + } + } + + let duration: u128 = test_start.elapsed().as_millis(); + gum::info!(target: LOG_TARGET, "All blocks processed in {}", format!("{:?}ms", duration).cyan()); + gum::info!(target: LOG_TARGET, + "Avg block time: {}", + format!("{} ms", test_start.elapsed().as_millis() / env.config().num_blocks as u128).red() + ); + + env.stop().await; + env.collect_resource_usage(&["statement-distribution"]) +} diff --git a/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs b/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs new file mode 100644 index 0000000000000000000000000000000000000000..b8ea64c7e331773fdcc2ee6bbd3da67a1c147980 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs @@ -0,0 +1,436 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use crate::{ + configuration::{TestAuthorities, TestConfiguration}, + mock::runtime_api::session_info_for_peers, + network::{HandleNetworkMessage, NetworkMessage}, + NODE_UNDER_TEST, +}; +use bitvec::vec::BitVec; +use futures::channel::oneshot; +use itertools::Itertools; +use parity_scale_codec::{Decode, Encode}; +use polkadot_node_network_protocol::{ + request_response::{ + v2::{AttestedCandidateRequest, AttestedCandidateResponse}, + Requests, + }, + v3::{ + BackedCandidateAcknowledgement, StatementDistributionMessage, StatementFilter, + ValidationProtocol, + }, + Versioned, +}; +use polkadot_node_primitives::{AvailableData, BlockData, PoV}; +use polkadot_node_subsystem_test_helpers::{ + derive_erasure_chunks_with_proofs_and_root, mock::new_block_import_info, +}; +use polkadot_overseer::BlockInfo; +use polkadot_primitives::{ + BlockNumber, CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CompactStatement, + Hash, Header, Id, PersistedValidationData, SessionInfo, SignedStatement, SigningContext, + UncheckedSigned, ValidatorIndex, ValidatorPair, +}; +use polkadot_primitives_test_helpers::{ + dummy_committed_candidate_receipt, dummy_hash, dummy_head_data, dummy_pvd, +}; +use sc_network::{config::IncomingRequest, ProtocolName}; +use sp_core::{Pair, H256}; +use std::{ + collections::HashMap, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; + +#[derive(Clone)] +pub struct TestState { + // Full test config + pub config: TestConfiguration, + // Authority keys for the network emulation. + pub test_authorities: TestAuthorities, + // Relay chain block infos + pub block_infos: Vec, + // Map from generated candidate receipts + pub candidate_receipts: HashMap>, + // Map from generated commited candidate receipts + pub commited_candidate_receipts: HashMap>, + // PersistedValidationData, we use one for all candidates + pub pvd: PersistedValidationData, + // Relay chain block headers + pub block_headers: HashMap, + // Session info + pub session_info: SessionInfo, + // Pregenerated statements + pub statements: HashMap>>, + // Indices in the backing group where the node under test is + pub own_backing_group: Vec, + // Tracks how many statements we received for a candidates + pub statements_tracker: HashMap>>, + // Tracks if manifest exchange happened + pub manifests_tracker: HashMap>, +} + +impl TestState { + pub fn new(config: &TestConfiguration) -> Self { + let test_authorities = config.generate_authorities(); + let session_info = session_info_for_peers(config, &test_authorities); + let own_backing_group = session_info + .validator_groups + .iter() + .find(|g| g.contains(&ValidatorIndex(NODE_UNDER_TEST))) + .unwrap() + .clone(); + let mut state = Self { + config: config.clone(), + test_authorities, + block_infos: (1..=config.num_blocks).map(generate_block_info).collect(), + candidate_receipts: Default::default(), + commited_candidate_receipts: Default::default(), + pvd: dummy_pvd(dummy_head_data(), 0), + block_headers: Default::default(), + statements_tracker: Default::default(), + manifests_tracker: Default::default(), + session_info, + own_backing_group, + statements: Default::default(), + }; + + state.block_headers = state.block_infos.iter().map(generate_block_header).collect(); + + // For each unique pov we create a candidate receipt. + let pov_sizes = Vec::from(config.pov_sizes()); // For n_cores + let pov_size_to_candidate = generate_pov_size_to_candidate(&pov_sizes); + let receipt_templates = + generate_receipt_templates(&pov_size_to_candidate, config.n_validators, &state.pvd); + + for block_info in state.block_infos.iter() { + for core_idx in 0..config.n_cores { + let pov_size = pov_sizes.get(core_idx).expect("This is a cycle; qed"); + let candidate_index = + *pov_size_to_candidate.get(pov_size).expect("pov_size always exists; qed"); + let mut receipt = receipt_templates[candidate_index].clone(); + receipt.descriptor.para_id = Id::new(core_idx as u32 + 1); + receipt.descriptor.relay_parent = block_info.hash; + + state.candidate_receipts.entry(block_info.hash).or_default().push( + CandidateReceipt { + descriptor: receipt.descriptor.clone(), + commitments_hash: receipt.commitments.hash(), + }, + ); + state.statements_tracker.entry(receipt.hash()).or_default().extend( + (0..config.n_validators) + .map(|_| Arc::new(AtomicBool::new(false))) + .collect_vec(), + ); + state.manifests_tracker.insert(receipt.hash(), Arc::new(AtomicBool::new(false))); + state + .commited_candidate_receipts + .entry(block_info.hash) + .or_default() + .push(receipt); + } + } + + let groups = state.session_info.validator_groups.clone(); + + for block_info in state.block_infos.iter() { + for (index, group) in groups.iter().enumerate() { + let candidate = + state.candidate_receipts.get(&block_info.hash).unwrap().get(index).unwrap(); + let statements = group + .iter() + .map(|&v| { + sign_statement( + CompactStatement::Seconded(candidate.hash()), + block_info.hash, + v, + state.test_authorities.validator_pairs.get(v.0 as usize).unwrap(), + ) + }) + .collect_vec(); + state.statements.insert(candidate.hash(), statements); + } + } + + state + } + + pub fn reset_trackers(&self) { + self.statements_tracker.values().for_each(|v| { + v.iter() + .enumerate() + .for_each(|(index, v)| v.as_ref().store(index <= 1, Ordering::SeqCst)) + }); + self.manifests_tracker + .values() + .for_each(|v| v.as_ref().store(false, Ordering::SeqCst)); + } +} + +fn sign_statement( + statement: CompactStatement, + relay_parent: H256, + validator_index: ValidatorIndex, + pair: &ValidatorPair, +) -> UncheckedSigned { + let context = SigningContext { parent_hash: relay_parent, session_index: 0 }; + let payload = statement.signing_payload(&context); + + SignedStatement::new( + statement, + validator_index, + pair.sign(&payload[..]), + &context, + &pair.public(), + ) + .unwrap() + .as_unchecked() + .to_owned() +} + +fn generate_block_info(block_num: usize) -> BlockInfo { + new_block_import_info(Hash::repeat_byte(block_num as u8), block_num as BlockNumber) +} + +fn generate_block_header(info: &BlockInfo) -> (H256, Header) { + ( + info.hash, + Header { + digest: Default::default(), + number: info.number, + parent_hash: info.parent_hash, + extrinsics_root: Default::default(), + state_root: Default::default(), + }, + ) +} + +fn generate_pov_size_to_candidate(pov_sizes: &[usize]) -> HashMap { + pov_sizes + .iter() + .cloned() + .unique() + .enumerate() + .map(|(index, pov_size)| (pov_size, index)) + .collect() +} + +fn generate_receipt_templates( + pov_size_to_candidate: &HashMap, + n_validators: usize, + pvd: &PersistedValidationData, +) -> Vec { + pov_size_to_candidate + .iter() + .map(|(&pov_size, &index)| { + let mut receipt = dummy_committed_candidate_receipt(dummy_hash()); + let (_, erasure_root) = derive_erasure_chunks_with_proofs_and_root( + n_validators, + &AvailableData { + validation_data: pvd.clone(), + pov: Arc::new(PoV { block_data: BlockData(vec![index as u8; pov_size]) }), + }, + |_, _| {}, + ); + receipt.descriptor.persisted_validation_data_hash = pvd.hash(); + receipt.descriptor.erasure_root = erasure_root; + receipt + }) + .collect() +} + +#[async_trait::async_trait] +impl HandleNetworkMessage for TestState { + async fn handle( + &self, + message: NetworkMessage, + node_sender: &mut futures::channel::mpsc::UnboundedSender, + ) -> Option { + match message { + NetworkMessage::RequestFromNode(_authority_id, Requests::AttestedCandidateV2(req)) => { + let payload = req.payload; + let candidate_receipt = self + .commited_candidate_receipts + .values() + .flatten() + .find(|v| v.hash() == payload.candidate_hash) + .unwrap() + .clone(); + let persisted_validation_data = self.pvd.clone(); + let statements = self.statements.get(&payload.candidate_hash).unwrap().clone(); + let res = AttestedCandidateResponse { + candidate_receipt, + persisted_validation_data, + statements, + }; + let _ = req.pending_response.send(Ok((res.encode(), ProtocolName::from("")))); + None + }, + NetworkMessage::MessageFromNode( + authority_id, + Versioned::V3(ValidationProtocol::StatementDistribution( + StatementDistributionMessage::Statement(relay_parent, statement), + )), + ) => { + let index = self + .test_authorities + .validator_authority_id + .iter() + .position(|v| v == &authority_id) + .unwrap(); + let candidate_hash = *statement.unchecked_payload().candidate_hash(); + + let statements_sent_count = self + .statements_tracker + .get(&candidate_hash) + .unwrap() + .get(index) + .unwrap() + .as_ref(); + if statements_sent_count.load(Ordering::SeqCst) { + return None + } else { + statements_sent_count.store(true, Ordering::SeqCst); + } + + let group_statements = self.statements.get(&candidate_hash).unwrap(); + if !group_statements.iter().any(|s| s.unchecked_validator_index().0 == index as u32) + { + return None + } + + let statement = CompactStatement::Valid(candidate_hash); + let context = SigningContext { parent_hash: relay_parent, session_index: 0 }; + let payload = statement.signing_payload(&context); + let pair = self.test_authorities.validator_pairs.get(index).unwrap(); + let signature = pair.sign(&payload[..]); + let statement = SignedStatement::new( + statement, + ValidatorIndex(index as u32), + signature, + &context, + &pair.public(), + ) + .unwrap() + .as_unchecked() + .to_owned(); + + node_sender + .start_send(NetworkMessage::MessageFromPeer( + *self.test_authorities.peer_ids.get(index).unwrap(), + Versioned::V3(ValidationProtocol::StatementDistribution( + StatementDistributionMessage::Statement(relay_parent, statement), + )), + )) + .unwrap(); + None + }, + NetworkMessage::MessageFromNode( + authority_id, + Versioned::V3(ValidationProtocol::StatementDistribution( + StatementDistributionMessage::BackedCandidateManifest(manifest), + )), + ) => { + let index = self + .test_authorities + .validator_authority_id + .iter() + .position(|v| v == &authority_id) + .unwrap(); + let backing_group = + self.session_info.validator_groups.get(manifest.group_index).unwrap(); + let group_size = backing_group.len(); + let is_own_backing_group = backing_group.contains(&ValidatorIndex(NODE_UNDER_TEST)); + let mut seconded_in_group = + BitVec::from_iter((0..group_size).map(|_| !is_own_backing_group)); + let mut validated_in_group = BitVec::from_iter((0..group_size).map(|_| false)); + + if is_own_backing_group { + let (pending_response, response_receiver) = oneshot::channel(); + let peer_id = self.test_authorities.peer_ids.get(index).unwrap().to_owned(); + node_sender + .start_send(NetworkMessage::RequestFromPeer(IncomingRequest { + peer: peer_id, + payload: AttestedCandidateRequest { + candidate_hash: manifest.candidate_hash, + mask: StatementFilter::blank(self.own_backing_group.len()), + } + .encode(), + pending_response, + })) + .unwrap(); + + let response = response_receiver.await.unwrap(); + let response = + AttestedCandidateResponse::decode(&mut response.result.unwrap().as_ref()) + .unwrap(); + + for statement in response.statements { + let validator_index = statement.unchecked_validator_index(); + let position_in_group = + backing_group.iter().position(|v| *v == validator_index).unwrap(); + match statement.unchecked_payload() { + CompactStatement::Seconded(_) => + seconded_in_group.set(position_in_group, true), + CompactStatement::Valid(_) => + validated_in_group.set(position_in_group, true), + } + } + } + + let ack = BackedCandidateAcknowledgement { + candidate_hash: manifest.candidate_hash, + statement_knowledge: StatementFilter { seconded_in_group, validated_in_group }, + }; + node_sender + .start_send(NetworkMessage::MessageFromPeer( + *self.test_authorities.peer_ids.get(index).unwrap(), + Versioned::V3(ValidationProtocol::StatementDistribution( + StatementDistributionMessage::BackedCandidateKnown(ack), + )), + )) + .unwrap(); + + self.manifests_tracker + .get(&manifest.candidate_hash) + .unwrap() + .as_ref() + .store(true, Ordering::SeqCst); + + None + }, + NetworkMessage::MessageFromNode( + _authority_id, + Versioned::V3(ValidationProtocol::StatementDistribution( + StatementDistributionMessage::BackedCandidateKnown(ack), + )), + ) => { + self.manifests_tracker + .get(&ack.candidate_hash) + .unwrap() + .as_ref() + .store(true, Ordering::SeqCst); + + None + }, + _ => Some(message), + } + } +} diff --git a/polkadot/node/subsystem-bench/src/lib/usage.rs b/polkadot/node/subsystem-bench/src/lib/usage.rs index bfaac3265a2e3741aaa2fa4811785bd90e8ea016..883e9aa7ad0a0cec210ef49ccd7542f17d7256ee 100644 --- a/polkadot/node/subsystem-bench/src/lib/usage.rs +++ b/polkadot/node/subsystem-bench/src/lib/usage.rs @@ -23,7 +23,6 @@ use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct BenchmarkUsage { - pub benchmark_name: String, pub network_usage: Vec, pub cpu_usage: Vec, } @@ -32,8 +31,7 @@ impl std::fmt::Display for BenchmarkUsage { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, - "\n{}\n\n{}\n{}\n\n{}\n{}\n", - self.benchmark_name.purple(), + "\n{}\n{}\n\n{}\n{}\n", format!("{:<32}{:>12}{:>12}", "Network usage, KiB", "total", "per block").blue(), self.network_usage .iter() @@ -59,18 +57,17 @@ impl BenchmarkUsage { let all_cpu_usage: Vec<&ResourceUsage> = usages.iter().flat_map(|v| &v.cpu_usage).collect(); Self { - benchmark_name: usages.first().map(|v| v.benchmark_name.clone()).unwrap_or_default(), network_usage: ResourceUsage::average_by_resource_name(&all_network_usages), cpu_usage: ResourceUsage::average_by_resource_name(&all_cpu_usage), } } pub fn check_network_usage(&self, checks: &[ResourceUsageCheck]) -> Vec { - check_usage(&self.benchmark_name, &self.network_usage, checks) + check_usage(&self.network_usage, checks) } pub fn check_cpu_usage(&self, checks: &[ResourceUsageCheck]) -> Vec { - check_usage(&self.benchmark_name, &self.cpu_usage, checks) + check_usage(&self.cpu_usage, checks) } pub fn cpu_usage_diff(&self, other: &Self, resource_name: &str) -> Option { @@ -105,18 +102,8 @@ impl BenchmarkUsage { } } -fn check_usage( - benchmark_name: &str, - usage: &[ResourceUsage], - checks: &[ResourceUsageCheck], -) -> Vec { - checks - .iter() - .filter_map(|check| { - check_resource_usage(usage, check) - .map(|message| format!("{}: {}", benchmark_name, message)) - }) - .collect() +fn check_usage(usage: &[ResourceUsage], checks: &[ResourceUsageCheck]) -> Vec { + checks.iter().filter_map(|check| check_resource_usage(usage, check)).collect() } fn check_resource_usage( diff --git a/polkadot/node/subsystem-test-helpers/src/lib.rs b/polkadot/node/subsystem-test-helpers/src/lib.rs index 6c1ac86c4507b798e4270b7c52e97a4dad74b64c..375121c3746377157e852de382c9d2cb64bce496 100644 --- a/polkadot/node/subsystem-test-helpers/src/lib.rs +++ b/polkadot/node/subsystem-test-helpers/src/lib.rs @@ -25,7 +25,7 @@ use polkadot_node_subsystem::{ SubsystemError, SubsystemResult, TrySendError, }; use polkadot_node_subsystem_util::TimeoutExt; -use polkadot_primitives::{Hash, ValidatorIndex}; +use polkadot_primitives::{ChunkIndex, Hash}; use futures::{channel::mpsc, poll, prelude::*}; use parking_lot::Mutex; @@ -487,7 +487,7 @@ pub fn derive_erasure_chunks_with_proofs_and_root( .enumerate() .map(|(index, (proof, chunk))| ErasureChunk { chunk: chunk.to_vec(), - index: ValidatorIndex(index as _), + index: ChunkIndex(index as _), proof: Proof::try_from(proof).unwrap(), }) .collect::>(); diff --git a/polkadot/node/subsystem-types/Cargo.toml b/polkadot/node/subsystem-types/Cargo.toml index 93dd43c5dbfc495ff92fa76f28e3ad80992b8a6a..e03fc60a1fd73c32e0ebfaa6c0d63e76b3d4aebc 100644 --- a/polkadot/node/subsystem-types/Cargo.toml +++ b/polkadot/node/subsystem-types/Cargo.toml @@ -11,6 +11,7 @@ workspace = true [dependencies] derive_more = "0.99.17" +fatality = "0.1.1" futures = "0.3.30" polkadot-primitives = { path = "../../primitives" } polkadot-node-primitives = { path = "../primitives" } diff --git a/polkadot/node/subsystem-types/src/errors.rs b/polkadot/node/subsystem-types/src/errors.rs index 44136362a69efa0ba316413cc9f78d834b5c3e9f..b8e70641243eab6b6958649c416ab1b533f9abc5 100644 --- a/polkadot/node/subsystem-types/src/errors.rs +++ b/polkadot/node/subsystem-types/src/errors.rs @@ -18,6 +18,7 @@ use crate::JaegerError; use ::orchestra::OrchestraError as OverseerError; +use fatality::fatality; /// A description of an error causing the runtime API request to be unservable. #[derive(thiserror::Error, Debug, Clone)] @@ -68,32 +69,21 @@ impl core::fmt::Display for ChainApiError { impl std::error::Error for ChainApiError {} /// An error that may happen during Availability Recovery process. -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Clone)] +#[fatality(splitable)] +#[allow(missing_docs)] pub enum RecoveryError { - /// A chunk is recovered but is invalid. + #[error("Invalid data")] Invalid, - /// A requested chunk is unavailable. + #[error("Data is unavailable")] Unavailable, - /// Erasure task channel closed, usually means node is shutting down. + #[fatal] + #[error("Erasure task channel closed")] ChannelClosed, } -impl std::fmt::Display for RecoveryError { - fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { - let msg = match self { - RecoveryError::Invalid => "Invalid", - RecoveryError::Unavailable => "Unavailable", - RecoveryError::ChannelClosed => "ChannelClosed", - }; - - write!(f, "{}", msg) - } -} - -impl std::error::Error for RecoveryError {} - /// An error type that describes faults that may happen /// /// These are: diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index e75d80395c4ba0371b58ce1383db2a1f364eaad8..722a97989bce0b8587c8992827f6438fd78ff21e 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -62,7 +62,7 @@ pub mod network_bridge_event; pub use network_bridge_event::NetworkBridgeEvent; /// A request to the candidate backing subsystem to check whether -/// there exists vacant membership in some fragment tree. +/// we can second this candidate. #[derive(Debug, Copy, Clone)] pub struct CanSecondRequest { /// Para id of the candidate. @@ -90,10 +90,12 @@ pub enum CandidateBackingMessage { oneshot::Sender>>, ), /// Request the subsystem to check whether it's allowed to second given candidate. - /// The rule is to only fetch collations that are either built on top of the root - /// of some fragment tree or have a parent node which represents backed candidate. + /// The rule is to only fetch collations that can either be directly chained to any + /// FragmentChain in the view or there is at least one FragmentChain where this candidate is a + /// potentially unconnected candidate (we predict that it may become connected to a + /// FragmentChain in the future). /// - /// Always responses with `false` if async backing is disabled for candidate's relay + /// Always responds with `false` if async backing is disabled for candidate's relay /// parent. CanSecond(CanSecondRequest, oneshot::Sender), /// Note that the Candidate Backing subsystem should second the given candidate in the context @@ -244,13 +246,6 @@ pub enum CollatorProtocolMessage { /// /// The hash is the relay parent. Seconded(Hash, SignedFullStatement), - /// The candidate received enough validity votes from the backing group. - Backed { - /// Candidate's para id. - para_id: ParaId, - /// Hash of the para head generated by candidate. - para_head: Hash, - }, } impl Default for CollatorProtocolMessage { @@ -485,6 +480,8 @@ pub enum AvailabilityRecoveryMessage { CandidateReceipt, SessionIndex, Option, // Optional backing group to request from first. + Option, /* A `CoreIndex` needs to be specified for the recovery process to + * prefer systematic chunk recovery. */ oneshot::Sender>, ), } @@ -520,7 +517,7 @@ pub enum AvailabilityStoreMessage { QueryChunkSize(CandidateHash, oneshot::Sender>), /// Query all chunks that we have for the given candidate hash. - QueryAllChunks(CandidateHash, oneshot::Sender>), + QueryAllChunks(CandidateHash, oneshot::Sender>), /// Query whether an `ErasureChunk` exists within the AV Store. /// @@ -535,6 +532,8 @@ pub enum AvailabilityStoreMessage { StoreChunk { /// A hash of the candidate this chunk belongs to. candidate_hash: CandidateHash, + /// Validator index. May not be equal to the chunk index. + validator_index: ValidatorIndex, /// The chunk itself. chunk: ErasureChunk, /// Sending side of the channel to send result to. @@ -554,6 +553,11 @@ pub enum AvailabilityStoreMessage { available_data: AvailableData, /// Erasure root we expect to get after chunking. expected_erasure_root: Hash, + /// Core index where the candidate was backed. + core_index: CoreIndex, + /// Node features at the candidate relay parent. Used for computing the validator->chunk + /// mapping. + node_features: NodeFeatures, /// Sending side of the channel to send result to. tx: oneshot::Sender>, }, @@ -1023,9 +1027,9 @@ pub enum GossipSupportMessage { NetworkBridgeUpdate(NetworkBridgeEvent), } -/// Request introduction of a candidate into the prospective parachains subsystem. +/// Request introduction of a seconded candidate into the prospective parachains subsystem. #[derive(Debug, PartialEq, Eq, Clone)] -pub struct IntroduceCandidateRequest { +pub struct IntroduceSecondedCandidateRequest { /// The para-id of the candidate. pub candidate_para: ParaId, /// The candidate receipt itself. @@ -1034,7 +1038,7 @@ pub struct IntroduceCandidateRequest { pub persisted_validation_data: PersistedValidationData, } -/// A hypothetical candidate to be evaluated for frontier membership +/// A hypothetical candidate to be evaluated for potential/actual membership /// in the prospective parachains subsystem. /// /// Hypothetical candidates are either complete or incomplete. @@ -1103,21 +1107,27 @@ impl HypotheticalCandidate { candidate_relay_parent, } } + + /// Get the output head data hash, if the candidate is complete. + pub fn output_head_data_hash(&self) -> Option { + match *self { + HypotheticalCandidate::Complete { ref receipt, .. } => + Some(receipt.descriptor.para_head), + HypotheticalCandidate::Incomplete { .. } => None, + } + } } /// Request specifying which candidates are either already included -/// or might be included in the hypothetical frontier of fragment trees -/// under a given active leaf. +/// or might become included in fragment chain under a given active leaf (or any active leaf if +/// `fragment_chain_relay_parent` is `None`). #[derive(Debug, PartialEq, Eq, Clone)] -pub struct HypotheticalFrontierRequest { +pub struct HypotheticalMembershipRequest { /// Candidates, in arbitrary order, which should be checked for - /// possible membership in fragment trees. + /// hypothetical/actual membership in fragment chains. pub candidates: Vec, - /// Either a specific fragment tree to check, otherwise all. - pub fragment_tree_relay_parent: Option, - /// Only return membership if all candidates in the path from the - /// root are backed. - pub backed_in_path_only: bool, + /// Either a specific fragment chain to check, otherwise all. + pub fragment_chain_relay_parent: Option, } /// A request for the persisted validation data stored in the prospective @@ -1156,9 +1166,9 @@ impl ParentHeadData { } } -/// Indicates the relay-parents whose fragment tree a candidate -/// is present in and the depths of that tree the candidate is present in. -pub type FragmentTreeMembership = Vec<(Hash, Vec)>; +/// Indicates the relay-parents whose fragment chain a candidate +/// is present in or can be added in (right now or in the future). +pub type HypotheticalMembership = Vec; /// A collection of ancestor candidates of a parachain. pub type Ancestors = HashSet; @@ -1166,15 +1176,11 @@ pub type Ancestors = HashSet; /// Messages sent to the Prospective Parachains subsystem. #[derive(Debug)] pub enum ProspectiveParachainsMessage { - /// Inform the Prospective Parachains Subsystem of a new candidate. + /// Inform the Prospective Parachains Subsystem of a new seconded candidate. /// - /// The response sender accepts the candidate membership, which is the existing - /// membership of the candidate if it was already known. - IntroduceCandidate(IntroduceCandidateRequest, oneshot::Sender), - /// Inform the Prospective Parachains Subsystem that a previously introduced candidate - /// has been seconded. This requires that the candidate was successfully introduced in - /// the past. - CandidateSeconded(ParaId, CandidateHash), + /// The response sender returns false if the candidate was rejected by prospective parachains, + /// true otherwise (if it was accepted or already present) + IntroduceSecondedCandidate(IntroduceSecondedCandidateRequest, oneshot::Sender), /// Inform the Prospective Parachains Subsystem that a previously introduced candidate /// has been backed. This requires that the candidate was successfully introduced in /// the past. @@ -1193,23 +1199,29 @@ pub enum ProspectiveParachainsMessage { Ancestors, oneshot::Sender>, ), - /// Get the hypothetical frontier membership of candidates with the given properties - /// under the specified active leaves' fragment trees. + /// Get the hypothetical or actual membership of candidates with the given properties + /// under the specified active leave's fragment chain. + /// + /// For each candidate, we return a vector of leaves where the candidate is present or could be + /// added. "Could be added" either means that the candidate can be added to the chain right now + /// or could be added in the future (we may not have its ancestors yet). + /// Note that even if we think it could be added in the future, we may find out that it was + /// invalid, as time passes. + /// If an active leaf is not in the vector, it means that there's no + /// chance this candidate will become valid under that leaf in the future. /// - /// For any candidate which is already known, this returns the depths the candidate - /// occupies. - GetHypotheticalFrontier( - HypotheticalFrontierRequest, - oneshot::Sender>, + /// If `fragment_chain_relay_parent` in the request is `Some()`, the return vector can only + /// contain this relay parent (or none). + GetHypotheticalMembership( + HypotheticalMembershipRequest, + oneshot::Sender>, ), - /// Get the membership of the candidate in all fragment trees. - GetTreeMembership(ParaId, CandidateHash, oneshot::Sender), - /// Get the minimum accepted relay-parent number for each para in the fragment tree + /// Get the minimum accepted relay-parent number for each para in the fragment chain /// for the given relay-chain block hash. /// /// That is, if the block hash is known and is an active leaf, this returns the /// minimum relay-parent block number in the same branch of the relay chain which - /// is accepted in the fragment tree for each para-id. + /// is accepted in the fragment chain for each para-id. /// /// If the block hash is not an active leaf, this will return an empty vector. /// @@ -1219,8 +1231,10 @@ pub enum ProspectiveParachainsMessage { /// Para-IDs are returned in no particular order. GetMinimumRelayParents(Hash, oneshot::Sender>), /// Get the validation data of some prospective candidate. The candidate doesn't need - /// to be part of any fragment tree, but this only succeeds if the parent head-data and - /// relay-parent are part of some fragment tree. + /// to be part of any fragment chain, but this only succeeds if the parent head-data and + /// relay-parent are part of the `CandidateStorage` (meaning that it's a candidate which is + /// part of some fragment chain or which prospective-parachains predicted will become part of + /// some fragment chain). GetProspectiveValidationData( ProspectiveValidationDataRequest, oneshot::Sender>, diff --git a/polkadot/node/subsystem-util/Cargo.toml b/polkadot/node/subsystem-util/Cargo.toml index 79a6a75e4cdfb5cf644dc8f963e51d0ef49c1fcd..9259ca94f07359dcc1ca7eac29647e34f1f18428 100644 --- a/polkadot/node/subsystem-util/Cargo.toml +++ b/polkadot/node/subsystem-util/Cargo.toml @@ -13,17 +13,18 @@ workspace = true async-trait = "0.1.79" futures = "0.3.30" futures-channel = "0.3.23" -itertools = "0.10" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +itertools = "0.11" +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } parking_lot = "0.12.1" pin-project = "1.0.9" rand = "0.8.5" thiserror = { workspace = true } -fatality = "0.0.6" +fatality = "0.1.1" gum = { package = "tracing-gum", path = "../gum" } derive_more = "0.99.17" schnellru = "0.2.1" +erasure-coding = { package = "polkadot-erasure-coding", path = "../../erasure-coding" } polkadot-node-subsystem = { path = "../subsystem" } polkadot-node-subsystem-types = { path = "../subsystem-types" } polkadot-node-jaeger = { path = "../jaeger" } diff --git a/polkadot/node/subsystem-util/src/availability_chunks.rs b/polkadot/node/subsystem-util/src/availability_chunks.rs new file mode 100644 index 0000000000000000000000000000000000000000..45168e4512e156fcc9151f28246c95f32f8e184e --- /dev/null +++ b/polkadot/node/subsystem-util/src/availability_chunks.rs @@ -0,0 +1,227 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use erasure_coding::systematic_recovery_threshold; +use polkadot_primitives::{node_features, ChunkIndex, CoreIndex, NodeFeatures, ValidatorIndex}; + +/// Compute the per-validator availability chunk index. +/// WARNING: THIS FUNCTION IS CRITICAL TO PARACHAIN CONSENSUS. +/// Any modification to the output of the function needs to be coordinated via the runtime. +/// It's best to use minimal/no external dependencies. +pub fn availability_chunk_index( + maybe_node_features: Option<&NodeFeatures>, + n_validators: usize, + core_index: CoreIndex, + validator_index: ValidatorIndex, +) -> Result { + if let Some(features) = maybe_node_features { + if let Some(&true) = features + .get(usize::from(node_features::FeatureIndex::AvailabilityChunkMapping as u8)) + .as_deref() + { + let systematic_threshold = systematic_recovery_threshold(n_validators)? as u32; + let core_start_pos = core_index.0 * systematic_threshold; + + return Ok(ChunkIndex((core_start_pos + validator_index.0) % n_validators as u32)) + } + } + + Ok(validator_index.into()) +} + +/// Compute the per-core availability chunk indices. Returns a Vec which maps ValidatorIndex to +/// ChunkIndex for a given availability core index +/// WARNING: THIS FUNCTION IS CRITICAL TO PARACHAIN CONSENSUS. +/// Any modification to the output of the function needs to be coordinated via the +/// runtime. It's best to use minimal/no external dependencies. +pub fn availability_chunk_indices( + maybe_node_features: Option<&NodeFeatures>, + n_validators: usize, + core_index: CoreIndex, +) -> Result, erasure_coding::Error> { + let identity = (0..n_validators).map(|index| ChunkIndex(index as u32)); + if let Some(features) = maybe_node_features { + if let Some(&true) = features + .get(usize::from(node_features::FeatureIndex::AvailabilityChunkMapping as u8)) + .as_deref() + { + let systematic_threshold = systematic_recovery_threshold(n_validators)? as u32; + let core_start_pos = core_index.0 * systematic_threshold; + + return Ok(identity + .into_iter() + .cycle() + .skip(core_start_pos as usize) + .take(n_validators) + .collect()) + } + } + + Ok(identity.collect()) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + pub fn node_features_with_mapping_enabled() -> NodeFeatures { + let mut node_features = NodeFeatures::new(); + node_features + .resize(node_features::FeatureIndex::AvailabilityChunkMapping as usize + 1, false); + node_features + .set(node_features::FeatureIndex::AvailabilityChunkMapping as u8 as usize, true); + node_features + } + + pub fn node_features_with_other_bits_enabled() -> NodeFeatures { + let mut node_features = NodeFeatures::new(); + node_features.resize(node_features::FeatureIndex::FirstUnassigned as usize + 1, true); + node_features + .set(node_features::FeatureIndex::AvailabilityChunkMapping as u8 as usize, false); + node_features + } + + #[test] + fn test_availability_chunk_indices() { + let n_validators = 20u32; + let n_cores = 15u32; + + // If the mapping feature is not enabled, it should always be the identity vector. + { + for node_features in + [None, Some(NodeFeatures::EMPTY), Some(node_features_with_other_bits_enabled())] + { + for core_index in 0..n_cores { + let indices = availability_chunk_indices( + node_features.as_ref(), + n_validators as usize, + CoreIndex(core_index), + ) + .unwrap(); + + for validator_index in 0..n_validators { + assert_eq!( + indices[validator_index as usize], + availability_chunk_index( + node_features.as_ref(), + n_validators as usize, + CoreIndex(core_index), + ValidatorIndex(validator_index) + ) + .unwrap() + ) + } + + assert_eq!( + indices, + (0..n_validators).map(|i| ChunkIndex(i)).collect::>() + ); + } + } + } + + // Test when mapping feature is enabled. + { + let node_features = node_features_with_mapping_enabled(); + let mut previous_indices = None; + + for core_index in 0..n_cores { + let indices = availability_chunk_indices( + Some(&node_features), + n_validators as usize, + CoreIndex(core_index), + ) + .unwrap(); + + for validator_index in 0..n_validators { + assert_eq!( + indices[validator_index as usize], + availability_chunk_index( + Some(&node_features), + n_validators as usize, + CoreIndex(core_index), + ValidatorIndex(validator_index) + ) + .unwrap() + ) + } + + // Check that it's not equal to the previous core's indices. + if let Some(previous_indices) = previous_indices { + assert_ne!(previous_indices, indices); + } + + previous_indices = Some(indices.clone()); + + // Check that it's indeed a permutation. + assert_eq!( + (0..n_validators).map(|i| ChunkIndex(i)).collect::>(), + indices.into_iter().collect::>() + ); + } + } + } + + #[test] + // This is just a dummy test that checks the mapping against some hardcoded outputs, to prevent + // accidental changes to the algorithms. + fn prevent_changes_to_mapping() { + let n_validators = 7; + let node_features = node_features_with_mapping_enabled(); + + assert_eq!( + availability_chunk_indices(Some(&node_features), n_validators, CoreIndex(0)) + .unwrap() + .into_iter() + .map(|i| i.0) + .collect::>(), + vec![0, 1, 2, 3, 4, 5, 6] + ); + assert_eq!( + availability_chunk_indices(Some(&node_features), n_validators, CoreIndex(1)) + .unwrap() + .into_iter() + .map(|i| i.0) + .collect::>(), + vec![2, 3, 4, 5, 6, 0, 1] + ); + assert_eq!( + availability_chunk_indices(Some(&node_features), n_validators, CoreIndex(2)) + .unwrap() + .into_iter() + .map(|i| i.0) + .collect::>(), + vec![4, 5, 6, 0, 1, 2, 3] + ); + assert_eq!( + availability_chunk_indices(Some(&node_features), n_validators, CoreIndex(3)) + .unwrap() + .into_iter() + .map(|i| i.0) + .collect::>(), + vec![6, 0, 1, 2, 3, 4, 5] + ); + assert_eq!( + availability_chunk_indices(Some(&node_features), n_validators, CoreIndex(4)) + .unwrap() + .into_iter() + .map(|i| i.0) + .collect::>(), + vec![1, 2, 3, 4, 5, 6, 0] + ); + } +} diff --git a/polkadot/node/subsystem-util/src/backing_implicit_view.rs b/polkadot/node/subsystem-util/src/backing_implicit_view.rs index a14536a17666c8e2d9183755e3579990f6185113..23a758d25715bbd33251b5edf8835ca3625f3ffa 100644 --- a/polkadot/node/subsystem-util/src/backing_implicit_view.rs +++ b/polkadot/node/subsystem-util/src/backing_implicit_view.rs @@ -17,23 +17,45 @@ use futures::channel::oneshot; use polkadot_node_subsystem::{ errors::ChainApiError, - messages::{ChainApiMessage, ProspectiveParachainsMessage}, + messages::{ChainApiMessage, ProspectiveParachainsMessage, RuntimeApiMessage}, SubsystemSender, }; use polkadot_primitives::{BlockNumber, Hash, Id as ParaId}; use std::collections::HashMap; +use crate::{ + request_session_index_for_child, + runtime::{self, prospective_parachains_mode, recv_runtime, ProspectiveParachainsMode}, +}; + // Always aim to retain 1 block before the active leaves. const MINIMUM_RETAIN_LENGTH: BlockNumber = 2; /// Handles the implicit view of the relay chain derived from the immediate view, which /// is composed of active leaves, and the minimum relay-parents allowed for /// candidates of various parachains at those leaves. -#[derive(Default, Clone)] +#[derive(Clone)] pub struct View { leaves: HashMap, block_info_storage: HashMap, + collating_for: Option, +} + +impl View { + /// Create a new empty view. + /// If `collating_for` is `Some`, the node is a collator and is only interested in the allowed + /// relay parents of a single paraid. When this is true, prospective-parachains is no longer + /// queried. + pub fn new(collating_for: Option) -> Self { + Self { leaves: Default::default(), block_info_storage: Default::default(), collating_for } + } +} + +impl Default for View { + fn default() -> Self { + Self::new(None) + } } // Minimum relay parents implicitly relative to a particular block. @@ -106,15 +128,13 @@ impl View { } /// Activate a leaf in the view. - /// This will request the minimum relay parents from the - /// Prospective Parachains subsystem for each leaf and will load headers in the ancestry of each - /// leaf in the view as needed. These are the 'implicit ancestors' of the leaf. + /// This will request the minimum relay parents the leaf and will load headers in the + /// ancestry of the leaf as needed. These are the 'implicit ancestors' of the leaf. /// /// To maximize reuse of outdated leaves, it's best to activate new leaves before /// deactivating old ones. /// - /// This returns a list of para-ids which are relevant to the leaf, - /// and the allowed relay parents for these paras under this leaf can be + /// The allowed relay parents for the relevant paras under this leaf can be /// queried with [`View::known_allowed_relay_parents_under`]. /// /// No-op for known leaves. @@ -122,10 +142,11 @@ impl View { &mut self, sender: &mut Sender, leaf_hash: Hash, - ) -> Result, FetchError> + ) -> Result<(), FetchError> where - Sender: SubsystemSender, - Sender: SubsystemSender, + Sender: SubsystemSender + + SubsystemSender + + SubsystemSender, { if self.leaves.contains_key(&leaf_hash) { return Err(FetchError::AlreadyKnown) @@ -135,6 +156,7 @@ impl View { leaf_hash, &mut self.block_info_storage, &mut *sender, + self.collating_for, ) .await; @@ -150,7 +172,7 @@ impl View { self.leaves.insert(leaf_hash, ActiveLeafPruningInfo { retain_minimum }); - Ok(fetched.relevant_paras) + Ok(()) }, Err(e) => Err(e), } @@ -249,6 +271,10 @@ pub enum FetchError { /// Request to the Chain API subsystem failed. #[error("The chain API subsystem was unavailable")] ChainApiUnavailable, + + /// Request to the runtime API failed. + #[error("Runtime API error: {0}")] + RuntimeApi(#[from] runtime::Error), } /// Reasons a block header might have been unavailable. @@ -265,30 +291,92 @@ pub enum BlockHeaderUnavailableReason { struct FetchSummary { minimum_ancestor_number: BlockNumber, leaf_number: BlockNumber, - relevant_paras: Vec, } -async fn fetch_fresh_leaf_and_insert_ancestry( +// Request the min relay parents from prospective-parachains. +async fn fetch_min_relay_parents_from_prospective_parachains< + Sender: SubsystemSender, +>( leaf_hash: Hash, - block_info_storage: &mut HashMap, sender: &mut Sender, -) -> Result +) -> Result, FetchError> { + let (tx, rx) = oneshot::channel(); + sender + .send_message(ProspectiveParachainsMessage::GetMinimumRelayParents(leaf_hash, tx)) + .await; + + rx.await.map_err(|_| FetchError::ProspectiveParachainsUnavailable) +} + +// Request the min relay parent for the purposes of a collator, directly using ChainApi (where +// prospective-parachains is not available). +async fn fetch_min_relay_parents_for_collator( + leaf_hash: Hash, + leaf_number: BlockNumber, + sender: &mut Sender, +) -> Result, FetchError> where - Sender: SubsystemSender, - Sender: SubsystemSender, + Sender: SubsystemSender + + SubsystemSender + + SubsystemSender, { - let min_relay_parents_raw = { - let (tx, rx) = oneshot::channel(); - sender - .send_message(ProspectiveParachainsMessage::GetMinimumRelayParents(leaf_hash, tx)) - .await; + let Ok(ProspectiveParachainsMode::Enabled { allowed_ancestry_len, .. }) = + prospective_parachains_mode(sender, leaf_hash).await + else { + // This should never happen, leaves that don't have prospective parachains mode enabled + // should not use implicit view. + return Ok(None) + }; - match rx.await { - Ok(m) => m, - Err(_) => return Err(FetchError::ProspectiveParachainsUnavailable), + // Fetch the session of the leaf. We must make sure that we stop at the ancestor which has a + // different session index. + let required_session = + recv_runtime(request_session_index_for_child(leaf_hash, sender).await).await?; + + let mut min = leaf_number; + + // Fetch the ancestors, up to allowed_ancestry_len. + let (tx, rx) = oneshot::channel(); + sender + .send_message(ChainApiMessage::Ancestors { + hash: leaf_hash, + k: allowed_ancestry_len, + response_channel: tx, + }) + .await; + let hashes = rx + .await + .map_err(|_| FetchError::ChainApiUnavailable)? + .map_err(|err| FetchError::ChainApiError(leaf_hash, err))?; + + for hash in hashes { + // The relay chain cannot accept blocks backed from previous sessions, with + // potentially previous validators. This is a technical limitation we need to + // respect here. + let session = recv_runtime(request_session_index_for_child(hash, sender).await).await?; + + if session == required_session { + // We should never underflow here, the ChainAPI stops at genesis block. + min = min.saturating_sub(1); + } else { + break } - }; + } + Ok(Some(min)) +} + +async fn fetch_fresh_leaf_and_insert_ancestry( + leaf_hash: Hash, + block_info_storage: &mut HashMap, + sender: &mut Sender, + collating_for: Option, +) -> Result +where + Sender: SubsystemSender + + SubsystemSender + + SubsystemSender, +{ let leaf_header = { let (tx, rx) = oneshot::channel(); sender.send_message(ChainApiMessage::BlockHeader(leaf_hash, tx)).await; @@ -313,8 +401,18 @@ where } }; - let min_min = min_relay_parents_raw.iter().map(|x| x.1).min().unwrap_or(leaf_header.number); - let relevant_paras = min_relay_parents_raw.iter().map(|x| x.0).collect(); + // If the node is a collator, bypass prospective-parachains. We're only interested in the one + // paraid and the subsystem is not present. + let min_relay_parents = if let Some(para_id) = collating_for { + fetch_min_relay_parents_for_collator(leaf_hash, leaf_header.number, sender) + .await? + .map(|x| vec![(para_id, x)]) + .unwrap_or_default() + } else { + fetch_min_relay_parents_from_prospective_parachains(leaf_hash, sender).await? + }; + + let min_min = min_relay_parents.iter().map(|x| x.1).min().unwrap_or(leaf_header.number); let expected_ancestry_len = (leaf_header.number.saturating_sub(min_min) as usize) + 1; let ancestry = if leaf_header.number > 0 { @@ -380,14 +478,11 @@ where vec![leaf_hash] }; - let fetched_ancestry = FetchSummary { - minimum_ancestor_number: min_min, - leaf_number: leaf_header.number, - relevant_paras, - }; + let fetched_ancestry = + FetchSummary { minimum_ancestor_number: min_min, leaf_number: leaf_header.number }; let allowed_relay_parents = AllowedRelayParents { - minimum_relay_parents: min_relay_parents_raw.iter().cloned().collect(), + minimum_relay_parents: min_relay_parents.into_iter().collect(), allowed_relay_parents_contiguous: ancestry, }; @@ -408,12 +503,12 @@ mod tests { use crate::TimeoutExt; use assert_matches::assert_matches; use futures::future::{join, FutureExt}; - use polkadot_node_subsystem::AllMessages; + use polkadot_node_subsystem::{messages::RuntimeApiRequest, AllMessages}; use polkadot_node_subsystem_test_helpers::{ make_subsystem_context, TestSubsystemContextHandle, }; use polkadot_overseer::SubsystemContext; - use polkadot_primitives::Header; + use polkadot_primitives::{AsyncBackingParams, Header}; use sp_core::testing::TaskExecutor; use std::time::Duration; @@ -514,6 +609,71 @@ mod tests { ); } + async fn assert_async_backing_params_request( + virtual_overseer: &mut VirtualOverseer, + leaf: Hash, + params: AsyncBackingParams, + ) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + leaf_hash, + RuntimeApiRequest::AsyncBackingParams( + tx + ) + ) + ) => { + assert_eq!(leaf, leaf_hash, "received unexpected leaf hash"); + tx.send(Ok(params)).unwrap(); + } + ); + } + + async fn assert_session_index_request( + virtual_overseer: &mut VirtualOverseer, + leaf: Hash, + session: u32, + ) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + leaf_hash, + RuntimeApiRequest::SessionIndexForChild( + tx + ) + ) + ) => { + assert_eq!(leaf, leaf_hash, "received unexpected leaf hash"); + tx.send(Ok(session)).unwrap(); + } + ); + } + + async fn assert_ancestors_request( + virtual_overseer: &mut VirtualOverseer, + leaf: Hash, + expected_ancestor_len: u32, + response: Vec, + ) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::ChainApi( + ChainApiMessage::Ancestors { + hash: leaf_hash, + k, + response_channel: tx + } + ) => { + assert_eq!(leaf, leaf_hash, "received unexpected leaf hash"); + assert_eq!(k, expected_ancestor_len as usize); + + tx.send(Ok(response)).unwrap(); + } + ); + } + #[test] fn construct_fresh_view() { let pool = TaskExecutor::new(); @@ -521,6 +681,8 @@ mod tests { let mut view = View::default(); + assert_eq!(view.collating_for, None); + // Chain B. const PARA_A_MIN_PARENT: u32 = 4; const PARA_B_MIN_PARENT: u32 = 3; @@ -528,15 +690,17 @@ mod tests { let prospective_response = vec![(PARA_A, PARA_A_MIN_PARENT), (PARA_B, PARA_B_MIN_PARENT)]; let leaf = CHAIN_B.last().unwrap(); + let leaf_idx = CHAIN_B.len() - 1; let min_min_idx = (PARA_B_MIN_PARENT - GENESIS_NUMBER - 1) as usize; let fut = view.activate_leaf(ctx.sender(), *leaf).timeout(TIMEOUT).map(|res| { - let paras = res.expect("`activate_leaf` timed out").unwrap(); - assert_eq!(paras, vec![PARA_A, PARA_B]); + res.expect("`activate_leaf` timed out").unwrap(); }); let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[leaf_idx..]).await; assert_min_relay_parents_request(&mut ctx_handle, leaf, prospective_response).await; - assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[min_min_idx..]).await; + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[min_min_idx..leaf_idx]) + .await; }; futures::executor::block_on(join(fut, overseer_fut)); @@ -558,6 +722,11 @@ mod tests { allowed_relay_parents.allowed_relay_parents_contiguous, expected_ancestry ); + + assert_eq!(view.known_allowed_relay_parents_under(&leaf, None), Some(&expected_ancestry[..])); + assert_eq!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_A)), Some(&expected_ancestry[..(PARA_A_MIN_PARENT - 1) as usize])); + assert_eq!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_B)), Some(&expected_ancestry[..])); + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_C)).unwrap().is_empty()); } ); @@ -566,18 +735,188 @@ mod tests { let prospective_response = vec![(PARA_C, PARA_C_MIN_PARENT)]; let leaf = CHAIN_A.last().unwrap(); let blocks = [&[GENESIS_HASH], CHAIN_A].concat(); + let leaf_idx = blocks.len() - 1; let fut = view.activate_leaf(ctx.sender(), *leaf).timeout(TIMEOUT).map(|res| { - let paras = res.expect("`activate_leaf` timed out").unwrap(); - assert_eq!(paras, vec![PARA_C]); + res.expect("`activate_leaf` timed out").unwrap(); }); let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks[leaf_idx..]).await; assert_min_relay_parents_request(&mut ctx_handle, leaf, prospective_response).await; - assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks).await; + assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks[..leaf_idx]).await; + }; + futures::executor::block_on(join(fut, overseer_fut)); + + assert_eq!(view.leaves.len(), 2); + + let leaf_info = + view.block_info_storage.get(leaf).expect("block must be present in storage"); + assert_matches!( + leaf_info.maybe_allowed_relay_parents, + Some(ref allowed_relay_parents) => { + assert_eq!(allowed_relay_parents.minimum_relay_parents[&PARA_C], GENESIS_NUMBER); + let expected_ancestry: Vec = + blocks[..].iter().rev().copied().collect(); + assert_eq!( + allowed_relay_parents.allowed_relay_parents_contiguous, + expected_ancestry + ); + + assert_eq!(view.known_allowed_relay_parents_under(&leaf, None), Some(&expected_ancestry[..])); + assert_eq!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_C)), Some(&expected_ancestry[..])); + + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_A)).unwrap().is_empty()); + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_B)).unwrap().is_empty()); + } + ); + } + + #[test] + fn construct_fresh_view_single_para() { + let pool = TaskExecutor::new(); + let (mut ctx, mut ctx_handle) = make_subsystem_context::(pool); + + let mut view = View::new(Some(PARA_A)); + + assert_eq!(view.collating_for, Some(PARA_A)); + + // Chain B. + const PARA_A_MIN_PARENT: u32 = 4; + + let current_session = 2; + + let leaf = CHAIN_B.last().unwrap(); + let leaf_idx = CHAIN_B.len() - 1; + let min_min_idx = (PARA_A_MIN_PARENT - GENESIS_NUMBER - 1) as usize; + + let fut = view.activate_leaf(ctx.sender(), *leaf).timeout(TIMEOUT).map(|res| { + res.expect("`activate_leaf` timed out").unwrap(); + }); + let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[leaf_idx..]).await; + + assert_async_backing_params_request( + &mut ctx_handle, + *leaf, + AsyncBackingParams { + max_candidate_depth: 0, + allowed_ancestry_len: PARA_A_MIN_PARENT, + }, + ) + .await; + + assert_session_index_request(&mut ctx_handle, *leaf, current_session).await; + + assert_ancestors_request( + &mut ctx_handle, + *leaf, + PARA_A_MIN_PARENT, + CHAIN_B[min_min_idx..leaf_idx].iter().copied().rev().collect(), + ) + .await; + + for hash in CHAIN_B[min_min_idx..leaf_idx].into_iter().rev() { + assert_session_index_request(&mut ctx_handle, *hash, current_session).await; + } + + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[min_min_idx..leaf_idx]) + .await; }; futures::executor::block_on(join(fut, overseer_fut)); + for i in min_min_idx..(CHAIN_B.len() - 1) { + // No allowed relay parents constructed for ancestry. + assert!(view.known_allowed_relay_parents_under(&CHAIN_B[i], None).is_none()); + } + + let leaf_info = + view.block_info_storage.get(leaf).expect("block must be present in storage"); + assert_matches!( + leaf_info.maybe_allowed_relay_parents, + Some(ref allowed_relay_parents) => { + assert_eq!(allowed_relay_parents.minimum_relay_parents[&PARA_A], PARA_A_MIN_PARENT); + let expected_ancestry: Vec = + CHAIN_B[min_min_idx..].iter().rev().copied().collect(); + assert_eq!( + allowed_relay_parents.allowed_relay_parents_contiguous, + expected_ancestry + ); + + assert_eq!(view.known_allowed_relay_parents_under(&leaf, None), Some(&expected_ancestry[..])); + assert_eq!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_A)), Some(&expected_ancestry[..])); + + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_B)).unwrap().is_empty()); + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_C)).unwrap().is_empty()); + } + ); + + // Suppose the whole test chain A is allowed up to genesis for para A, but the genesis block + // is in a different session. + let leaf = CHAIN_A.last().unwrap(); + let blocks = [&[GENESIS_HASH], CHAIN_A].concat(); + let leaf_idx = blocks.len() - 1; + + let fut = view.activate_leaf(ctx.sender(), *leaf).timeout(TIMEOUT).map(|res| { + res.expect("`activate_leaf` timed out").unwrap(); + }); + + let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks[leaf_idx..]).await; + + assert_async_backing_params_request( + &mut ctx_handle, + *leaf, + AsyncBackingParams { + max_candidate_depth: 0, + allowed_ancestry_len: blocks.len() as u32, + }, + ) + .await; + + assert_session_index_request(&mut ctx_handle, *leaf, current_session).await; + + assert_ancestors_request( + &mut ctx_handle, + *leaf, + blocks.len() as u32, + blocks[..leaf_idx].iter().rev().copied().collect(), + ) + .await; + + for hash in blocks[1..leaf_idx].into_iter().rev() { + assert_session_index_request(&mut ctx_handle, *hash, current_session).await; + } + + assert_session_index_request(&mut ctx_handle, GENESIS_HASH, 0).await; + + // We won't request for the genesis block + assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks[1..leaf_idx]).await; + }; + + futures::executor::block_on(join(fut, overseer_fut)); + assert_eq!(view.leaves.len(), 2); + + let leaf_info = + view.block_info_storage.get(leaf).expect("block must be present in storage"); + assert_matches!( + leaf_info.maybe_allowed_relay_parents, + Some(ref allowed_relay_parents) => { + assert_eq!(allowed_relay_parents.minimum_relay_parents[&PARA_A], 1); + let expected_ancestry: Vec = + CHAIN_A[..].iter().rev().copied().collect(); + assert_eq!( + allowed_relay_parents.allowed_relay_parents_contiguous, + expected_ancestry + ); + + assert_eq!(view.known_allowed_relay_parents_under(&leaf, None), Some(&expected_ancestry[..])); + assert_eq!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_A)), Some(&expected_ancestry[..])); + + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_B)).unwrap().is_empty()); + assert!(view.known_allowed_relay_parents_under(&leaf, Some(PARA_C)).unwrap().is_empty()); + } + ); } #[test] @@ -595,15 +934,20 @@ mod tests { let prospective_response = vec![(PARA_A, PARA_A_MIN_PARENT)]; let fut = view.activate_leaf(ctx.sender(), leaf_a).timeout(TIMEOUT).map(|res| { - let paras = res.expect("`activate_leaf` timed out").unwrap(); - assert_eq!(paras, vec![PARA_A]); + res.expect("`activate_leaf` timed out").unwrap(); }); let overseer_fut = async { + assert_block_header_requests( + &mut ctx_handle, + CHAIN_B, + &CHAIN_B[(leaf_a_number - 1)..leaf_a_number], + ) + .await; assert_min_relay_parents_request(&mut ctx_handle, &leaf_a, prospective_response).await; assert_block_header_requests( &mut ctx_handle, CHAIN_B, - &CHAIN_B[min_min_idx..leaf_a_number], + &CHAIN_B[min_min_idx..(leaf_a_number - 1)], ) .await; }; @@ -617,15 +961,20 @@ mod tests { let prospective_response = vec![(PARA_B, PARA_B_MIN_PARENT)]; let fut = view.activate_leaf(ctx.sender(), leaf_b).timeout(TIMEOUT).map(|res| { - let paras = res.expect("`activate_leaf` timed out").unwrap(); - assert_eq!(paras, vec![PARA_B]); + res.expect("`activate_leaf` timed out").unwrap(); }); let overseer_fut = async { + assert_block_header_requests( + &mut ctx_handle, + CHAIN_B, + &CHAIN_B[(leaf_b_number - 1)..leaf_b_number], + ) + .await; assert_min_relay_parents_request(&mut ctx_handle, &leaf_b, prospective_response).await; assert_block_header_requests( &mut ctx_handle, CHAIN_B, - &CHAIN_B[leaf_a_number..leaf_b_number], // Note the expected range. + &CHAIN_B[leaf_a_number..(leaf_b_number - 1)], // Note the expected range. ) .await; }; @@ -665,13 +1014,15 @@ mod tests { .timeout(TIMEOUT) .map(|res| res.unwrap().unwrap()); let overseer_fut = async { - assert_min_relay_parents_request(&mut ctx_handle, &leaf_a, prospective_response).await; assert_block_header_requests( &mut ctx_handle, CHAIN_B, - &CHAIN_B[min_a_idx..=leaf_a_idx], + &CHAIN_B[leaf_a_idx..(leaf_a_idx + 1)], ) .await; + assert_min_relay_parents_request(&mut ctx_handle, &leaf_a, prospective_response).await; + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[min_a_idx..leaf_a_idx]) + .await; }; futures::executor::block_on(join(fut, overseer_fut)); @@ -689,8 +1040,11 @@ mod tests { .timeout(TIMEOUT) .map(|res| res.expect("`activate_leaf` timed out").unwrap()); let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &blocks[(blocks.len() - 1)..]) + .await; assert_min_relay_parents_request(&mut ctx_handle, &leaf_b, prospective_response).await; - assert_block_header_requests(&mut ctx_handle, CHAIN_B, blocks).await; + assert_block_header_requests(&mut ctx_handle, CHAIN_B, &blocks[..(blocks.len() - 1)]) + .await; }; futures::executor::block_on(join(fut, overseer_fut)); @@ -721,19 +1075,18 @@ mod tests { let prospective_response = vec![(PARA_A, PARA_A_MIN_PARENT)]; let fut = view.activate_leaf(ctx.sender(), GENESIS_HASH).timeout(TIMEOUT).map(|res| { - let paras = res.expect("`activate_leaf` timed out").unwrap(); - assert_eq!(paras, vec![PARA_A]); + res.expect("`activate_leaf` timed out").unwrap(); }); let overseer_fut = async { + assert_block_header_requests(&mut ctx_handle, &[GENESIS_HASH], &[GENESIS_HASH]).await; assert_min_relay_parents_request(&mut ctx_handle, &GENESIS_HASH, prospective_response) .await; - assert_block_header_requests(&mut ctx_handle, &[GENESIS_HASH], &[GENESIS_HASH]).await; }; futures::executor::block_on(join(fut, overseer_fut)); assert_matches!( view.known_allowed_relay_parents_under(&GENESIS_HASH, None), - Some(hashes) if !hashes.is_empty() + Some(hashes) if hashes == &[GENESIS_HASH] ); } } diff --git a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs index d38d838fedefac643253528ab99d0035eeae55da..b5aef325c8b437ec43c2872f130651de65c28a52 100644 --- a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs +++ b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs @@ -39,8 +39,8 @@ /// /// # Usage /// -/// It's expected that the users of this module will be building up trees of -/// [`Fragment`]s and consistently pruning and adding to the tree. +/// It's expected that the users of this module will be building up chains of +/// [`Fragment`]s and consistently pruning and adding to the chains. /// /// ## Operating Constraints /// @@ -54,60 +54,65 @@ /// make an intelligent prediction about what might be accepted in the future based on /// prior fragments that also exist off-chain. /// -/// ## Fragment Trees +/// ## Fragment Chains +/// +/// For simplicity and practicality, we expect that collators of the same parachain are +/// cooperating and don't create parachain forks or cycles on the same relay chain active leaf. +/// Therefore, higher-level code should maintain one fragment chain for each active leaf (not a +/// fragment tree). If parachains do create forks, their performance in regards to async +/// backing and elastic scaling will suffer, because different validators will have different +/// predictions of the future. /// /// As the relay-chain grows, some predictions come true and others come false. /// And new predictions get made. These three changes correspond distinctly to the -/// 3 primary operations on fragment trees. -/// -/// A fragment tree is a mental model for thinking about a forking series of predictions -/// about a single parachain. There may be one or more fragment trees per parachain. -/// -/// In expectation, most parachains will have a plausibly-unique authorship method which means -/// that they should really be much closer to fragment-chains, maybe with an occasional fork. +/// 3 primary operations on fragment chains. /// -/// Avoiding fragment-tree blowup is beyond the scope of this module. +/// Avoiding fragment-chain blowup is beyond the scope of this module. Higher-level must ensure +/// proper spam protection. /// -/// ### Pruning Fragment Trees +/// ### Pruning Fragment Chains /// /// When the relay-chain advances, we want to compare the new constraints of that relay-parent -/// to the roots of the fragment trees we have. There are 3 cases: +/// to the root of the fragment chain we have. There are 3 cases: /// /// 1. The root fragment is still valid under the new constraints. In this case, we do nothing. -/// This is the "prediction still uncertain" case. +/// This is the "prediction still uncertain" case. (Corresponds to some candidates still +/// being pending availability). /// -/// 2. The root fragment is invalid under the new constraints because it has been subsumed by -/// the relay-chain. In this case, we can discard the root and split & re-root the fragment -/// tree under its descendants and compare to the new constraints again. This is the -/// "prediction came true" case. +/// 2. The root fragment (potentially along with a number of descendants) is invalid under the +/// new constraints because it has been included by the relay-chain. In this case, we can +/// discard the included chain and split & re-root the chain under its descendants and +/// compare to the new constraints again. This is the "prediction came true" case. /// -/// 3. The root fragment is invalid under the new constraints because a competing parachain -/// block has been included or it would never be accepted for some other reason. In this -/// case we can discard the entire fragment tree. This is the "prediction came false" case. +/// 3. The root fragment becomes invalid under the new constraints for any reason (if for +/// example the parachain produced a fork and the block producer picked a different +/// candidate to back). In this case we can discard the entire fragment chain. This is the +/// "prediction came false" case. /// /// This is all a bit of a simplification because it assumes that the relay-chain advances -/// without forks and is finalized instantly. In practice, the set of fragment-trees needs to +/// without forks and is finalized instantly. In practice, the set of fragment-chains needs to /// be observable from the perspective of a few different possible forks of the relay-chain and /// not pruned too eagerly. /// /// Note that the fragments themselves don't need to change and the only thing we care about /// is whether the predictions they represent are still valid. /// -/// ### Extending Fragment Trees +/// ### Extending Fragment Chains /// /// As predictions fade into the past, new ones should be stacked on top. /// /// Every new relay-chain block is an opportunity to make a new prediction about the future. -/// Higher-level logic should select the leaves of the fragment-trees to build upon or whether -/// to create a new fragment-tree. +/// Higher-level logic should decide whether to build upon an existing chain or whether +/// to create a new fragment-chain. /// /// ### Code Upgrades /// /// Code upgrades are the main place where this emulation fails. The on-chain PVF upgrade /// scheduling logic is very path-dependent and intricate so we just assume that code upgrades -/// can't be initiated and applied within a single fragment-tree. Fragment-trees aren't deep, -/// in practice and code upgrades are fairly rare. So what's likely to happen around code -/// upgrades is that the entire fragment-tree has to get discarded at some point. +/// can't be initiated and applied within a single fragment-chain. Fragment-chains aren't deep, +/// in practice (bounded by a linear function of the the number of cores assigned to a +/// parachain) and code upgrades are fairly rare. So what's likely to happen around code +/// upgrades is that the entire fragment-chain has to get discarded at some point. /// /// That means a few blocks of execution time lost, which is not a big deal for code upgrades /// in practice at most once every few weeks. @@ -116,10 +121,7 @@ use polkadot_primitives::{ CollatorId, CollatorSignature, Hash, HeadData, Id as ParaId, PersistedValidationData, UpgradeRestriction, ValidationCodeHash, }; -use std::{ - borrow::{Borrow, Cow}, - collections::HashMap, -}; +use std::{collections::HashMap, sync::Arc}; /// Constraints on inbound HRMP channels. #[derive(Debug, Clone, PartialEq)] @@ -524,9 +526,9 @@ impl ConstraintModifications { /// here. But the erasure-root is not. This means that prospective candidates /// are not correlated to any session in particular. #[derive(Debug, Clone, PartialEq)] -pub struct ProspectiveCandidate<'a> { +pub struct ProspectiveCandidate { /// The commitments to the output of the execution. - pub commitments: Cow<'a, CandidateCommitments>, + pub commitments: CandidateCommitments, /// The collator that created the candidate. pub collator: CollatorId, /// The signature of the collator on the payload. @@ -539,32 +541,6 @@ pub struct ProspectiveCandidate<'a> { pub validation_code_hash: ValidationCodeHash, } -impl<'a> ProspectiveCandidate<'a> { - fn into_owned(self) -> ProspectiveCandidate<'static> { - ProspectiveCandidate { commitments: Cow::Owned(self.commitments.into_owned()), ..self } - } - - /// Partially clone the prospective candidate, but borrow the - /// parts which are potentially heavy. - pub fn partial_clone(&self) -> ProspectiveCandidate { - ProspectiveCandidate { - commitments: Cow::Borrowed(self.commitments.borrow()), - collator: self.collator.clone(), - collator_signature: self.collator_signature.clone(), - persisted_validation_data: self.persisted_validation_data.clone(), - pov_hash: self.pov_hash, - validation_code_hash: self.validation_code_hash, - } - } -} - -#[cfg(test)] -impl ProspectiveCandidate<'static> { - fn commitments_mut(&mut self) -> &mut CandidateCommitments { - self.commitments.to_mut() - } -} - /// Kinds of errors with the validity of a fragment. #[derive(Debug, Clone, PartialEq)] pub enum FragmentValidityError { @@ -618,19 +594,19 @@ pub enum FragmentValidityError { /// This is a type which guarantees that the candidate is valid under the /// operating constraints. #[derive(Debug, Clone, PartialEq)] -pub struct Fragment<'a> { +pub struct Fragment { /// The new relay-parent. relay_parent: RelayChainBlockInfo, /// The constraints this fragment is operating under. operating_constraints: Constraints, /// The core information about the prospective candidate. - candidate: ProspectiveCandidate<'a>, + candidate: Arc, /// Modifications to the constraints based on the outputs of /// the candidate. modifications: ConstraintModifications, } -impl<'a> Fragment<'a> { +impl Fragment { /// Create a new fragment. /// /// This fails if the fragment isn't in line with the operating @@ -642,10 +618,29 @@ impl<'a> Fragment<'a> { pub fn new( relay_parent: RelayChainBlockInfo, operating_constraints: Constraints, - candidate: ProspectiveCandidate<'a>, + candidate: Arc, ) -> Result { + let modifications = Self::check_against_constraints( + &relay_parent, + &operating_constraints, + &candidate.commitments, + &candidate.validation_code_hash, + &candidate.persisted_validation_data, + )?; + + Ok(Fragment { relay_parent, operating_constraints, candidate, modifications }) + } + + /// Check the candidate against the operating constrains and return the constraint modifications + /// made by this candidate. + pub fn check_against_constraints( + relay_parent: &RelayChainBlockInfo, + operating_constraints: &Constraints, + commitments: &CandidateCommitments, + validation_code_hash: &ValidationCodeHash, + persisted_validation_data: &PersistedValidationData, + ) -> Result { let modifications = { - let commitments = &candidate.commitments; ConstraintModifications { required_parent: Some(commitments.head_data.clone()), hrmp_watermark: Some({ @@ -689,11 +684,13 @@ impl<'a> Fragment<'a> { validate_against_constraints( &operating_constraints, &relay_parent, - &candidate, + commitments, + persisted_validation_data, + validation_code_hash, &modifications, )?; - Ok(Fragment { relay_parent, operating_constraints, candidate, modifications }) + Ok(modifications) } /// Access the relay parent information. @@ -707,7 +704,7 @@ impl<'a> Fragment<'a> { } /// Access the underlying prospective candidate. - pub fn candidate(&self) -> &ProspectiveCandidate<'a> { + pub fn candidate(&self) -> &ProspectiveCandidate { &self.candidate } @@ -715,31 +712,14 @@ impl<'a> Fragment<'a> { pub fn constraint_modifications(&self) -> &ConstraintModifications { &self.modifications } - - /// Convert the fragment into an owned variant. - pub fn into_owned(self) -> Fragment<'static> { - Fragment { candidate: self.candidate.into_owned(), ..self } - } - - /// Validate this fragment against some set of constraints - /// instead of the operating constraints. - pub fn validate_against_constraints( - &self, - constraints: &Constraints, - ) -> Result<(), FragmentValidityError> { - validate_against_constraints( - constraints, - &self.relay_parent, - &self.candidate, - &self.modifications, - ) - } } fn validate_against_constraints( constraints: &Constraints, relay_parent: &RelayChainBlockInfo, - candidate: &ProspectiveCandidate, + commitments: &CandidateCommitments, + persisted_validation_data: &PersistedValidationData, + validation_code_hash: &ValidationCodeHash, modifications: &ConstraintModifications, ) -> Result<(), FragmentValidityError> { let expected_pvd = PersistedValidationData { @@ -749,17 +729,17 @@ fn validate_against_constraints( max_pov_size: constraints.max_pov_size as u32, }; - if expected_pvd != candidate.persisted_validation_data { + if expected_pvd != *persisted_validation_data { return Err(FragmentValidityError::PersistedValidationDataMismatch( expected_pvd, - candidate.persisted_validation_data.clone(), + persisted_validation_data.clone(), )) } - if constraints.validation_code_hash != candidate.validation_code_hash { + if constraints.validation_code_hash != *validation_code_hash { return Err(FragmentValidityError::ValidationCodeMismatch( constraints.validation_code_hash, - candidate.validation_code_hash, + *validation_code_hash, )) } @@ -770,7 +750,7 @@ fn validate_against_constraints( )) } - if candidate.commitments.new_validation_code.is_some() { + if commitments.new_validation_code.is_some() { match constraints.upgrade_restriction { None => {}, Some(UpgradeRestriction::Present) => @@ -778,11 +758,8 @@ fn validate_against_constraints( } } - let announced_code_size = candidate - .commitments - .new_validation_code - .as_ref() - .map_or(0, |code| code.0.len()); + let announced_code_size = + commitments.new_validation_code.as_ref().map_or(0, |code| code.0.len()); if announced_code_size > constraints.max_code_size { return Err(FragmentValidityError::CodeSizeTooLarge( @@ -801,17 +778,17 @@ fn validate_against_constraints( } } - if candidate.commitments.horizontal_messages.len() > constraints.max_hrmp_num_per_candidate { + if commitments.horizontal_messages.len() > constraints.max_hrmp_num_per_candidate { return Err(FragmentValidityError::HrmpMessagesPerCandidateOverflow { messages_allowed: constraints.max_hrmp_num_per_candidate, - messages_submitted: candidate.commitments.horizontal_messages.len(), + messages_submitted: commitments.horizontal_messages.len(), }) } - if candidate.commitments.upward_messages.len() > constraints.max_ump_num_per_candidate { + if commitments.upward_messages.len() > constraints.max_ump_num_per_candidate { return Err(FragmentValidityError::UmpMessagesPerCandidateOverflow { messages_allowed: constraints.max_ump_num_per_candidate, - messages_submitted: candidate.commitments.upward_messages.len(), + messages_submitted: commitments.upward_messages.len(), }) } @@ -1184,21 +1161,21 @@ mod tests { fn make_candidate( constraints: &Constraints, relay_parent: &RelayChainBlockInfo, - ) -> ProspectiveCandidate<'static> { + ) -> ProspectiveCandidate { let collator_pair = CollatorPair::generate().0; let collator = collator_pair.public(); let sig = collator_pair.sign(b"blabla".as_slice()); ProspectiveCandidate { - commitments: Cow::Owned(CandidateCommitments { + commitments: CandidateCommitments { upward_messages: Default::default(), horizontal_messages: Default::default(), new_validation_code: None, head_data: HeadData::from(vec![1, 2, 3, 4, 5]), processed_downward_messages: 0, hrmp_watermark: relay_parent.number, - }), + }, collator, collator_signature: sig, persisted_validation_data: PersistedValidationData { @@ -1229,7 +1206,7 @@ mod tests { candidate.validation_code_hash = got_code; assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::ValidationCodeMismatch(expected_code, got_code,)), ) } @@ -1261,7 +1238,7 @@ mod tests { let got_pvd = candidate.persisted_validation_data.clone(); assert_eq!( - Fragment::new(relay_parent_b, constraints, candidate), + Fragment::new(relay_parent_b, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::PersistedValidationDataMismatch(expected_pvd, got_pvd,)), ); } @@ -1278,10 +1255,10 @@ mod tests { let mut candidate = make_candidate(&constraints, &relay_parent); let max_code_size = constraints.max_code_size; - candidate.commitments_mut().new_validation_code = Some(vec![0; max_code_size + 1].into()); + candidate.commitments.new_validation_code = Some(vec![0; max_code_size + 1].into()); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::CodeSizeTooLarge(max_code_size, max_code_size + 1,)), ); } @@ -1298,7 +1275,7 @@ mod tests { let candidate = make_candidate(&constraints, &relay_parent); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::RelayParentTooOld(5, 3,)), ); } @@ -1317,7 +1294,7 @@ mod tests { let max_hrmp = constraints.max_hrmp_num_per_candidate; candidate - .commitments_mut() + .commitments .horizontal_messages .try_extend((0..max_hrmp + 1).map(|i| OutboundHrmpMessage { recipient: ParaId::from(i as u32), @@ -1326,7 +1303,7 @@ mod tests { .unwrap(); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::HrmpMessagesPerCandidateOverflow { messages_allowed: max_hrmp, messages_submitted: max_hrmp + 1, @@ -1346,22 +1323,36 @@ mod tests { let mut candidate = make_candidate(&constraints, &relay_parent); // Empty dmp queue is ok. - assert!(Fragment::new(relay_parent.clone(), constraints.clone(), candidate.clone()).is_ok()); + assert!(Fragment::new( + relay_parent.clone(), + constraints.clone(), + Arc::new(candidate.clone()) + ) + .is_ok()); // Unprocessed message that was sent later is ok. constraints.dmp_remaining_messages = vec![relay_parent.number + 1]; - assert!(Fragment::new(relay_parent.clone(), constraints.clone(), candidate.clone()).is_ok()); + assert!(Fragment::new( + relay_parent.clone(), + constraints.clone(), + Arc::new(candidate.clone()) + ) + .is_ok()); for block_number in 0..=relay_parent.number { constraints.dmp_remaining_messages = vec![block_number]; assert_eq!( - Fragment::new(relay_parent.clone(), constraints.clone(), candidate.clone()), + Fragment::new( + relay_parent.clone(), + constraints.clone(), + Arc::new(candidate.clone()) + ), Err(FragmentValidityError::DmpAdvancementRule), ); } - candidate.commitments.to_mut().processed_downward_messages = 1; - assert!(Fragment::new(relay_parent, constraints, candidate).is_ok()); + candidate.commitments.processed_downward_messages = 1; + assert!(Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())).is_ok()); } #[test] @@ -1379,13 +1370,12 @@ mod tests { candidate .commitments - .to_mut() .upward_messages .try_extend((0..max_ump + 1).map(|i| vec![i as u8])) .unwrap(); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::UmpMessagesPerCandidateOverflow { messages_allowed: max_ump, messages_submitted: max_ump + 1, @@ -1405,10 +1395,10 @@ mod tests { let mut candidate = make_candidate(&constraints, &relay_parent); constraints.upgrade_restriction = Some(UpgradeRestriction::Present); - candidate.commitments_mut().new_validation_code = Some(ValidationCode(vec![1, 2, 3])); + candidate.commitments.new_validation_code = Some(ValidationCode(vec![1, 2, 3])); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::CodeUpgradeRestricted), ); } @@ -1424,23 +1414,23 @@ mod tests { let constraints = make_constraints(); let mut candidate = make_candidate(&constraints, &relay_parent); - candidate.commitments_mut().horizontal_messages = HorizontalMessages::truncate_from(vec![ + candidate.commitments.horizontal_messages = HorizontalMessages::truncate_from(vec![ OutboundHrmpMessage { recipient: ParaId::from(0 as u32), data: vec![1, 2, 3] }, OutboundHrmpMessage { recipient: ParaId::from(0 as u32), data: vec![4, 5, 6] }, ]); assert_eq!( - Fragment::new(relay_parent.clone(), constraints.clone(), candidate.clone()), + Fragment::new(relay_parent.clone(), constraints.clone(), Arc::new(candidate.clone())), Err(FragmentValidityError::HrmpMessagesDescendingOrDuplicate(1)), ); - candidate.commitments_mut().horizontal_messages = HorizontalMessages::truncate_from(vec![ + candidate.commitments.horizontal_messages = HorizontalMessages::truncate_from(vec![ OutboundHrmpMessage { recipient: ParaId::from(1 as u32), data: vec![1, 2, 3] }, OutboundHrmpMessage { recipient: ParaId::from(0 as u32), data: vec![4, 5, 6] }, ]); assert_eq!( - Fragment::new(relay_parent, constraints, candidate), + Fragment::new(relay_parent, constraints, Arc::new(candidate.clone())), Err(FragmentValidityError::HrmpMessagesDescendingOrDuplicate(1)), ); } diff --git a/polkadot/node/subsystem-util/src/lib.rs b/polkadot/node/subsystem-util/src/lib.rs index b93818070a183e43e71f327bcc1770a71fae1cb6..d371b699b9eb9eda4c59b68ad695514fe0ea80d3 100644 --- a/polkadot/node/subsystem-util/src/lib.rs +++ b/polkadot/node/subsystem-util/src/lib.rs @@ -25,17 +25,15 @@ #![warn(missing_docs)] +pub use overseer::{ + gen::{OrchestraError as OverseerError, Timeout}, + Subsystem, TimeoutExt, +}; use polkadot_node_subsystem::{ errors::{RuntimeApiError, SubsystemError}, messages::{RuntimeApiMessage, RuntimeApiRequest, RuntimeApiSender}, overseer, SubsystemSender, }; -use polkadot_primitives::{async_backing::BackingState, slashing, CoreIndex, ExecutorParams}; - -pub use overseer::{ - gen::{OrchestraError as OverseerError, Timeout}, - Subsystem, TimeoutExt, -}; pub use polkadot_node_metrics::{metrics, Metronome}; @@ -43,11 +41,12 @@ use futures::channel::{mpsc, oneshot}; use parity_scale_codec::Encode; use polkadot_primitives::{ - AsyncBackingParams, AuthorityDiscoveryId, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, EncodeAs, GroupIndex, GroupRotationInfo, Hash, - Id as ParaId, OccupiedCoreAssumption, PersistedValidationData, ScrapedOnChainVotes, - SessionIndex, SessionInfo, Signed, SigningContext, ValidationCode, ValidationCodeHash, - ValidatorId, ValidatorIndex, ValidatorSignature, + async_backing::BackingState, slashing, AsyncBackingParams, AuthorityDiscoveryId, + CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex, CoreState, EncodeAs, + ExecutorParams, GroupIndex, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, + PersistedValidationData, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, + SigningContext, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }; pub use rand; use sp_application_crypto::AppCrypto; @@ -60,17 +59,18 @@ use std::{ use thiserror::Error; use vstaging::get_disabled_validators_with_fallback; +pub use determine_new_blocks::determine_new_blocks; pub use metered; pub use polkadot_node_network_protocol::MIN_GOSSIP_PEERS; -pub use determine_new_blocks::determine_new_blocks; - /// These reexports are required so that external crates can use the `delegated_subsystem` macro /// properly. pub mod reexports { pub use polkadot_overseer::gen::{SpawnedSubsystem, Spawner, Subsystem, SubsystemContext}; } +/// Helpers for the validator->chunk index mapping. +pub mod availability_chunks; /// A utility for managing the implicit view of the relay-chain derived from active /// leaves and the minimum allowed relay-parents that parachain candidates can have /// and be backed in those leaves' children. diff --git a/polkadot/node/subsystem-util/src/runtime/error.rs b/polkadot/node/subsystem-util/src/runtime/error.rs index 8751693b078a6797584ed59a2ebd3c320d87cd78..1111b119e95f5926321f7a09de6af02bcbc4acba 100644 --- a/polkadot/node/subsystem-util/src/runtime/error.rs +++ b/polkadot/node/subsystem-util/src/runtime/error.rs @@ -28,7 +28,7 @@ pub enum Error { /// Runtime API subsystem is down, which means we're shutting down. #[fatal] #[error("Runtime request got canceled")] - RuntimeRequestCanceled(oneshot::Canceled), + RuntimeRequestCanceled(#[from] oneshot::Canceled), /// Some request to the runtime failed. /// For example if we prune a block we're requesting info about. diff --git a/polkadot/node/subsystem-util/src/runtime/mod.rs b/polkadot/node/subsystem-util/src/runtime/mod.rs index 714384b32e37bcbd6ba7f077252fa23f50eac490..214c58a8e88f76b66d1d6477a3593bd2e32f3e1f 100644 --- a/polkadot/node/subsystem-util/src/runtime/mod.rs +++ b/polkadot/node/subsystem-util/src/runtime/mod.rs @@ -31,8 +31,8 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_types::UnpinHandle; use polkadot_primitives::{ node_features::FeatureIndex, slashing, AsyncBackingParams, CandidateEvent, CandidateHash, - CoreState, EncodeAs, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, IndexedVec, - NodeFeatures, OccupiedCore, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, + CoreIndex, CoreState, EncodeAs, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, + IndexedVec, NodeFeatures, OccupiedCore, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, SigningContext, UncheckedSigned, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, LEGACY_MIN_BACKING_VOTES, }; @@ -348,7 +348,7 @@ where pub async fn get_occupied_cores( sender: &mut Sender, relay_parent: Hash, -) -> Result> +) -> Result> where Sender: overseer::SubsystemSender, { @@ -356,9 +356,10 @@ where Ok(cores .into_iter() - .filter_map(|core_state| { + .enumerate() + .filter_map(|(core_index, core_state)| { if let CoreState::Occupied(occupied) = core_state { - Some(occupied) + Some((CoreIndex(core_index as u32), occupied)) } else { None } diff --git a/polkadot/node/test/client/Cargo.toml b/polkadot/node/test/client/Cargo.toml index 7db00404eb8eca049a6194d19e5e92e66325628c..55d4d81d1c21bbb5007962ac71c8d38fe898d49b 100644 --- a/polkadot/node/test/client/Cargo.toml +++ b/polkadot/node/test/client/Cargo.toml @@ -10,7 +10,7 @@ license.workspace = true workspace = true [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } # Polkadot dependencies polkadot-test-runtime = { path = "../../../runtime/test-runtime" } diff --git a/polkadot/node/test/service/src/chain_spec.rs b/polkadot/node/test/service/src/chain_spec.rs index f14fa9fde58b4426690cd1bd0e16129f095c34ec..e6a1229caf866d7572b32e04139e42a0e83918a4 100644 --- a/polkadot/node/test/service/src/chain_spec.rs +++ b/polkadot/node/test/service/src/chain_spec.rs @@ -33,7 +33,7 @@ use test_runtime_constants::currency::DOTS; const DEFAULT_PROTOCOL_ID: &str = "dot"; /// The `ChainSpec` parameterized for polkadot test runtime. -pub type PolkadotChainSpec = sc_service::GenericChainSpec<(), Extensions>; +pub type PolkadotChainSpec = sc_service::GenericChainSpec; /// Returns the properties for the [`PolkadotChainSpec`]. pub fn polkadot_chain_spec_properties() -> serde_json::map::Map { diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index 87fbc7c20f318c6a791276f7fb509e8c33c4f909..35156a3a9372b54cf438fe086d3642b8fd55992d 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -216,6 +216,8 @@ pub fn node_config( rpc_message_buffer_capacity: Default::default(), rpc_batch_config: RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/polkadot/node/zombienet-backchannel/Cargo.toml b/polkadot/node/zombienet-backchannel/Cargo.toml index fa99490a997434eedee977121f13d8dcc1a9b5a1..a0233bb46e5128b1b036a6fa7dd0181e587f1e9a 100644 --- a/polkadot/node/zombienet-backchannel/Cargo.toml +++ b/polkadot/node/zombienet-backchannel/Cargo.toml @@ -14,10 +14,10 @@ workspace = true [dependencies] tokio = { version = "1.24.2", default-features = false, features = ["macros", "net", "rt-multi-thread", "sync"] } url = "2.3.1" -tokio-tungstenite = "0.17" +tokio-tungstenite = "0.20.1" futures-util = "0.3.30" lazy_static = "1.4.0" -parity-scale-codec = { version = "3.6.1", features = ["derive"] } +parity-scale-codec = { version = "3.6.12", features = ["derive"] } reqwest = { version = "0.11", features = ["rustls-tls"], default-features = false } thiserror = { workspace = true } gum = { package = "tracing-gum", path = "../gum" } diff --git a/polkadot/parachain/Cargo.toml b/polkadot/parachain/Cargo.toml index 15eea2addc893ced551edaf2557ff703a455a879..1344baac64b65246945b3bd09569cf21990fde5e 100644 --- a/polkadot/parachain/Cargo.toml +++ b/polkadot/parachain/Cargo.toml @@ -13,7 +13,7 @@ workspace = true # note: special care is taken to avoid inclusion of `sp-io` externals when compiling # this crate for WASM. This is critical to avoid forcing all parachain WASM into implementing # various unnecessary Substrate-specific endpoints. -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } sp-std = { path = "../../substrate/primitives/std", default-features = false } sp-runtime = { path = "../../substrate/primitives/runtime", default-features = false, features = ["serde"] } diff --git a/polkadot/parachain/src/primitives.rs b/polkadot/parachain/src/primitives.rs index 5a1efdf898217a18972cab8c9ea49a41e5a2280f..2764384363727a8b7b350b02441903204eae717f 100644 --- a/polkadot/parachain/src/primitives.rs +++ b/polkadot/parachain/src/primitives.rs @@ -333,7 +333,19 @@ impl DmpMessageHandler for () { } /// The aggregate XCMP message format. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, RuntimeDebug)] +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + TypeInfo, + RuntimeDebug, + MaxEncodedLen, +)] pub enum XcmpMessageFormat { /// Encoded `VersionedXcm` messages, all concatenated. ConcatenatedVersionedXcm, diff --git a/polkadot/parachain/test-parachains/Cargo.toml b/polkadot/parachain/test-parachains/Cargo.toml index 6acdedf67ff2e4be34da2caa70c572a41f861eca..22f3d2942e0c2076cae4e9e37a6d960b42969860 100644 --- a/polkadot/parachain/test-parachains/Cargo.toml +++ b/polkadot/parachain/test-parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] tiny-keccak = { version = "2.0.2", features = ["keccak"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } adder = { package = "test-parachain-adder", path = "adder" } halt = { package = "test-parachain-halt", path = "halt" } diff --git a/polkadot/parachain/test-parachains/adder/Cargo.toml b/polkadot/parachain/test-parachains/adder/Cargo.toml index eec19ef788aad510d7ea9ef6d2ab61d7c6aeb8f9..273fa93a50f412ffc282aeeafb07c0e173fd5e72 100644 --- a/polkadot/parachain/test-parachains/adder/Cargo.toml +++ b/polkadot/parachain/test-parachains/adder/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] parachain = { package = "polkadot-parachain-primitives", path = "../..", default-features = false, features = ["wasm-api"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sp-std = { path = "../../../../substrate/primitives/std", default-features = false } tiny-keccak = { version = "2.0.2", features = ["keccak"] } dlmalloc = { version = "0.2.4", features = ["global"] } diff --git a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml index 5a2b5405741446f52e5f1212de2665ab04d350d2..dbc8507d599bb5e7899a8ee99450e95e4c480618 100644 --- a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml @@ -15,7 +15,7 @@ name = "adder-collator" path = "src/main.rs" [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.30" futures-timer = "3.0.2" diff --git a/polkadot/parachain/test-parachains/undying/Cargo.toml b/polkadot/parachain/test-parachains/undying/Cargo.toml index 82ceebcf4eee99f36140908580b41c13b04ea87e..f2067a2c3b9bdc3c7e585fbb03fc79ee435f7d1d 100644 --- a/polkadot/parachain/test-parachains/undying/Cargo.toml +++ b/polkadot/parachain/test-parachains/undying/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] parachain = { package = "polkadot-parachain-primitives", path = "../..", default-features = false, features = ["wasm-api"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sp-std = { path = "../../../../substrate/primitives/std", default-features = false } tiny-keccak = { version = "2.0.2", features = ["keccak"] } dlmalloc = { version = "0.2.4", features = ["global"] } diff --git a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml index cacf7304f90a29d39848b80a58159afbbb6cb3e5..28efdbbf242f7879615928bb228a4975b54c2d0c 100644 --- a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml @@ -15,7 +15,7 @@ name = "undying-collator" path = "src/main.rs" [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.30" futures-timer = "3.0.2" diff --git a/polkadot/primitives/Cargo.toml b/polkadot/primitives/Cargo.toml index 99800afc37fe0133b78dd6f1b7432014b923c0ca..603d08b8fee524f803b32c751cdd818249687132 100644 --- a/polkadot/primitives/Cargo.toml +++ b/polkadot/primitives/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc", "serde"] } hex-literal = "0.4.1" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive", "serde"] } log = { workspace = true, default-features = false } serde = { features = ["alloc", "derive"], workspace = true } diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index 01f393086a668f43d2e18abc10b4491f54aae2cf..061794ca06d1be1883fd3605eb5bc691e5b7b23b 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -41,26 +41,26 @@ pub use v7::{ ApprovalVotingParams, AssignmentId, AsyncBackingParams, AuthorityDiscoveryId, AvailabilityBitfield, BackedCandidate, Balance, BlakeTwo256, Block, BlockId, BlockNumber, CandidateCommitments, CandidateDescriptor, CandidateEvent, CandidateHash, CandidateIndex, - CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, CollatorId, - CollatorSignature, CommittedCandidateReceipt, CompactStatement, ConsensusLog, CoreIndex, - CoreState, DisputeState, DisputeStatement, DisputeStatementSet, DownwardMessage, EncodeAs, - ExecutorParam, ExecutorParamError, ExecutorParams, ExecutorParamsHash, ExecutorParamsPrepHash, - ExplicitDisputeStatement, GroupIndex, GroupRotationInfo, Hash, HashT, HeadData, Header, - HorizontalMessages, HrmpChannelId, Id, InboundDownwardMessage, InboundHrmpMessage, IndexedVec, - InherentData, InvalidDisputeStatementKind, Moment, MultiDisputeStatementSet, NodeFeatures, - Nonce, OccupiedCore, OccupiedCoreAssumption, OutboundHrmpMessage, ParathreadClaim, - ParathreadEntry, PersistedValidationData, PvfCheckStatement, PvfExecKind, PvfPrepKind, - RuntimeMetricLabel, RuntimeMetricLabelValue, RuntimeMetricLabelValues, RuntimeMetricLabels, - RuntimeMetricOp, RuntimeMetricUpdate, ScheduledCore, ScrapedOnChainVotes, SessionIndex, - SessionInfo, Signature, Signed, SignedAvailabilityBitfield, SignedAvailabilityBitfields, - SignedStatement, SigningContext, Slot, UncheckedSigned, UncheckedSignedAvailabilityBitfield, - UncheckedSignedAvailabilityBitfields, UncheckedSignedStatement, UpgradeGoAhead, - UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, - ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation, - ValidityError, ASSIGNMENT_KEY_TYPE_ID, LEGACY_MIN_BACKING_VOTES, LOWEST_PUBLIC_ID, - MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, MIN_CODE_SIZE, - ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE, PARACHAINS_INHERENT_IDENTIFIER, - PARACHAIN_KEY_TYPE_ID, + CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, ChunkIndex, + CollatorId, CollatorSignature, CommittedCandidateReceipt, CompactStatement, ConsensusLog, + CoreIndex, CoreState, DisputeState, DisputeStatement, DisputeStatementSet, DownwardMessage, + EncodeAs, ExecutorParam, ExecutorParamError, ExecutorParams, ExecutorParamsHash, + ExecutorParamsPrepHash, ExplicitDisputeStatement, GroupIndex, GroupRotationInfo, Hash, HashT, + HeadData, Header, HorizontalMessages, HrmpChannelId, Id, InboundDownwardMessage, + InboundHrmpMessage, IndexedVec, InherentData, InvalidDisputeStatementKind, Moment, + MultiDisputeStatementSet, NodeFeatures, Nonce, OccupiedCore, OccupiedCoreAssumption, + OutboundHrmpMessage, ParathreadClaim, ParathreadEntry, PersistedValidationData, + PvfCheckStatement, PvfExecKind, PvfPrepKind, RuntimeMetricLabel, RuntimeMetricLabelValue, + RuntimeMetricLabelValues, RuntimeMetricLabels, RuntimeMetricOp, RuntimeMetricUpdate, + ScheduledCore, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signature, Signed, + SignedAvailabilityBitfield, SignedAvailabilityBitfields, SignedStatement, SigningContext, Slot, + UncheckedSigned, UncheckedSignedAvailabilityBitfield, UncheckedSignedAvailabilityBitfields, + UncheckedSignedStatement, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, + ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, ValidityAttestation, ValidityError, ASSIGNMENT_KEY_TYPE_ID, + LEGACY_MIN_BACKING_VOTES, LOWEST_PUBLIC_ID, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, + MIN_CODE_SIZE, ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE, + PARACHAINS_INHERENT_IDENTIFIER, PARACHAIN_KEY_TYPE_ID, }; #[cfg(feature = "std")] diff --git a/polkadot/primitives/src/v7/mod.rs b/polkadot/primitives/src/v7/mod.rs index 8a059408496c0f87e2d1394beb84263f48c4fbda..fb8406aece690f25626ed2dd3be5c26aeaa62b7e 100644 --- a/polkadot/primitives/src/v7/mod.rs +++ b/polkadot/primitives/src/v7/mod.rs @@ -117,6 +117,34 @@ pub trait TypeIndex { #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] pub struct ValidatorIndex(pub u32); +/// Index of an availability chunk. +/// +/// The underlying type is identical to `ValidatorIndex`, because +/// the number of chunks will always be equal to the number of validators. +/// However, the chunk index held by a validator may not always be equal to its `ValidatorIndex`, so +/// we use a separate type to make code easier to read. +#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] +pub struct ChunkIndex(pub u32); + +impl From for ValidatorIndex { + fn from(c_index: ChunkIndex) -> Self { + ValidatorIndex(c_index.0) + } +} + +impl From for ChunkIndex { + fn from(v_index: ValidatorIndex) -> Self { + ChunkIndex(v_index.0) + } +} + +impl From for ChunkIndex { + fn from(n: u32) -> Self { + ChunkIndex(n) + } +} + // We should really get https://github.com/paritytech/polkadot/issues/2403 going .. impl From for ValidatorIndex { fn from(n: u32) -> Self { @@ -1787,6 +1815,14 @@ where self.0.get(index.type_index()) } + /// Returns a mutable reference to an element indexed using `K`. + pub fn get_mut(&mut self, index: K) -> Option<&mut V> + where + K: TypeIndex, + { + self.0.get_mut(index.type_index()) + } + /// Returns number of elements in vector. pub fn len(&self) -> usize { self.0.len() @@ -1989,6 +2025,7 @@ pub mod node_features { /// A feature index used to identify a bit into the node_features array stored /// in the HostConfiguration. #[repr(u8)] + #[derive(Clone, Copy)] pub enum FeatureIndex { /// Tells if tranch0 assignments could be sent in a single certificate. /// Reserved for: `` @@ -1997,10 +2034,16 @@ pub mod node_features { /// The value stored there represents the assumed core index where the candidates /// are backed. This is needed for the elastic scaling MVP. ElasticScalingMVP = 1, + /// Tells if the chunk mapping feature is enabled. + /// Enables the implementation of + /// [RFC-47](https://github.com/polkadot-fellows/RFCs/blob/main/text/0047-assignment-of-availability-chunks.md). + /// Must not be enabled unless all validators and collators have stopped using `req_chunk` + /// protocol version 1. If it is enabled, validators can start systematic chunk recovery. + AvailabilityChunkMapping = 2, /// First unassigned feature bit. /// Every time a new feature flag is assigned it should take this value. /// and this should be incremented. - FirstUnassigned = 2, + FirstUnassigned = 3, } } diff --git a/polkadot/roadmap/implementers-guide/src/SUMMARY.md b/polkadot/roadmap/implementers-guide/src/SUMMARY.md index bb19390c7af4d422dfe62252a7153392c8ef534d..41485e5df8ec1f75bc04a54c5c21ef87a5ef4bb6 100644 --- a/polkadot/roadmap/implementers-guide/src/SUMMARY.md +++ b/polkadot/roadmap/implementers-guide/src/SUMMARY.md @@ -8,6 +8,7 @@ - [Disputes Process](protocol-disputes.md) - [Dispute Flow](disputes-flow.md) - [Chain Selection and Finalization](protocol-chain-selection.md) + - [Validator Disabling](protocol-validator-disabling.md) - [Architecture Overview](architecture.md) - [Messaging Overview](messaging.md) - [PVF Pre-checking](pvf-prechecking.md) diff --git a/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md b/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md index 345b3d2e6970403f3096272cc51f903e0566a22e..9b4082c49e2f003f0b7d0fd317bc2e8ce06580e4 100644 --- a/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md +++ b/polkadot/roadmap/implementers-guide/src/node/approval/approval-voting.md @@ -396,7 +396,7 @@ On receiving an `ApprovedAncestor(Hash, BlockNumber, response_channel)`: * Requires `(SessionIndex, SessionInfo, CandidateReceipt, ValidatorIndex, backing_group, block_hash, candidate_index)` * Extract the public key of the `ValidatorIndex` from the `SessionInfo` for the session. * Issue an `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session_index, Some(backing_group), - response_sender)` +Some(core_index), response_sender)` * Load the historical validation code of the parachain by dispatching a `RuntimeApiRequest::ValidationCodeByHash(descriptor.validation_code_hash)` against the state of `block_hash`. * Spawn a background task with a clone of `background_tx` diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md index c57c4589244e79f6cd54a87f823abc466ed8eb43..5b756080becc05b4804138e64baeac3bfdaf97b8 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md @@ -1,84 +1,108 @@ # Availability Recovery -This subsystem is the inverse of the [Availability Distribution](availability-distribution.md) subsystem: validators -will serve the availability chunks kept in the availability store to nodes who connect to them. And the subsystem will -also implement the other side: the logic for nodes to connect to validators, request availability pieces, and -reconstruct the `AvailableData`. +This subsystem is responsible for recovering the data made available via the +[Availability Distribution](availability-distribution.md) subsystem, neccessary for candidate validation during the +approval/disputes processes. Additionally, it is also being used by collators to recover PoVs in adversarial scenarios +where the other collators of the para are censoring blocks. -This version of the availability recovery subsystem is based off of direct connections to validators. In order to -recover any given `AvailableData`, we must recover at least `f + 1` pieces from validators of the session. Thus, we will -connect to and query randomly chosen validators until we have received `f + 1` pieces. +According to the Polkadot protocol, in order to recover any given `AvailableData`, we generally must recover at least +`f + 1` pieces from validators of the session. Thus, we should connect to and query randomly chosen validators until we +have received `f + 1` pieces. + +In practice, there are various optimisations implemented in this subsystem which avoid querying all chunks from +different validators and/or avoid doing the chunk reconstruction altogether. ## Protocol -`PeerSet`: `Validation` +This version of the availability recovery subsystem is based only on request-response network protocols. Input: -* `NetworkBridgeUpdate(update)` -* `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session, backing_group, response)` +* `AvailabilityRecoveryMessage::RecoverAvailableData(candidate, session, backing_group, core_index, response)` Output: -* `NetworkBridge::SendValidationMessage` -* `NetworkBridge::ReportPeer` -* `AvailabilityStore::QueryChunk` +* `NetworkBridgeMessage::SendRequests` +* `AvailabilityStoreMessage::QueryAllChunks` +* `AvailabilityStoreMessage::QueryAvailableData` +* `AvailabilityStoreMessage::QueryChunkSize` + ## Functionality -We hold a state which tracks the currently ongoing recovery tasks, as well as which request IDs correspond to which -task. A recovery task is a structure encapsulating all recovery tasks with the network necessary to recover the -available data in respect to one candidate. +We hold a state which tracks the currently ongoing recovery tasks. A `RecoveryTask` is a structure encapsulating all +network tasks needed in order to recover the available data in respect to a candidate. + +Each `RecoveryTask` has a collection of ordered recovery strategies to try. ```rust +/// Subsystem state. struct State { - /// Each recovery is implemented as an independent async task, and the handles only supply information about the result. - ongoing_recoveries: FuturesUnordered, - /// A recent block hash for which state should be available. - live_block_hash: Hash, - // An LRU cache of recently recovered data. - availability_lru: LruMap>, + /// Each recovery task is implemented as its own async task, + /// and these handles are for communicating with them. + ongoing_recoveries: FuturesUnordered, + /// A recent block hash for which state should be available. + live_block: (BlockNumber, Hash), + /// An LRU cache of recently recovered data. + availability_lru: LruMap, + /// Cached runtime info. + runtime_info: RuntimeInfo, } -/// This is a future, which concludes either when a response is received from the recovery tasks, -/// or all the `awaiting` channels have closed. -struct RecoveryHandle { - candidate_hash: CandidateHash, - interaction_response: RemoteHandle, - awaiting: Vec>>, -} - -struct Unavailable; -struct Concluded(CandidateHash, Result); - -struct RecoveryTaskParams { - validator_authority_keys: Vec, - validators: Vec, - // The number of pieces needed. - threshold: usize, - candidate_hash: Hash, - erasure_root: Hash, +struct RecoveryParams { + /// Discovery ids of `validators`. + pub validator_authority_keys: Vec, + /// Number of validators. + pub n_validators: usize, + /// The number of regular chunks needed. + pub threshold: usize, + /// The number of systematic chunks needed. + pub systematic_threshold: usize, + /// A hash of the relevant candidate. + pub candidate_hash: CandidateHash, + /// The root of the erasure encoding of the candidate. + pub erasure_root: Hash, + /// Metrics to report. + pub metrics: Metrics, + /// Do not request data from availability-store. Useful for collators. + pub bypass_availability_store: bool, + /// The type of check to perform after available data was recovered. + pub post_recovery_check: PostRecoveryCheck, + /// The blake2-256 hash of the PoV. + pub pov_hash: Hash, + /// Protocol name for ChunkFetchingV1. + pub req_v1_protocol_name: ProtocolName, + /// Protocol name for ChunkFetchingV2. + pub req_v2_protocol_name: ProtocolName, + /// Whether or not chunk mapping is enabled. + pub chunk_mapping_enabled: bool, + /// Channel to the erasure task handler. + pub erasure_task_tx: mpsc::Sender, } -enum RecoveryTask { - RequestFromBackers { - // a random shuffling of the validators from the backing group which indicates the order - // in which we connect to them and request the chunk. - shuffled_backers: Vec, - } - RequestChunksFromValidators { - // a random shuffling of the validators which indicates the order in which we connect to the validators and - // request the chunk from them. - shuffling: Vec, - received_chunks: Map, - requesting_chunks: FuturesUnordered>, - } +pub struct RecoveryTask { + sender: Sender, + params: RecoveryParams, + strategies: VecDeque>>, + state: task::State, } -struct RecoveryTask { - to_subsystems: SubsystemSender, - params: RecoveryTaskParams, - source: Source, +#[async_trait::async_trait] +/// Common trait for runnable recovery strategies. +pub trait RecoveryStrategy: Send { + /// Main entry point of the strategy. + async fn run( + mut self: Box, + state: &mut task::State, + sender: &mut Sender, + common_params: &RecoveryParams, + ) -> Result; + + /// Return the name of the strategy for logging purposes. + fn display_name(&self) -> &'static str; + + /// Return the strategy type for use as a metric label. + fn strategy_type(&self) -> &'static str; } ``` @@ -90,68 +114,71 @@ Ignore `BlockFinalized` signals. On `Conclude`, shut down the subsystem. -#### `AvailabilityRecoveryMessage::RecoverAvailableData(receipt, session, Option, response)` +#### `AvailabilityRecoveryMessage::RecoverAvailableData(...)` -1. Check the `availability_lru` for the candidate and return the data if so. -1. Check if there is already an recovery handle for the request. If so, add the response handle to it. +1. Check the `availability_lru` for the candidate and return the data if present. +1. Check if there is already a recovery handle for the request. If so, add the response handle to it. 1. Otherwise, load the session info for the given session under the state of `live_block_hash`, and initiate a recovery - task with *`launch_recovery_task`*. Add a recovery handle to the state and add the response channel to it. + task with `launch_recovery_task`. Add a recovery handle to the state and add the response channel to it. 1. If the session info is not available, return `RecoveryError::Unavailable` on the response channel. ### Recovery logic -#### `launch_recovery_task(session_index, session_info, candidate_receipt, candidate_hash, Option)` +#### `handle_recover(...) -> Result<()>` -1. Compute the threshold from the session info. It should be `f + 1`, where `n = 3f + k`, where `k in {1, 2, 3}`, and - `n` is the number of validators. -1. Set the various fields of `RecoveryParams` based on the validator lists in `session_info` and information about the - candidate. -1. If the `backing_group_index` is `Some`, start in the `RequestFromBackers` phase with a shuffling of the backing group - validator indices and a `None` requesting value. -1. Otherwise, start in the `RequestChunksFromValidators` source with `received_chunks`,`requesting_chunks`, and - `next_shuffling` all empty. -1. Set the `to_subsystems` sender to be equal to a clone of the `SubsystemContext`'s sender. -1. Initialize `received_chunks` to an empty set, as well as `requesting_chunks`. +Instantiate the appropriate `RecoveryStrategy`es, based on the subsystem configuration, params and session info. +Call `launch_recovery_task()`. -Launch the source as a background task running `run(recovery_task)`. +#### `launch_recovery_task(state, ctx, response_sender, recovery_strategies, params) -> Result<()>` -#### `run(recovery_task) -> Result` +Create the `RecoveryTask` and launch it as a background task running `recovery_task.run()`. -```rust -// How many parallel requests to have going at once. -const N_PARALLEL: usize = 50; -``` +#### `recovery_task.run(mut self) -> Result` + +* Loop: + * Pop a strategy from the queue. If none are left, return `RecoveryError::Unavailable`. + * Run the strategy. + * If the strategy returned successfully or returned `RecoveryError::Invalid`, break the loop. + +### Recovery strategies + +#### `FetchFull` + +This strategy tries requesting the full available data from the validators in the backing group to +which the node is already connected. They are tried one by one in a random order. +It is very performant if there's enough network bandwidth and the backing group is not overloaded. +The costly reed-solomon reconstruction is not needed. + +#### `FetchSystematicChunks` + +Very similar to `FetchChunks` below but requests from the validators that hold the systematic chunks, so that we avoid +reed-solomon reconstruction. Only possible if `node_features::FeatureIndex::AvailabilityChunkMapping` is enabled and +the `core_index` is supplied (currently only for recoveries triggered by approval voting). + +More info in +[RFC-47](https://github.com/polkadot-fellows/RFCs/blob/main/text/0047-assignment-of-availability-chunks.md). + +#### `FetchChunks` + +The least performant strategy but also the most comprehensive one. It's the only one that cannot fail under the +byzantine threshold assumption, so it's always added as the last one in the `recovery_strategies` queue. + +Performs parallel chunk requests to validators. When enough chunks were received, do the reconstruction. +In the worst case, all validators will be tried. + +### Default recovery strategy configuration + +#### For validators + +If the estimated available data size is smaller than a configured constant (currently 1Mib for Polkadot or 4Mib for +other networks), try doing `FetchFull` first. +Next, if the preconditions described in `FetchSystematicChunks` above are met, try systematic recovery. +As a last resort, do `FetchChunks`. + +#### For collators + +Collators currently only use `FetchChunks`, as they only attempt recoveries in rare scenarios. -* Request `AvailabilityStoreMessage::QueryAvailableData`. If it exists, return that. -* If the task contains `RequestFromBackers` - * Loop: - * If the `requesting_pov` is `Some`, poll for updates on it. If it concludes, set `requesting_pov` to `None`. - * If the `requesting_pov` is `None`, take the next backer off the `shuffled_backers`. - * If the backer is `Some`, issue a `NetworkBridgeMessage::Requests` with a network request for the - `AvailableData` and wait for the response. - * If it concludes with a `None` result, return to beginning. - * If it concludes with available data, attempt a re-encoding. - * If it has the correct erasure-root, break and issue a `Ok(available_data)`. - * If it has an incorrect erasure-root, return to beginning. - * Send the result to each member of `awaiting`. - * If the backer is `None`, set the source to `RequestChunksFromValidators` with a random shuffling of validators - and empty `received_chunks`, and `requesting_chunks` and break the loop. - -* If the task contains `RequestChunksFromValidators`: - * Request `AvailabilityStoreMessage::QueryAllChunks`. For each chunk that exists, add it to `received_chunks` and - remote the validator from `shuffling`. - * Loop: - * If `received_chunks + requesting_chunks + shuffling` lengths are less than the threshold, break and return - `Err(Unavailable)`. - * Poll for new updates from `requesting_chunks`. Check merkle proofs of any received chunks. If the request simply - fails due to network issues, insert into the front of `shuffling` to be retried. - * If `received_chunks` has more than `threshold` entries, attempt to recover the data. - * If that fails, return `Err(RecoveryError::Invalid)` - * If correct: - * If re-encoding produces an incorrect erasure-root, break and issue a `Err(RecoveryError::Invalid)`. - * break and issue `Ok(available_data)` - * Send the result to each member of `awaiting`. - * While there are fewer than `N_PARALLEL` entries in `requesting_chunks`, - * Pop the next item from `shuffling`. If it's empty and `requesting_chunks` is empty, return - `Err(RecoveryError::Unavailable)`. - * Issue a `NetworkBridgeMessage::Requests` and wait for the response in `requesting_chunks`. +Moreover, the recovery task is specially configured to not attempt requesting data from the local availability-store +(because it doesn't exist) and to not reencode the data after a succcessful recovery (because it's an expensive check +that is not needed; checking the pov_hash is enough for collators). diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/prospective-parachains.md b/polkadot/roadmap/implementers-guide/src/node/backing/prospective-parachains.md index 8f00ff084941cc260dea6a9e76c0ff30d3770caf..701f6c87caff0341c36e4b2799d2444c015c411c 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/prospective-parachains.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/prospective-parachains.md @@ -98,15 +98,11 @@ prospective validation data. This is unlikely to change. hashes. - Sent by the Provisioner when requesting backable candidates, when selecting candidates for a given relay-parent. -- `ProspectiveParachainsMessage::GetHypotheticalFrontier` +- `ProspectiveParachainsMessage::GetHypotheticalMembership` - Gets the hypothetical frontier membership of candidates with the given properties under the specified active leaves' fragment trees. - Sent by the Backing Subsystem when sanity-checking whether a candidate can be seconded based on its hypothetical frontiers. -- `ProspectiveParachainsMessage::GetTreeMembership` - - Gets the membership of the candidate in all fragment trees. - - Sent by the Backing Subsystem when it needs to update the candidates - seconded at various depths under new active leaves. - `ProspectiveParachainsMessage::GetMinimumRelayParents` - Gets the minimum accepted relay-parent number for each para in the fragment tree for the given relay-chain block hash. diff --git a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md index e6e597c531787f46ced0a6f9e38e05817f2323d7..e5eb9bd7642c1108c45e73134a00ee22b2f6475c 100644 --- a/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/backing/statement-distribution.md @@ -194,7 +194,7 @@ request). This doesn't fully avoid race conditions, but tries to minimize them. - Reports a peer (either good or bad). - `CandidateBackingMessage::Statement` - Note a validator's statement about a particular candidate. -- `ProspectiveParachainsMessage::GetHypotheticalFrontier` +- `ProspectiveParachainsMessage::GetHypotheticalMembership` - Gets the hypothetical frontier membership of candidates under active leaves' fragment trees. - `NetworkBridgeTxMessage::SendRequests` - Sends requests, initiating the request/response protocol. diff --git a/polkadot/roadmap/implementers-guide/src/protocol-disputes.md b/polkadot/roadmap/implementers-guide/src/protocol-disputes.md index 2a4082cc07f92aa99425e9e708ec2e90117c02c5..922cc3c3e2b56836d804f9decd8c2be44e7a7fd4 100644 --- a/polkadot/roadmap/implementers-guide/src/protocol-disputes.md +++ b/polkadot/roadmap/implementers-guide/src/protocol-disputes.md @@ -8,9 +8,9 @@ All parachain blocks that end up in the finalized relay chain should be valid. T only backed, but not included. We have two primary components for ensuring that nothing invalid ends up in the finalized relay chain: - * Approval Checking, as described [here](./protocol-approval.md) and implemented according to the [Approval - Voting](node/approval/approval-voting.md) subsystem. This protocol can be shown to prevent invalid parachain blocks - from making their way into the finalized relay chain as long as the amount of attempts are limited. + * Approval Checking, as described [here](./protocol-approval.md) and implemented accordingly in the [Approval +Voting](node/approval/approval-voting.md) subsystem. This protocol can be shown to prevent invalid parachain blocks +from making their way into the finalized relay chain as long as the amount of attempts are limited. * Disputes, this protocol, which ensures that each attempt to include something bad is caught, and the offending validators are punished. Disputes differ from backing and approval process (and can not be part of those) in that a dispute is independent of a particular fork, while both backing and approval operate on particular forks. This diff --git a/polkadot/roadmap/implementers-guide/src/protocol-validator-disabling.md b/polkadot/roadmap/implementers-guide/src/protocol-validator-disabling.md new file mode 100644 index 0000000000000000000000000000000000000000..9fd44c00fa0a1c9ba7f5bb0d5abd54bdc55b8e4e --- /dev/null +++ b/polkadot/roadmap/implementers-guide/src/protocol-validator-disabling.md @@ -0,0 +1,437 @@ +# Validator Disabling + +## Background + +As established in the [approval process](protocol-approval.md) dealing with bad parablocks is a three step process: + +1. Detection +1. Escalation +1. Consequences + +The main system responsible for dispensing **consequences** for malicious actors is the [dispute +system](protocol-disputes.md) which eventually dispenses slash events. The slashes itself can be dispensed quickly (a +matter of blocks) but for an extra layer of auditing all slashes are deferred for 27 days (in Polkadot/Kusama) which +gives time for Governance to investigate and potentially alter the punishment. Dispute concluding by itself does not +immediately remove the validator from the active validator set. + +> **Note:** \ +> There was an additional mechanism of automatically chilling the validator which removed their intent to participate in +> the next election, but the removed validator could simply re-register his intent to validate. + +There is a need to have a more immediate way to deal with malicious validators. This is where the validator disabling +comes in. It is focused on dispensing **low latency** consequences for malicious actors. It is important to note that +the validator disabling is not a replacement for the dispute or slashing systems. It is a complementary system that is +focused on lighter but immediate consequences usually in the form of restricted validator privileges. + +The primary goals are: +- Eliminate or minimize cases where attackers can get free attempts at attacking the network +- Eliminate or minimize the risks of honest nodes being pushed out of consensus when getting unjustly slashed (defense + in depth) + +The above two goals are generally at odds so a careful balance has to be struck between them. We will achieve them by +sacrificing some **liveness** in favor of **soundness** when the network is under stress. Maintaining some liveness but +absolute soundness is paramount. + +> **Note:** \ +> Liveness = Valid candidates can go through (at a decent pace) \ +> Security = Invalid candidates cannot go through (or are statistically very improbable) + +Side goals are: +- Reduce the damages to honest nodes that had a fault which might cause repeated slashes +- Reduce liveness impact of individual malicious attackers + +## System Overview + +High level assumptions and goals of the validator disabling system that will be further discussed in the following +sections: + +1. If validator gets slashed (even 0%) we mark them as disabled in the runtime and on the node side. +1. We only disable up to byzantine threshold of the validators. +1. If there are more offenders than byzantine threshold disable only the highest offenders. (Some might get re-enabled.) +1. Disablement lasts for 1 era. +1. Disabled validators remain in the active validator set but have some limited permissions. +1. Disabled validators can get re-elected. +1. Disabled validators can participate in approval checking. +1. Disabled validators can participate in GRANDPA/BEEFY, but equivocations cause disablement. +1. Disabled validators cannot author blocks. +1. Disabled validators cannot back candidates. +1. Disabled validators cannot initiate disputes, but their votes are still counted if a dispute occurs. +1. Disabled validators making dispute statements no-show in approval checking. + +


+ +# Risks + +## Risks of NOT having validator disabling + +Assume that if an offense is committed a slash is deposited but the perpetrator can still act normally. He will be +slashed 100% with a long delay (slash deferral duration which is 27 days). This is akin to the current design. + +A simple argument for disabling is that if someone is already slashed 100% and they have nothing to lose they could +cause harm to the network and should be silenced. + +What harm could they cause? + +**1. Liveness attacks:** + +- 1.1. Break sharding (with mass no-shows or mass disputes): It forces everyone to do all the work which affects + liveness but doesn't kill it completely. The chain can progress at a slow rate. + +- 1.2. Mass invalid candidate backing: Spawns a lot of worthless work that needs to be done but it is bounded by backing + numbers. Honest backers will still back valid candidates and that cannot be stopped. Honest block authors will + eventually select valid candidates and even if disputed they will win and progress the chain. + +**2. Soundness attacks:** + +- 2.1. The best and possibly only way to affect soundness is by getting lucky in the approval process. If by chance all + approval voters would be malicious, the attackers could get a single invalid candidate through. Their chances would be + relatively low but in general this risk has to be taken seriously as it significantly reduces the safety buffer around + approval checking. + +> **Note:** With 30 approvals needed chance that a malicious candidate going through is around 4\*10^-15. Assuming +> attackers can back invalid candidates on 50 cores for 48 hours straight and only those candidates get included it +> still gives a 7\*10^-9 chance of success which is still relatively small considering the cost (all malicious stake +> slashed). + +Attacks 1.2 and 2.1 should generally be pretty futile as a solo attacker while 1.1 could be possible with mass disputes +even from a single attacker. Nevertheless whatever the attack vector within the old system the attackers would get +*eventually* get slashed and pushed out of the active validator set but they had plenty of time to wreck havoc. + +## Risks of having validator disabling + +Assume we fully push out validator when they commit offenses. + +The primary risk behind having any sort of disabling is that it is a double-edged sword that in case of any dispute bugs +or sources of PVF non-determinism could disable honest nodes or be abused by attackers to specifically silence honest +nodes. + +Validators being pushed out of the validator set are an issue because that can greatly skew the numbers game in approval +checking (% for 30-ish malicious in a row). + +There are also censorship or liveness issues if backing is suddenly dominated by malicious nodes but in general even if +some honest blocks get backed liveness should be preserved. + +> **Note:** It is worth noting that is is fundamentally a defense in depth strategy because if we assume disputes are +> perfect it should not be a real concern. In reality disputes and determinism are difficult to get right, and +> non-determinism and happen so defense in depth is crucial when handling those subsystems. + +


+ +# Risks Mitigation + +## Addressing the risks of having validator disabling + +One safety measure is bounding the disabled number to 1/3 ([**Point 2.**](#system-overview)) or to be exact the +byzantine threshold. If for any reason more than 1/3 of validators are getting disabled it means that some part of the +protocol failed or there is more than 1/3 malicious nodes which breaks the assumptions. + +Even in such a dire situation where more than 1/3 got disabled the most likely scenario is a non-determinism bug or +sacrifice attack bug. Those attacks generally cause minor slashes to multiple honest nodes. In such a case the situation +could be salvaged by prioritizing highest offenders for disabling ([**Point 3.**](#system-overview)). + +> **Note:** \ +> System can be launched with re-enabling and will still provide some security improvements. Re-enabling will be +> launched in an upgrade after the initial deployment. + +Fully pushing out offending validator out of the validator set it too risky in case of a dispute bug, non-determinism or +sacrifice attacks. Main issue lies in skewing the numbers in approval checking so instead of fully blocking disabled +nodes a different approach can be taken - one were only some functionalities are disabled ([**Point +5.**](#system-overview)). Once of those functionalities can be approval voting which as pointed above is so crucial that +even in a disabled state nodes should be able to participate in it ([**Point 7.**](#system-overview)). + +> **Note:** \ +> Approval Checking statement are implicitly valid. Sending a statement for an invalid candidate is a part of the +> dispute logic which we did not yet discuss. For now we only allow nodes to state that a candidate is valid or remain +> silent. But this solves the main risk of disabling. + +Because we capped the number of disabled nodes to 1/3 there will always be at least 1/3 honest nodes to participate in +backing so liveness should be preserved. That means that backing **COULD** be safely disabled for disabled nodes +([**Point 10.**](#system-overview)). + + +## Addressing the risks of NOT having validator disabling + +To determine if backing **SHOULD** be disabled the attack vector of 1.2 (Mass invalid candidate backing) and 2.1 +(Getting lucky in approval voting) need to be considered. In both of those cases having extra backed malicious +candidates gives attackers extra chances to get lucky in approval checking. The solution is to not allow for backing in +disablement. ([**Point 10.**](#system-overview)) + +The attack vector 1.1 (Break sharding) requires a bit more nuance. If we assume that the attacker is a single entity and +that he can get a lot of disputes through he could potentially incredibly easily break sharding. This generally points +into the direction of disallowing that during disablement ([**Point 11.**](#system-overview)). + +This might seem like an issue because it takes away the escalation privileges of disabled approval checkers but this is +NOT true. By issuing a dispute statement those nodes remain silent in approval checking because they skip their approval +statement and thus will count as a no-show. This will create a mini escalation for that particular candidate. This means +that disabled nodes maintain just enough escalation that they can protect soundness (same argument as soundness +protection during a DoS attack on approval checking) but they lose their extreme escalation privilege which are only +given to flawlessly performing nodes ([**Point 12.**](#system-overview)). + +As a defense in depth measure dispute statements from disabled validators count toward confirming disputes (byzantine +threshold needed to confirm). If a dispute is confirmed everyone participates in it. This protects us from situations +where due to a bug more than byzantine threshold of validators would be disabled. + +> **Note:** \ +> The way this behavior is achieved easily in implementation is that honest nodes note down dispute statements from +> disabled validators just like they would for normal nodes, but they do not release their own dispute statements unless +> the dispute is confirmed already. This simply stops the escalation process of disputes. + +

+ +# Disabling Duration + +## Context + +A crucial point to understand is that as of the time of writing all slashing events as alluded to in the begging are +delayed for 27 days before being executed. This is primarily because it gives governance enough time to investigate and +potentially intervene. For that duration when the slash is pending the stake is locked and cannot be moved. Time to +unbond you stake is 28 days which ensures that the stake will eventually be slashed before being withdrawn. + +## Design + +A few options for the duration of disablement were considered: +- 1 epoch (4h in Polkadot) +- 1 era (24h in Polkadot) +- 2-26 eras +- 27 eras + +1 epoch is a short period and between a few epochs the validator will most likely be exactly the same. It is also very +difficult to fix any local node issues for honest validator in such a short time so the chance for a repeated offense is +high. + +1 era gives a bit more time to fix any minor issues. Additionally, it guarantees a validator set change at so many of +the currently disabled validator might no longer be present anyway. It also gives the time for the validator to chill +themselves if they have identified a cause and want to spend more time fixing it. ([**Point 4.**](#system-overview)) + +Higher values could be considered and the main arguments for those are based around the fact that it reduces the number +of repeated attacks that will be allowed before the slash execution. Generally 1 attack per era for 27 eras resulting in +27 attacks at most should not compromise our safety assumptions. Although this direction could be further explored and +might be parametrized for governance to decide. + +


+ +# Economic consequences of Disablement + +Disablement is generally a form of punishment and that will be reflected in the rewards at the end of an era. A disabled +validator will not receive any rewards for backing or block authoring. which will reduce its profits. + +That means that the opportunity cost of being disabled is a punishment by itself and thus it can be used for some cases +where a minor punishment is needed. Current implementation was using 0% slashes to mark nodes for chilling and similar +approach of 0% slashes can be used to mark validators for disablement. ([**Point 1.**](#system-overview)) 0% slashes +could for instance be used to punish approval checkers voting invalid on valid candidates. + +Anything higher than 0% will of course also lead to a disablement. + +> **Notes:** \ +> Alternative designs incorporating disabling proportional to offenses were explored but they were deemed too complex +> and not worth the effort. Main issue with those is that proportional disabling would cause back and forth between +> disabled and enabled which complicated tracking the state of disabled validators and messes with optimistic node +> optimizations. Main benefits were that minor slashes will be barely disabled which has nice properties against +> sacrifice attacks. + +


+ +# Redundancy + +Some systems can be greatly simplified or outright removed thanks to the above changes. This leads to reduced complexity +around the systems that were hard to reason about and were sources of potential bugs or new attack vectors. + +## Automatic Chilling + +Chilling is process of a validator dropping theirs intent to validate. This removes them from the upcoming NPoS +elections and effectively pushes them out of the validator set as quickly as of the next era (or 2 era in case of late +offenses). All nominators of that validator were also getting unsubscribed from that validator. Validator could +re-register their intent to validate at any time. The intent behind this logic was to protect honest stakes from +repeated slashes caused by unnoticed bugs. It would give time for validators to fix their issue before continuing as a +validator. + +Chilling had a myriad of problems. It assumes that validators and nominators remain very active and monitor everything. +If a validator got slashed he was getting automatically chilled and his nominators were getting unsubscribed. This was +an issue because of minor non-malicious slashes due to node operator mistakes or small bugs. Validators got those bugs +fixed quickly and were reimbursed but nominator had to manually re-subscribe to the validator, which they often +postponed for very lengthy amounts of time most likely due to simply not checking their stake. **This forced +unsubscribing of nominators was later disabled.** + +Automatic chilling was achieving its goals in ideal scenarios (no attackers, no lazy nominators) but it opened new +vulnerabilities for attackers. The biggest issue was that chilling in case of honest node slashes could lead to honest +validators being quickly pushed out of the next validator set within the next era. This retains the validator set size +but gives an edge to attackers as they can more easily win slots in the NPoS election. + +Disabling allows for punishment that limits the damages malicious actors can cause without having to resort to kicking +them out of the validator set. This protects us from the edge case of honest validators getting quickly pushed out of +the set by slashes. ([**Point 6.**](#system-overview)) + +> **Notes:** \ +> As long as honest slashes absolutely cannot occur automatic chilling is a sensible and desirable. This means it could +> be re-enabled once PolkaVM introduces deterministic gas metering. Then best of both worlds could be achieved. + +## Forcing New Era + +Previous implementation of disabling had some limited mechanisms allowing for validators disablement and if too many +were disabled forcing a new era (new election). Frame staking pallet offered the ability to force a new era but it was +also deemed unsafe as it could be abused and compromised the security of the network for instance by weakening the +randomness used throughout the protocol. + +


+ +# Other types of slashing + +Above slashes were specifically referring to slashing events coming from disputes against candidates, but in Polkadot +other types of offenses exist for example GRANDPA equivocations or block authoring offenses. Question is if the above +defined design can handle those offenses. + +## GRANDPA/BEEFY Offenses + +The main offences for GRANDPA/BEEFY are equivocations. It is not a very serious offense and some nodes committing do not +endanger the system and performance is barely affected. If more than byzantine threshold of nodes equivocate it is a +catastrophic failure potentially resulting in 2 finalized blocks on the same height in the case of GRANDPA. + +Honest nodes generally should not commit those offenses so the goal of protecting them does not apply here. + +> **Note:** \ +> A validator running multiple nodes with the same identity might equivocate. Doing that is highly not advised but it +> has happened before. + +It's not a game of chance so giving attackers extra chances does not compromise soundness. Also it requires a +supermajority of honest nodes to successfully finalize blocks so any disabling of honest nodes from GRANDPA might +compromise liveness. + +Best approach is to allow disabled nodes to participate in GRANDPA/BEEFY as normal and as mentioned before +GRANDPA/BABE/BEEFY equivocations should not happen to honest nodes so we can safely disable the offenders. Additionally +the slashes for singular equivocations will be very low so those offenders would easily get re-enabled in the case of +more serious offenders showing up. ([**Point 8.**](#system-overview)) + +## Block Authoring Offenses (BABE Equivocations) + +Even if all honest nodes are disabled in Block Authoring (BA) liveness is generally preserved. At least 50% of blocks +produced should still be honest. Soundness wise disabled nodes can create a decent amount of wasted work by creating bad +blocks but they only get to do it in bounded amounts. + +Disabling in BA is not a requirement as both liveness and soundness are preserved but it is the current default behavior +as well as it offers a bit less wasted work. + +Offenses in BA just like in backing can be caused by faulty PVFs or bugs. They might happen to honest nodes and +disabling here while not a requirement can also ensure that this node does not repeat the offense as it might not be +trusted with it's PVF anymore. + +Both points above don't present significant risks when disabling so the default behavior is to disable in BA and because +of offenses in BA. ([**Point 9.**](#system-overview)) This filters out honest faulty nodes as well as protects from some +attackers. + +


+ +# Extra Design Considerations + +## Disabling vs Accumulating Slashes + +Instant disabling generally allows us to remove the need for accumulating slashes. It is a more immediate punishment and +it is a more lenient punishment for honest nodes. + +The current architecture of using max slashing can be used and it works around the problems of delaying the slash for a +long period. + +An alternative design with immediate slashing and acclimating slashing could relevant to other systems but it goes +against the governance auditing mechanisms so it's not be suitable for Polkadot. + +## Disabling vs Getting Pushed Out of NPoS Elections + +Validator disabling and getting forced ouf of NPoS elections (1 era) due to slashes are actually very similar processes +in terms of outcomes but there are some differences: + +- **latency** (next few blocks for validator disabling and 27 days for getting pushed out organically) +- **pool restriction** (validator disabling could effectively lower the number of active validators during an era if we + fully disable) +- **granularity** (validator disabling could remove only a portion of validator privileges instead of all) + +Granularity is particularly crucial in the final design as only a few select functions are disabled while others remain. + +## Enabling Approval Voter Slashes + +The original Polkadot 1.0 design describes that all validators on the loosing side of the dispute are slashed. In the +current system only the backers are slashed and any approval voters on the wrong side will not be slashed. This creates +some undesirable incentives: + +- Lazy approval checkers (approvals yay`ing everything) +- Spammy approval checkers (approval voters nay`ing everything) + +Initially those slashes were disabled to reduce the complexity and to minimize the risk surface in case the system +malfunctioned. This is especially risky in case any nondeterministic bugs are present in the system. Once validator +re-enabling is launched approval voter slashes can be re-instated. Numbers need to be further explored but slashes +between 0-2% are reasonable. 0% would still disable which with the opportunity cost consideration should be enough. + + > **Note:** \ +> Spammy approval checkers are in fact not a big issue as a side effect of the offchain-disabling introduced by the +> Defense Against Past-Era Dispute Spam (**Node**) [#2225](https://github.com/paritytech/polkadot-sdk/issues/2225). It +> makes it so all validators loosing a dispute are locally disabled and ignored for dispute initiation so it effectively +> silences spammers. They can still no-show but the damage is minimized. + + +## Interaction with all types of misbehaviors + +With re-enabling in place and potentially approval voter slashes enabled the overall misbehaviour-punishment system can +be as highlighted in the table below: + +|Misbehaviour |Slash % |Onchain Disabling |Offchain Disabling |Chilling |Reputation Costs | +|------------ |------- |----------------- |------------------ |-------- |----------------- | +|Backing Invalid |100% |Yes (High Prio) |Yes (High Prio) |No |No | +|ForInvalid Vote |2% |Yes (Mid Prio) |Yes (Mid Prio) |No |No | +|AgainstValid Vote |0% |Yes (Low Prio) |Yes (Low Prio) |No |No | +|GRANDPA / BABE / BEEFY Equivocations |0.01-100% |Yes (Varying Prio) |No |No |No | +|Seconded + Valid Equivocation |- |No |No |No |No | +|Double Seconded Equivocation |- |No |No |No |Yes | + + +*Ignoring AURA offences. + +**There are some other misbehaviour types handled in rep only (DoS prevention etc) but they are not relevant to this strategy. + +*** BEEFY will soon introduce new slash types so this strategy table will need to be revised but no major changes are expected. + +


+ +# Implementation + +Implementation of the above design covers a few additional areas that allow for node-side optimizations. + +## Core Features + +1. Disabled Validators Tracking (**Runtime**) [#2950](https://github.com/paritytech/polkadot-sdk/issues/2950) + - Expose a ``disabled_validators`` map through a Runtime API +1. Enforce Backing Disabling (**Runtime**) [#1592](https://github.com/paritytech/polkadot-sdk/issues/1592) + - Filter out votes from ``disabled_validators`` in ``BackedCandidates`` in ``process_inherent_data`` +1. Substrate Byzantine Threshold (BZT) as Limit for Disabling + [#1963](https://github.com/paritytech/polkadot-sdk/issues/1963) + - Can be parametrized but default to BZT + - Disable only up to 1/3 of validators +1. Respect Disabling in Backing Statement Distribution (**Node**) + [#1591](https://github.com/paritytech/polkadot-sdk/issues/1951) + - This is an optimization as in the end it would get filtered in the runtime anyway + - Filter out backing statements coming from ``disabled_validators`` +1. Respect Disablement in Backing (**Node**) [#2951](https://github.com/paritytech/polkadot-sdk/issues/2951) + - This is an optimization as in the end it would get filtered in the runtime anyway + - Don't start backing new candidates when disabled + - Don't react to backing requests when disabled +1. Stop Automatic Chilling of Offenders [#1962](https://github.com/paritytech/polkadot-sdk/issues/1962) + - Chilling still persists as a state but is no longer automatically applied on offenses +1. Respect Disabling in Dispute Participation (**Node**) [#2225](https://github.com/paritytech/polkadot-sdk/issues/2225) + - Receive dispute statements from ``disabled_validators`` but do not release own statements + - Ensure dispute confirmation when BZT statements from disabled +1. Remove Liveness Slashes [#1964](https://github.com/paritytech/polkadot-sdk/issues/1964) + - Remove liveness slashes from the system + - The are other incentives to be online and they could be abused to attack the system +1. Defense Against Past-Era Dispute Spam (**Node**) [#2225](https://github.com/paritytech/polkadot-sdk/issues/2225) + - This is needed because runtime cannot disable validators which it no longer knows about + - Add a node-side parallel store of ``disabled_validators`` + - Add new disabled validators to node-side store when they loose a dispute in any leaf in scope + - Runtime ``disabled_validators`` always have priority over node-side ``disabled_validators`` + - Respect the BZT threshold + > **Note:** \ + > An alternative design here was considered where instead of tracking new incoming leaves a relay parent is used. + > This would guarantee determinism as different nodes can see different leaves, but this approach was leaving too + > wide of a window because of Async-Backing. Relay Parent could have been significantly in the past and it would + > give a lot of time for past session disputes to be spammed. +1. Do not block finality for "disabled" disputes [#3358](https://github.com/paritytech/polkadot-sdk/pull/3358) + - Emergency fix to not block finality for disputes initiated only by disabled validators +1. Re-enable small offender when approaching BZT (**Runtime**) #TODO + - When BZT limit is reached and there are more offenders to be disabled re-enable the smallest offenders to disable + the biggest ones diff --git a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md index 083ed2b6feac9ed6d27c44bc2267744dd49fffd1..be1e71666ad20626711e23f828820155746cbb68 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md @@ -1,7 +1,7 @@ # Scheduler Pallet > TODO: this section is still heavily under construction. key questions about availability cores and validator -> assignment are still open and the flow of the the section may be contradictory or inconsistent +> assignment are still open and the flow of the section may be contradictory or inconsistent The Scheduler module is responsible for two main tasks: diff --git a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md index e011afb97089aaf59d685b8d4bf9998d21390146..c82d89d2d8799eff6a68b49bdb01ee15bbe43d84 100644 --- a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -238,6 +238,9 @@ enum AvailabilityRecoveryMessage { CandidateReceipt, SessionIndex, Option, // Backing validator group to request the data directly from. + Option, /* A `CoreIndex` needs to be specified for the recovery process to + * prefer systematic chunk recovery. This is the core that the candidate + * was occupying while pending availability. */ ResponseChannel>, ), } diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml index 4219a7e7b0dcb57c50a5e709d0695dfa723b582a..3a64148817682096d409e9ea1c4e38a39b44d7b7 100644 --- a/polkadot/runtime/common/Cargo.toml +++ b/polkadot/runtime/common/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } rustc-hex = { version = "2.1.0", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/polkadot/runtime/common/slot_range_helper/Cargo.toml b/polkadot/runtime/common/slot_range_helper/Cargo.toml index cacafd8ed3b746d35b5b064ca3d6662b313f8b86..314e101ad221e9e842eb609a0ca6d80d8c8c52ad 100644 --- a/polkadot/runtime/common/slot_range_helper/Cargo.toml +++ b/polkadot/runtime/common/slot_range_helper/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] paste = "1.0" enumn = "0.1.12" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sp-std = { package = "sp-std", path = "../../../../substrate/primitives/std", default-features = false } sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } diff --git a/polkadot/runtime/common/src/assigned_slots/mod.rs b/polkadot/runtime/common/src/assigned_slots/mod.rs index 9b24b99cfbe2a2f1d06fc842f798a6232077e2fb..92a8e46f5f9cc55888c7e8d9b4a7d743e6e6ad70 100644 --- a/polkadot/runtime/common/src/assigned_slots/mod.rs +++ b/polkadot/runtime/common/src/assigned_slots/mod.rs @@ -671,10 +671,6 @@ mod tests { type OverarchingCall = RuntimeCall; } - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; @@ -689,7 +685,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; diff --git a/polkadot/runtime/common/src/auctions.rs b/polkadot/runtime/common/src/auctions.rs index aa4caac96f154b43f60fb4aa0dc45b9017aff1d9..e7b7c081ae4e96fd51f030fb482d9b9145a0d1d1 100644 --- a/polkadot/runtime/common/src/auctions.rs +++ b/polkadot/runtime/common/src/auctions.rs @@ -699,10 +699,6 @@ mod tests { } ); - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; @@ -718,7 +714,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/polkadot/runtime/common/src/crowdloan/mod.rs b/polkadot/runtime/common/src/crowdloan/mod.rs index 477530467fa105d93b41569d851b5699aadc09b0..0aecbcd531c49bba6d4ea3ca2c4f367ed3530d08 100644 --- a/polkadot/runtime/common/src/crowdloan/mod.rs +++ b/polkadot/runtime/common/src/crowdloan/mod.rs @@ -890,10 +890,6 @@ mod tests { } ); - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - type BlockNumber = u64; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] @@ -911,7 +907,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs index 85531e9c04fc47f83fb007802e30e87799c2150c..a92a05219cf8762d4903c3fbd1853e517b77f67e 100644 --- a/polkadot/runtime/common/src/impls.rs +++ b/polkadot/runtime/common/src/impls.rs @@ -276,7 +276,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() .base_block(Weight::from_parts(10, 0)) .for_class(DispatchClass::all(), |weight| { @@ -302,7 +301,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockLength = BlockLength; type BlockWeights = BlockWeights; type DbWeight = (); diff --git a/polkadot/runtime/common/src/integration_tests.rs b/polkadot/runtime/common/src/integration_tests.rs index 3e9ac1fc1b152574ea86d42c7d48f51da47ddc39..2122e75f3e2d2ac641df5429982ba3d1de679e2a 100644 --- a/polkadot/runtime/common/src/integration_tests.rs +++ b/polkadot/runtime/common/src/integration_tests.rs @@ -109,7 +109,6 @@ where use crate::{auctions::Error as AuctionsError, crowdloan::Error as CrowdloanError}; parameter_types! { - pub const BlockHashCount: u32 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max( Weight::from_parts(4 * 1024 * 1024, u64::MAX), @@ -131,7 +130,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/polkadot/runtime/common/src/paras_registrar/mod.rs b/polkadot/runtime/common/src/paras_registrar/mod.rs index a49ebab3e26a8df5ecfdf7615849b75d9e3c4671..c90802a40129bceb4a74f8f8fe4f7d4f54426482 100644 --- a/polkadot/runtime/common/src/paras_registrar/mod.rs +++ b/polkadot/runtime/common/src/paras_registrar/mod.rs @@ -761,7 +761,6 @@ mod tests { const NORMAL_RATIO: Perbill = Perbill::from_percent(75); parameter_types! { - pub const BlockHashCount: u32 = 250; pub BlockWeights: limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, u64::MAX)); pub BlockLength: limits::BlockLength = @@ -780,7 +779,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type DbWeight = (); type BlockWeights = BlockWeights; type BlockLength = BlockLength; diff --git a/polkadot/runtime/common/src/purchase.rs b/polkadot/runtime/common/src/purchase.rs index b90bbb3a7cfb87c8753114de74d12119ad8b6c56..3920a2c68c5532dcdca6b9363bd5a193a380c9f2 100644 --- a/polkadot/runtime/common/src/purchase.rs +++ b/polkadot/runtime/common/src/purchase.rs @@ -508,10 +508,6 @@ mod tests { type AccountId = AccountId32; - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; @@ -527,7 +523,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/polkadot/runtime/common/src/slots/mod.rs b/polkadot/runtime/common/src/slots/mod.rs index 738569ff4416c0049ca134e5ea94cf5e9245f81d..9da345beea3991057e65ca5d4019c0064e3c2699 100644 --- a/polkadot/runtime/common/src/slots/mod.rs +++ b/polkadot/runtime/common/src/slots/mod.rs @@ -525,10 +525,6 @@ mod tests { } ); - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; @@ -543,7 +539,6 @@ mod tests { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; diff --git a/polkadot/runtime/common/src/xcm_sender.rs b/polkadot/runtime/common/src/xcm_sender.rs index a712d4381f75f586ada72b3046925d97a1fba1db..cbec1a8ca1036117275b5234229c2cfc06481056 100644 --- a/polkadot/runtime/common/src/xcm_sender.rs +++ b/polkadot/runtime/common/src/xcm_sender.rs @@ -18,7 +18,7 @@ use frame_support::traits::Get; use frame_system::pallet_prelude::BlockNumberFor; -use parity_scale_codec::Encode; +use parity_scale_codec::{Decode, Encode}; use primitives::Id as ParaId; use runtime_parachains::{ configuration::{self, HostConfiguration}, @@ -27,6 +27,7 @@ use runtime_parachains::{ use sp_runtime::FixedPointNumber; use sp_std::{marker::PhantomData, prelude::*}; use xcm::prelude::*; +use xcm_builder::InspectMessageQueues; use SendError::*; /// Simple value-bearing trait for determining/expressing the assets required to be paid for a @@ -138,6 +139,24 @@ where } } +impl InspectMessageQueues for ChildParachainRouter { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + dmp::DownwardMessageQueues::::iter() + .map(|(para_id, messages)| { + let decoded_messages: Vec> = messages + .iter() + .map(|downward_message| { + let message = VersionedXcm::<()>::decode(&mut &downward_message.msg[..]).unwrap(); + log::trace!(target: "xcm::DownwardMessageQueues::get_messages", "Message: {:?}, sent at: {:?}", message, downward_message.sent_at); + message + }) + .collect(); + (VersionedLocation::V4(Parachain(para_id.into()).into()), decoded_messages) + }) + .collect() + } +} + /// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the /// `ParaId` parachain (sibling or child). Deposits existential deposit for origin (if needed). /// Deposits estimated fee to the origin account (if needed). diff --git a/polkadot/runtime/metrics/Cargo.toml b/polkadot/runtime/metrics/Cargo.toml index 481627542865e1e79e4be790c3ccf46cc5878c07..76c1d134fa18669768aff9e860bbaee35a201e67 100644 --- a/polkadot/runtime/metrics/Cargo.toml +++ b/polkadot/runtime/metrics/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] sp-std = { package = "sp-std", path = "../../../substrate/primitives/std", default-features = false } sp-tracing = { path = "../../../substrate/primitives/tracing", default-features = false } -parity-scale-codec = { version = "3.6.1", default-features = false } +parity-scale-codec = { version = "3.6.12", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 402c6e487a1f8b2b2ad9f535ca60bdc160c69895..d00a19c6ddb8e43881473d7b22daa31b4cc6990c 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } log = { workspace = true } rustc-hex = { version = "2.1.0", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs index 598a0f10970067a67186098019e6f067798df2da..795759b3b39e18880da9e314697ee4a0832d3939 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs @@ -173,7 +173,7 @@ impl QueueStatusType { fn consume_index(&mut self, removed_index: QueueIndex) { if removed_index != self.smallest_index { self.freed_indices.push(removed_index.reverse()); - return + return; } let mut index = self.smallest_index.0.overflowing_add(1).0; // Even more to advance? @@ -368,10 +368,10 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// An order was placed at some spot price amount. - OnDemandOrderPlaced { para_id: ParaId, spot_price: BalanceOf }, - /// The value of the spot traffic multiplier changed. - SpotTrafficSet { traffic: FixedU128 }, + /// An order was placed at some spot price amount by orderer ordered_by + OnDemandOrderPlaced { para_id: ParaId, spot_price: BalanceOf, ordered_by: T::AccountId }, + /// The value of the spot price has likely changed + SpotPriceSet { spot_price: BalanceOf }, } #[pallet::error] @@ -410,12 +410,11 @@ pub mod pallet { /// /// Errors: /// - `InsufficientBalance`: from the Currency implementation - /// - `InvalidParaId` /// - `QueueFull` /// - `SpotPriceHigherThanMaxAmount` /// /// Events: - /// - `SpotOrderPlaced` + /// - `OnDemandOrderPlaced` #[pallet::call_index(0)] #[pallet::weight(::WeightInfo::place_order_allow_death(QueueStatus::::get().size()))] pub fn place_order_allow_death( @@ -437,12 +436,11 @@ pub mod pallet { /// /// Errors: /// - `InsufficientBalance`: from the Currency implementation - /// - `InvalidParaId` /// - `QueueFull` /// - `SpotPriceHigherThanMaxAmount` /// /// Events: - /// - `SpotOrderPlaced` + /// - `OnDemandOrderPlaced` #[pallet::call_index(1)] #[pallet::weight(::WeightInfo::place_order_keep_alive(QueueStatus::::get().size()))] pub fn place_order_keep_alive( @@ -539,12 +537,11 @@ where /// /// Errors: /// - `InsufficientBalance`: from the Currency implementation - /// - `InvalidParaId` /// - `QueueFull` /// - `SpotPriceHigherThanMaxAmount` /// /// Events: - /// - `SpotOrderPlaced` + /// - `OnDemandOrderPlaced` fn do_place_order( sender: ::AccountId, max_amount: BalanceOf, @@ -578,6 +575,12 @@ where Error::::QueueFull ); Pallet::::add_on_demand_order(queue_status, para_id, QueuePushDirection::Back); + Pallet::::deposit_event(Event::::OnDemandOrderPlaced { + para_id, + spot_price, + ordered_by: sender, + }); + Ok(()) }) } @@ -599,7 +602,14 @@ where // Only update storage on change if new_traffic != old_traffic { queue_status.traffic = new_traffic; - Pallet::::deposit_event(Event::::SpotTrafficSet { traffic: new_traffic }); + + // calculate the new spot price + let spot_price: BalanceOf = new_traffic.saturating_mul_int( + config.scheduler_params.on_demand_base_fee.saturated_into::>(), + ); + + // emit the event for updated new price + Pallet::::deposit_event(Event::::SpotPriceSet { spot_price }); } }, Err(err) => { @@ -721,7 +731,7 @@ where "Decreased affinity for a para that has not been served on a core?" ); if affinity != Some(0) { - return + return; } // No affinity more for entries on this core, free any entries: // @@ -740,7 +750,7 @@ where /// /// Subtracts from the count of the `CoreAffinityCount` if an entry is found and the core_index /// matches. When the count reaches 0, the entry is removed. - /// A non-existant entry is a no-op. + /// A non-existent entry is a no-op. /// /// Returns: The new affinity of the para on that core. `None` if there is no affinity on this /// core. @@ -754,7 +764,7 @@ where } else { *maybe_affinity = None; } - return Some(new_count) + return Some(new_count); } else { None } diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index b5dad6c6e864ba94854e3b56198c75f894f89ce7..34923897f02b38891ca7af122f48ee91988a483e 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -30,7 +30,7 @@ use primitives::{ NodeFeatures, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE, }; -use sp_runtime::{traits::Zero, Perbill}; +use sp_runtime::{traits::Zero, Perbill, Percent}; use sp_std::prelude::*; #[cfg(test)] @@ -1460,3 +1460,16 @@ impl Pallet { Ok(()) } } + +/// The implementation of `Get<(u32, u32)>` which reads `ActiveConfig` and returns `P` percent of +/// `hrmp_channel_max_message_size` / `hrmp_channel_max_capacity`. +pub struct ActiveConfigHrmpChannelSizeAndCapacityRatio(sp_std::marker::PhantomData<(T, P)>); +impl> Get<(u32, u32)> + for ActiveConfigHrmpChannelSizeAndCapacityRatio +{ + fn get() -> (u32, u32) { + let config = ActiveConfig::::get(); + let percent = P::get(); + (percent * config.hrmp_channel_max_message_size, percent * config.hrmp_channel_max_capacity) + } +} diff --git a/polkadot/runtime/parachains/src/configuration/tests.rs b/polkadot/runtime/parachains/src/configuration/tests.rs index 239b466fde3970babec24ad109a22e16be2c9066..64bbb8481fc1ba63ff8f851aa8b3d2ba5d6bd7df 100644 --- a/polkadot/runtime/parachains/src/configuration/tests.rs +++ b/polkadot/runtime/parachains/src/configuration/tests.rs @@ -17,7 +17,7 @@ use super::*; use crate::{ configuration, - mock::{new_test_ext, Configuration, ParasShared, RuntimeOrigin, Test}, + mock::{new_test_ext, Configuration, MockGenesisConfig, ParasShared, RuntimeOrigin, Test}, }; use bitvec::{bitvec, prelude::Lsb0}; use frame_support::{assert_err, assert_noop, assert_ok}; @@ -547,3 +547,51 @@ fn verify_externally_accessible() { ); }); } + +#[test] +fn active_config_hrmp_channel_size_and_capacity_ratio_works() { + frame_support::parameter_types! { + pub Ratio100: Percent = Percent::from_percent(100); + pub Ratio50: Percent = Percent::from_percent(50); + } + + let mut genesis: MockGenesisConfig = Default::default(); + genesis.configuration.config.hrmp_channel_max_message_size = 1024; + genesis.configuration.config.hrmp_channel_max_capacity = 100; + + new_test_ext(genesis).execute_with(|| { + let active_config = configuration::ActiveConfig::::get(); + assert_eq!(active_config.hrmp_channel_max_message_size, 1024); + assert_eq!(active_config.hrmp_channel_max_capacity, 100); + + assert_eq!( + ActiveConfigHrmpChannelSizeAndCapacityRatio::::get(), + (1024, 100) + ); + assert_eq!(ActiveConfigHrmpChannelSizeAndCapacityRatio::::get(), (512, 50)); + + // change ActiveConfig + assert_ok!(Configuration::set_hrmp_channel_max_message_size( + RuntimeOrigin::root(), + active_config.hrmp_channel_max_message_size * 4 + )); + assert_ok!(Configuration::set_hrmp_channel_max_capacity( + RuntimeOrigin::root(), + active_config.hrmp_channel_max_capacity * 4 + )); + on_new_session(1); + on_new_session(2); + let active_config = configuration::ActiveConfig::::get(); + assert_eq!(active_config.hrmp_channel_max_message_size, 4096); + assert_eq!(active_config.hrmp_channel_max_capacity, 400); + + assert_eq!( + ActiveConfigHrmpChannelSizeAndCapacityRatio::::get(), + (4096, 400) + ); + assert_eq!( + ActiveConfigHrmpChannelSizeAndCapacityRatio::::get(), + (2048, 200) + ); + }) +} diff --git a/polkadot/runtime/parachains/src/coretime/migration.rs b/polkadot/runtime/parachains/src/coretime/migration.rs index 4f52fc99ec308a7f3dc21aa37495dbbfe8b9464b..6c8ddaa8aab30c702a4c13c25e3d1c571e6a79cf 100644 --- a/polkadot/runtime/parachains/src/coretime/migration.rs +++ b/polkadot/runtime/parachains/src/coretime/migration.rs @@ -46,7 +46,7 @@ mod v_coretime { #[cfg(feature = "try-runtime")] use sp_std::vec::Vec; use sp_std::{iter, prelude::*, result}; - use xcm::v4::{send_xcm, Instruction, Junction, Location, SendError, WeightLimit, Xcm}; + use xcm::prelude::{send_xcm, Instruction, Junction, Location, SendError, WeightLimit, Xcm}; /// Return information about a legacy lease of a parachain. pub trait GetLegacyLease { diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs index a30f7336f692f28d43b17f1ab6aef5fcdf7f2e96..33cbcb98fb29992a4eac77db9eb7def4088af16f 100644 --- a/polkadot/runtime/parachains/src/coretime/mod.rs +++ b/polkadot/runtime/parachains/src/coretime/mod.rs @@ -26,7 +26,9 @@ pub use pallet::*; use pallet_broker::{CoreAssignment, CoreIndex as BrokerCoreIndex}; use primitives::{CoreIndex, Id as ParaId}; use sp_arithmetic::traits::SaturatedConversion; -use xcm::v4::{send_xcm, Instruction, Junction, Location, OriginKind, SendXcm, WeightLimit, Xcm}; +use xcm::prelude::{ + send_xcm, Instruction, Junction, Location, OriginKind, SendXcm, WeightLimit, Xcm, +}; use crate::{ assigner_coretime::{self, PartsOf57600}, @@ -104,7 +106,7 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The runtime's definition of a Currency. type Currency: Currency; - /// The ParaId of the broker system parachain. + /// The ParaId of the coretime chain. #[pallet::constant] type BrokerId: Get; /// Something that provides the weight of this pallet. @@ -137,10 +139,16 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// Request the configuration to be updated with the specified number of cores. Warning: + /// Since this only schedules a configuration update, it takes two sessions to come into + /// effect. + /// + /// - `origin`: Root or the Coretime Chain + /// - `count`: total number of cores #[pallet::weight(::WeightInfo::request_core_count())] #[pallet::call_index(1)] pub fn request_core_count(origin: OriginFor, count: u16) -> DispatchResult { - // Ignore requests not coming from the broker parachain or root. + // Ignore requests not coming from the coretime chain or root. Self::ensure_root_or_para(origin, ::BrokerId::get().into())?; configuration::Pallet::::set_coretime_cores_unchecked(u32::from(count)) @@ -153,7 +161,7 @@ pub mod pallet { // origin: OriginFor, // _when: BlockNumberFor, //) -> DispatchResult { - // // Ignore requests not coming from the broker parachain or root. + // // Ignore requests not coming from the coretime chain or root. // Self::ensure_root_or_para(origin, ::BrokerId::get().into())?; // Ok(()) //} @@ -166,7 +174,7 @@ pub mod pallet { // _who: T::AccountId, // _amount: BalanceOf, //) -> DispatchResult { - // // Ignore requests not coming from the broker parachain or root. + // // Ignore requests not coming from the coretime chain or root. // Self::ensure_root_or_para(origin, ::BrokerId::get().into())?; // Ok(()) //} @@ -175,7 +183,7 @@ pub mod pallet { /// to be used. /// /// Parameters: - /// -`origin`: The `ExternalBrokerOrigin`, assumed to be the Broker system parachain. + /// -`origin`: The `ExternalBrokerOrigin`, assumed to be the coretime chain. /// -`core`: The core that should be scheduled. /// -`begin`: The starting blockheight of the instruction. /// -`assignment`: How the blockspace should be utilised. @@ -191,7 +199,7 @@ pub mod pallet { assignment: Vec<(CoreAssignment, PartsOf57600)>, end_hint: Option>, ) -> DispatchResult { - // Ignore requests not coming from the broker parachain or root. + // Ignore requests not coming from the coretime chain or root. Self::ensure_root_or_para(origin, T::BrokerId::get().into())?; let core = u32::from(core).into(); @@ -241,7 +249,7 @@ impl Pallet { } } - // Handle legacy swaps in coretime. Notifies broker parachain that a lease swap has occurred via + // Handle legacy swaps in coretime. Notifies coretime chain that a lease swap has occurred via // XCM message. This function is meant to be used in an implementation of `OnSwap` trait. pub fn on_legacy_lease_swap(one: ParaId, other: ParaId) { let message = Xcm(vec![ diff --git a/polkadot/runtime/parachains/src/dmp.rs b/polkadot/runtime/parachains/src/dmp.rs index 354b16cc3f082f2f74ad276e8139e21d4094c4cc..df2f93e194214c7bec474668f197ceaca53818ed 100644 --- a/polkadot/runtime/parachains/src/dmp.rs +++ b/polkadot/runtime/parachains/src/dmp.rs @@ -119,7 +119,7 @@ pub mod pallet { /// The downward messages addressed for a certain para. #[pallet::storage] - pub(crate) type DownwardMessageQueues = StorageMap< + pub type DownwardMessageQueues = StorageMap< _, Twox64Concat, ParaId, diff --git a/polkadot/runtime/parachains/src/hrmp.rs b/polkadot/runtime/parachains/src/hrmp.rs index 65652b38577b361353aca1920255e9788c838028..42a9c23e5aa1132c5f0ff4044b53df2407efdc1e 100644 --- a/polkadot/runtime/parachains/src/hrmp.rs +++ b/polkadot/runtime/parachains/src/hrmp.rs @@ -278,6 +278,14 @@ pub mod pallet { /// parachain. type DefaultChannelSizeAndCapacityWithSystem: Get<(u32, u32)>; + /// Means of converting an `Xcm` into a `VersionedXcm`. This pallet sends HRMP XCM + /// notifications to the channel-related parachains, while the `WrapVersion` implementation + /// attempts to wrap them into the most suitable XCM version for the destination parachain. + /// + /// NOTE: For example, `pallet_xcm` provides an accurate implementation (recommended), or + /// the default `()` implementation uses the latest XCM version for all parachains. + type VersionWrapper: xcm::WrapVersion; + /// Something that provides the weight of this pallet. type WeightInfo: WeightInfo; } @@ -1499,28 +1507,19 @@ impl Pallet { ); HrmpOpenChannelRequestsList::::append(channel_id); - let notification_bytes = { - use parity_scale_codec::Encode as _; - use xcm::opaque::{latest::prelude::*, VersionedXcm}; - - VersionedXcm::from(Xcm(vec![HrmpNewChannelOpenRequest { - sender: u32::from(origin), - max_capacity: proposed_max_capacity, - max_message_size: proposed_max_message_size, - }])) - .encode() - }; - if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) = - dmp::Pallet::::queue_downward_message(&config, recipient, notification_bytes) - { - // this should never happen unless the max downward message size is configured to a - // jokingly small number. - log::error!( - target: "runtime::hrmp", - "sending 'init_open_channel::notification_bytes' failed." - ); - debug_assert!(false); - } + Self::send_to_para( + "init_open_channel", + &config, + recipient, + Self::wrap_notification(|| { + use xcm::opaque::latest::{prelude::*, Xcm}; + Xcm(vec![HrmpNewChannelOpenRequest { + sender: origin.into(), + max_capacity: proposed_max_capacity, + max_message_size: proposed_max_message_size, + }]) + }), + ); Ok(()) } @@ -1562,23 +1561,15 @@ impl Pallet { HrmpOpenChannelRequests::::insert(&channel_id, channel_req); HrmpAcceptedChannelRequestCount::::insert(&origin, accepted_cnt + 1); - let notification_bytes = { - use parity_scale_codec::Encode as _; - use xcm::opaque::{latest::prelude::*, VersionedXcm}; - let xcm = Xcm(vec![HrmpChannelAccepted { recipient: u32::from(origin) }]); - VersionedXcm::from(xcm).encode() - }; - if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) = - dmp::Pallet::::queue_downward_message(&config, sender, notification_bytes) - { - // this should never happen unless the max downward message size is configured to an - // jokingly small number. - log::error!( - target: "runtime::hrmp", - "sending 'accept_open_channel::notification_bytes' failed." - ); - debug_assert!(false); - } + Self::send_to_para( + "accept_open_channel", + &config, + sender, + Self::wrap_notification(|| { + use xcm::opaque::latest::{prelude::*, Xcm}; + Xcm(vec![HrmpChannelAccepted { recipient: origin.into() }]) + }), + ); Ok(()) } @@ -1633,30 +1624,22 @@ impl Pallet { HrmpCloseChannelRequestsList::::append(channel_id.clone()); let config = configuration::ActiveConfig::::get(); - let notification_bytes = { - use parity_scale_codec::Encode as _; - use xcm::opaque::{latest::prelude::*, VersionedXcm}; - - VersionedXcm::from(Xcm(vec![HrmpChannelClosing { - initiator: u32::from(origin), - sender: u32::from(channel_id.sender), - recipient: u32::from(channel_id.recipient), - }])) - .encode() - }; let opposite_party = if origin == channel_id.sender { channel_id.recipient } else { channel_id.sender }; - if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) = - dmp::Pallet::::queue_downward_message(&config, opposite_party, notification_bytes) - { - // this should never happen unless the max downward message size is configured to an - // jokingly small number. - log::error!( - target: "runtime::hrmp", - "sending 'close_channel::notification_bytes' failed." - ); - debug_assert!(false); - } + + Self::send_to_para( + "close_channel", + &config, + opposite_party, + Self::wrap_notification(|| { + use xcm::opaque::latest::{prelude::*, Xcm}; + Xcm(vec![HrmpChannelClosing { + initiator: origin.into(), + sender: channel_id.sender.into(), + recipient: channel_id.recipient.into(), + }]) + }), + ); Ok(()) } @@ -1875,3 +1858,56 @@ impl Pallet { } } } + +impl Pallet { + /// Wraps HRMP XCM notifications to the most suitable XCM version for the destination para. + /// If the XCM version is unknown, the latest XCM version is used as a best effort. + fn wrap_notification( + mut notification: impl FnMut() -> xcm::opaque::latest::opaque::Xcm, + ) -> impl FnOnce(ParaId) -> primitives::DownwardMessage { + use xcm::{ + opaque::VersionedXcm, + prelude::{Junction, Location}, + WrapVersion, + }; + + // Return a closure that can prepare notifications. + move |dest| { + // Attempt to wrap the notification for the destination parachain. + T::VersionWrapper::wrap_version( + &Location::new(0, [Junction::Parachain(dest.into())]), + notification(), + ) + .unwrap_or_else(|_| { + // As a best effort, if we cannot resolve the version, fallback to using the latest + // version. + VersionedXcm::from(notification()) + }) + .encode() + } + } + + /// Sends/enqueues notification to the destination parachain. + fn send_to_para( + log_label: &str, + config: &HostConfiguration>, + dest: ParaId, + notification_bytes_for: impl FnOnce(ParaId) -> primitives::DownwardMessage, + ) { + // prepare notification + let notification_bytes = notification_bytes_for(dest); + + // try to enqueue + if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) = + dmp::Pallet::::queue_downward_message(&config, dest, notification_bytes) + { + // this should never happen unless the max downward message size is configured to a + // jokingly small number. + log::error!( + target: "runtime::hrmp", + "sending '{log_label}::notification_bytes' failed." + ); + debug_assert!(false); + } + } +} diff --git a/polkadot/runtime/parachains/src/hrmp/tests.rs b/polkadot/runtime/parachains/src/hrmp/tests.rs index 2f767ab7e1b19d311f53d194638bb23066c37d31..acfaa8f2d290510d9d11ed85872c281e8b9c7d85 100644 --- a/polkadot/runtime/parachains/src/hrmp/tests.rs +++ b/polkadot/runtime/parachains/src/hrmp/tests.rs @@ -22,13 +22,13 @@ use super::*; use crate::{ mock::{ deregister_parachain, new_test_ext, register_parachain, register_parachain_with_balance, - Hrmp, MockGenesisConfig, Paras, ParasShared, RuntimeEvent as MockEvent, RuntimeOrigin, - System, Test, + Dmp, Hrmp, MockGenesisConfig, Paras, ParasShared, RuntimeEvent as MockEvent, RuntimeOrigin, + System, Test, TestUsesOnlyStoredVersionWrapper, }, shared, }; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; -use primitives::BlockNumber; +use primitives::{BlockNumber, InboundDownwardMessage}; use std::collections::BTreeMap; pub(crate) fn run_to_block(to: BlockNumber, new_session: Option>) { @@ -1004,3 +1004,140 @@ fn establish_channel_with_system_with_invalid_args() { Hrmp::assert_storage_consistency_exhaustive(); }); } + +#[test] +fn hrmp_notifications_works() { + use xcm::{ + opaque::{ + latest::{prelude::*, Xcm}, + VersionedXcm, + }, + IntoVersion, + }; + + let para_a = 2001.into(); + let para_a_origin: crate::Origin = 2001.into(); + let para_b = 2003.into(); + let para_b_origin: crate::Origin = 2003.into(); + + new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { + // We need both A & B to be registered and alive parachains. + register_parachain(para_a); + register_parachain(para_b); + run_to_block(5, Some(vec![4, 5])); + + // set XCM versions for wrapper + + // for para_a -> `None`, means we will use latest. + TestUsesOnlyStoredVersionWrapper::set_version( + Location::new(0, [Junction::Parachain(para_a.into())]), + None, + ); + // for para_b -> `Some(latest - 1)`, means we will use latest-1 XCM version. + let previous_version = XCM_VERSION - 1; + TestUsesOnlyStoredVersionWrapper::set_version( + Location::new(0, [Junction::Parachain(para_b.into())]), + Some(previous_version), + ); + + let assert_notification_for = |sent_at, para_id, expected| { + assert_eq!( + Dmp::dmq_contents(para_id), + vec![InboundDownwardMessage { sent_at, msg: expected }] + ); + }; + + // init open channel requests + assert_ok!(Hrmp::hrmp_init_open_channel(para_a_origin.clone().into(), para_b, 2, 8)); + assert_ok!(Hrmp::hrmp_init_open_channel(para_b_origin.clone().into(), para_a, 2, 8)); + Hrmp::assert_storage_consistency_exhaustive(); + + // check dmp notications + assert_notification_for( + 5, + para_b, + VersionedXcm::from(Xcm(vec![HrmpNewChannelOpenRequest { + sender: u32::from(para_a), + max_capacity: 2, + max_message_size: 8, + }])) + .into_version(previous_version) + .expect("compatible") + .encode(), + ); + assert_notification_for( + 5, + para_a, + VersionedXcm::from(Xcm(vec![HrmpNewChannelOpenRequest { + sender: u32::from(para_b), + max_capacity: 2, + max_message_size: 8, + }])) + .encode(), + ); + let _ = Dmp::prune_dmq(para_a, 1000); + let _ = Dmp::prune_dmq(para_b, 1000); + + // accept open channel requests + assert_ok!(Hrmp::hrmp_accept_open_channel(para_a_origin.clone().into(), para_b)); + assert_ok!(Hrmp::hrmp_accept_open_channel(para_b_origin.clone().into(), para_a)); + Hrmp::assert_storage_consistency_exhaustive(); + + // check dmp notications + assert_notification_for( + 5, + para_b, + VersionedXcm::from(Xcm(vec![HrmpChannelAccepted { recipient: u32::from(para_a) }])) + .into_version(previous_version) + .expect("compatible") + .encode(), + ); + assert_notification_for( + 5, + para_a, + VersionedXcm::from(Xcm(vec![HrmpChannelAccepted { recipient: u32::from(para_b) }])) + .encode(), + ); + let _ = Dmp::prune_dmq(para_a, 1000); + let _ = Dmp::prune_dmq(para_b, 1000); + + // On Block 6: session change - creates channel. + run_to_block(6, Some(vec![6])); + assert!(channel_exists(para_a, para_b)); + + // close channel requests + assert_ok!(Hrmp::hrmp_close_channel( + para_a_origin.into(), + HrmpChannelId { sender: para_a, recipient: para_b } + )); + assert_ok!(Hrmp::hrmp_close_channel( + para_b_origin.into(), + HrmpChannelId { sender: para_b, recipient: para_a } + )); + Hrmp::assert_storage_consistency_exhaustive(); + + // check dmp notications + assert_notification_for( + 6, + para_b, + VersionedXcm::from(Xcm(vec![HrmpChannelClosing { + initiator: u32::from(para_a), + sender: u32::from(para_a), + recipient: u32::from(para_b), + }])) + .into_version(previous_version) + .expect("compatible") + .encode(), + ); + assert_notification_for( + 6, + para_a, + VersionedXcm::from(Xcm(vec![HrmpChannelClosing { + initiator: u32::from(para_b), + sender: u32::from(para_b), + recipient: u32::from(para_a), + }])) + .encode(), + ); + }); +} diff --git a/polkadot/runtime/parachains/src/inclusion/mod.rs b/polkadot/runtime/parachains/src/inclusion/mod.rs index 31befefa32201b4bf343301c2956abcfbfb6a896..0c7274984085835e69e2b06b49e44f0ee7cc2e85 100644 --- a/polkadot/runtime/parachains/src/inclusion/mod.rs +++ b/polkadot/runtime/parachains/src/inclusion/mod.rs @@ -421,6 +421,7 @@ impl From for AcceptanceCheckErr { /// An error returned by [`Pallet::check_upward_messages`] that indicates a violation of one of /// acceptance criteria rules. #[cfg_attr(test, derive(PartialEq))] +#[allow(dead_code)] pub(crate) enum UmpAcceptanceCheckErr { /// The maximal number of messages that can be submitted in one batch was exceeded. MoreMessagesThanPermitted { sent: u32, permitted: u32 }, diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index 97a75d47ff775401ec549c1fcfd7a247664449fb..75b835b175414fc933d2915ea0ab1bf6bb8e30a6 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -50,9 +50,16 @@ use sp_runtime::{ transaction_validity::TransactionPriority, BuildStorage, FixedU128, Perbill, Permill, }; -use sp_std::collections::vec_deque::VecDeque; -use std::{cell::RefCell, collections::HashMap}; -use xcm::v4::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash}; +use sp_std::{ + cell::RefCell, + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, +}; +use std::collections::HashMap; +use xcm::{ + prelude::XcmVersion, + v4::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash}, + IntoVersion, VersionedXcm, WrapVersion, +}; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlockU32; @@ -93,7 +100,6 @@ where } parameter_types! { - pub const BlockHashCount: u32 = 250; pub static BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max( Weight::from_parts(4 * 1024 * 1024, u64::MAX), @@ -118,7 +124,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -247,16 +252,41 @@ impl crate::paras::Config for Test { impl crate::dmp::Config for Test {} parameter_types! { - pub const FirstMessageFactorPercent: u64 = 100; pub const DefaultChannelSizeAndCapacityWithSystem: (u32, u32) = (4, 1); } +thread_local! { + pub static VERSION_WRAPPER: RefCell>> = RefCell::new(BTreeMap::new()); +} +/// Mock implementation of the [`WrapVersion`] trait which wraps XCM only for known/stored XCM +/// versions in the `VERSION_WRAPPER`. +pub struct TestUsesOnlyStoredVersionWrapper; +impl WrapVersion for TestUsesOnlyStoredVersionWrapper { + fn wrap_version( + dest: &Location, + xcm: impl Into>, + ) -> Result, ()> { + match VERSION_WRAPPER.with(|r| r.borrow().get(dest).map_or(None, |v| *v)) { + Some(v) => xcm.into().into_version(v), + None => return Err(()), + } + } +} +impl TestUsesOnlyStoredVersionWrapper { + pub fn set_version(location: Location, version: Option) { + VERSION_WRAPPER.with(|r| { + let _ = r.borrow_mut().entry(location).and_modify(|v| *v = version).or_insert(version); + }); + } +} + impl crate::hrmp::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeEvent = RuntimeEvent; type ChannelManager = frame_system::EnsureRoot; type Currency = pallet_balances::Pallet; type DefaultChannelSizeAndCapacityWithSystem = DefaultChannelSizeAndCapacityWithSystem; + type VersionWrapper = TestUsesOnlyStoredVersionWrapper; type WeightInfo = crate::hrmp::TestWeightInfo; } diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index bbe19310f970ade37e25f5c1e2c983758c617412..c78f3e668b9c901fe2e9a71913b3b295307bf6ef 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true workspace = true [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } log = { workspace = true } serde = { workspace = true } @@ -95,6 +95,7 @@ pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-feat pallet-root-testing = { path = "../../../substrate/frame/root-testing", default-features = false } frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } +frame-metadata-hash-extension = { path = "../../../substrate/frame/metadata-hash-extension", default-features = false } frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } hex-literal = { version = "0.4.1" } @@ -134,6 +135,7 @@ std = [ "block-builder-api/std", "frame-benchmarking?/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", @@ -268,6 +270,7 @@ runtime-benchmarks = [ "sp-staking/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "frame-executive/try-runtime", @@ -323,6 +326,9 @@ try-runtime = [ "sp-runtime/try-runtime", ] +# Enable the metadata hash generation in the wasm builder. +metadata-hash = ["substrate-wasm-builder/metadata-hash"] + # Set timing constants (e.g. session period) to faster versions to speed up testing. fast-runtime = ["rococo-runtime-constants/fast-runtime"] @@ -331,4 +337,4 @@ runtime-metrics = ["runtime-parachains/runtime-metrics", "sp-io/with-tracing"] # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. -on-chain-release-build = ["sp-api/disable-logging"] +on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"] diff --git a/polkadot/runtime/rococo/build.rs b/polkadot/runtime/rococo/build.rs index 403c31ff21c70f679059fa5b7e65478d309ba6a3..7aae84cd5e0fedcb29265f98d40bcd9ccd83ae43 100644 --- a/polkadot/runtime/rococo/build.rs +++ b/polkadot/runtime/rococo/build.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -#[cfg(feature = "std")] +#[cfg(all(not(feature = "metadata-hash"), feature = "std"))] fn main() { substrate_wasm_builder::WasmBuilder::build_using_defaults(); @@ -24,5 +24,18 @@ fn main() { .build(); } +#[cfg(all(feature = "metadata-hash", feature = "std"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("ROC", 12) + .build(); + + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .set_file_name("fast_runtime_binary.rs") + .enable_feature("fast-runtime") + .enable_metadata_hash("ROC", 12) + .build(); +} + #[cfg(not(feature = "std"))] fn main() {} diff --git a/polkadot/runtime/rococo/constants/src/lib.rs b/polkadot/runtime/rococo/constants/src/lib.rs index 9209045364c28bc585c548d6d2b30176bd52bb20..89d5deb86f1a0ff78a05255f9f5f3bdaca8333a6 100644 --- a/polkadot/runtime/rococo/constants/src/lib.rs +++ b/polkadot/runtime/rococo/constants/src/lib.rs @@ -57,7 +57,7 @@ pub mod time { // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. // The choice of is done in accordance to the slot duration and expected target // block time, for safely resisting network delays of maximum two seconds. - // + // pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 287ae9937da4b86bffe21f4d5cb7cc526e76d015..f0cc7e046f29ce1f28c0e4df5e9d701b9d429df4 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -53,6 +53,7 @@ use runtime_common::{ use runtime_parachains::{ assigner_coretime as parachains_assigner_coretime, assigner_on_demand as parachains_assigner_on_demand, configuration as parachains_configuration, + configuration::ActiveConfigHrmpChannelSizeAndCapacityRatio, coretime, disputes as parachains_disputes, disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, @@ -133,7 +134,10 @@ use governance::{ pallet_custom_origins, AuctionAdmin, Fellows, GeneralAdmin, LeaseAdmin, Treasurer, TreasurySpender, }; -use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; #[cfg(test)] mod tests; @@ -161,10 +165,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("rococo"), impl_name: create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 24, + transaction_version: 26, state_version: 1, }; @@ -639,7 +643,9 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + frame_metadata_hash_extension::CheckMetadataHash::new(true), ); + let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); @@ -1033,7 +1039,7 @@ impl pallet_message_queue::Config for Runtime { impl parachains_dmp::Config for Runtime {} parameter_types! { - pub const DefaultChannelSizeAndCapacityWithSystem: (u32, u32) = (51200, 500); + pub const HrmpChannelSizeAndCapacityWithSystemRatio: Percent = Percent::from_percent(100); } impl parachains_hrmp::Config for Runtime { @@ -1041,7 +1047,11 @@ impl parachains_hrmp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ChannelManager = EnsureRoot; type Currency = Balances; - type DefaultChannelSizeAndCapacityWithSystem = DefaultChannelSizeAndCapacityWithSystem; + type DefaultChannelSizeAndCapacityWithSystem = ActiveConfigHrmpChannelSizeAndCapacityRatio< + Runtime, + HrmpChannelSizeAndCapacityWithSystemRatio, + >; + type VersionWrapper = crate::XcmPallet; type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo; } @@ -1520,6 +1530,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. @@ -1759,26 +1770,34 @@ sp_api::impl_runtime_apis! { } } - impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { - if !matches!(xcm_version, 3 | 4) { - return Err(XcmPaymentApiError::UnhandledXcmVersion); - } - Ok([VersionedAssetId::V4(xcm_config::TokenLocation::get().into())] + let acceptable = vec![ + // native token + VersionedAssetId::from(AssetId(xcm_config::TokenLocation::get())) + ]; + + Ok(acceptable .into_iter() .filter_map(|asset| asset.into_version(xcm_version).ok()) .collect()) } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { - let local_asset = VersionedAssetId::V4(xcm_config::TokenLocation::get().into()); - let asset = asset - .into_version(4) - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - if asset != local_asset { return Err(XcmPaymentApiError::AssetNotFound); } - - Ok(WeightToFee::weight_to_fee(&weight)) + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == xcm_config::TokenLocation::get() => { + // for native token + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } } fn query_xcm_weight(message: VersionedXcm<()>) -> Result { @@ -1790,6 +1809,66 @@ sp_api::impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm_executor::RecordXcm; + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let xcm: Xcm = xcm.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); + let result = xcm_executor::XcmExecutor::::prepare_and_execute( + origin_location, + xcm, + &mut hash, + Weight::MAX, // Max limit available for execution. + Weight::zero(), + ); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } + impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) @@ -2058,7 +2137,7 @@ sp_api::impl_runtime_apis! { fn generate_proof( block_numbers: Vec, best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { + ) -> Result<(Vec, mmr::LeafProof), mmr::Error> { Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( @@ -2072,7 +2151,7 @@ sp_api::impl_runtime_apis! { ) } - fn verify_proof(leaves: Vec, proof: mmr::Proof) + fn verify_proof(leaves: Vec, proof: mmr::LeafProof) -> Result<(), mmr::Error> { let leaves = leaves.into_iter().map(|leaf| @@ -2085,7 +2164,7 @@ sp_api::impl_runtime_apis! { fn verify_proof_stateless( root: mmr::Hash, leaves: Vec, - proof: mmr::Proof + proof: mmr::LeafProof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); pallet_mmr::verify_leaves_proof::(root, nodes, proof) diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs index 1b0ae1eeece41b10aff0c65181fe757cfdc4dd0e..d37bb9369c688b596b22c25da25463719c428e32 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 44_127_000 picoseconds. - Weight::from_parts(45_099_000, 0) + // Minimum execution time: 44_771_000 picoseconds. + Weight::from_parts(45_635_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_265_000 picoseconds. - Weight::from_parts(35_083_000, 0) + // Minimum execution time: 34_225_000 picoseconds. + Weight::from_parts(35_622_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_189_000 picoseconds. - Weight::from_parts(12_655_000, 0) + // Minimum execution time: 12_443_000 picoseconds. + Weight::from_parts(12_944_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_910_000 picoseconds. - Weight::from_parts(17_474_000, 0) + // Minimum execution time: 17_189_000 picoseconds. + Weight::from_parts(17_922_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 45_212_000 picoseconds. - Weight::from_parts(46_320_000, 0) + // Minimum execution time: 45_925_000 picoseconds. + Weight::from_parts(47_021_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_500_000 picoseconds. - Weight::from_parts(43_991_000, 0) + // Minimum execution time: 43_775_000 picoseconds. + Weight::from_parts(44_955_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_197_000 picoseconds. - Weight::from_parts(15_749_000, 0) + // Minimum execution time: 15_358_000 picoseconds. + Weight::from_parts(15_958_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -140,11 +140,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_414_000 picoseconds. - Weight::from_parts(14_685_000, 0) + // Minimum execution time: 14_283_000 picoseconds. + Weight::from_parts(14_888_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 7_918 - .saturating_add(Weight::from_parts(13_095_420, 0).saturating_mul(u.into())) + // Standard Error: 8_164 + .saturating_add(Weight::from_parts(13_730_103, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -153,8 +153,24 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_239_000 picoseconds. - Weight::from_parts(5_617_000, 0) + // Minimum execution time: 5_167_000 picoseconds. + Weight::from_parts(5_505_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 27_587_000 picoseconds. + Weight::from_parts(28_493_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_023_000 picoseconds. + Weight::from_parts(18_694_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs index 6cca9b9320a6558ae6f1a5192e615d62b4acf8f4..706653aeb7692188103102bbe8aba72bbd6acb30 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -56,8 +56,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 41_978_000 picoseconds. - Weight::from_parts(42_989_000, 0) + // Minimum execution time: 42_331_000 picoseconds. + Weight::from_parts(43_215_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -70,8 +70,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 32_250_000 picoseconds. - Weight::from_parts(33_074_000, 0) + // Minimum execution time: 32_674_000 picoseconds. + Weight::from_parts(33_564_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -82,8 +82,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3577` - // Minimum execution time: 9_906_000 picoseconds. - Weight::from_parts(10_397_000, 0) + // Minimum execution time: 9_813_000 picoseconds. + Weight::from_parts(10_111_000, 0) .saturating_add(Weight::from_parts(0, 3577)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -96,8 +96,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 16_298_000 picoseconds. - Weight::from_parts(17_115_000, 0) + // Minimum execution time: 16_467_000 picoseconds. + Weight::from_parts(17_088_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -110,8 +110,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `6196` - // Minimum execution time: 43_283_000 picoseconds. - Weight::from_parts(44_033_000, 0) + // Minimum execution time: 43_846_000 picoseconds. + Weight::from_parts(45_059_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +124,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 40_564_000 picoseconds. - Weight::from_parts(41_597_000, 0) + // Minimum execution time: 41_260_000 picoseconds. + Weight::from_parts(42_367_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -138,8 +138,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 15_018_000 picoseconds. - Weight::from_parts(15_532_000, 0) + // Minimum execution time: 14_914_000 picoseconds. + Weight::from_parts(15_631_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -154,11 +154,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (256 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_470_000 picoseconds. - Weight::from_parts(14_828_000, 0) + // Minimum execution time: 14_630_000 picoseconds. + Weight::from_parts(14_924_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 15_515 - .saturating_add(Weight::from_parts(14_505_553, 0).saturating_mul(u.into())) + // Standard Error: 15_311 + .saturating_add(Weight::from_parts(14_920_201, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -167,8 +167,32 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_277_000 picoseconds. - Weight::from_parts(5_628_000, 0) + // Minimum execution time: 5_193_000 picoseconds. + Weight::from_parts(5_403_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) + /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `3577` + // Minimum execution time: 27_002_000 picoseconds. + Weight::from_parts(27_785_000, 0) + .saturating_add(Weight::from_parts(0, 3577)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) + /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `3577` + // Minimum execution time: 17_533_000 picoseconds. + Weight::from_parts(18_338_000, 0) + .saturating_add(Weight::from_parts(0, 3577)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs index 97b84155b36a6adb2258a714e65bf5c70bc9aa50..572ecc7d4110f0335b18a3c276032b4f6d285db5 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs @@ -16,25 +16,26 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --pallet=runtime_parachains::hrmp // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_hrmp.rs +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=runtime_parachains::hrmp +// --chain=rococo-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,105 +48,103 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::hrmp`. pub struct WeightInfo(PhantomData); impl runtime_parachains::hrmp::WeightInfo for WeightInfo { - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_init_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `704` - // Estimated: `6644` - // Minimum execution time: 41_564_000 picoseconds. - Weight::from_parts(42_048_000, 0) - .saturating_add(Weight::from_parts(0, 6644)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `488` + // Estimated: `3953` + // Minimum execution time: 37_574_000 picoseconds. + Weight::from_parts(38_789_000, 0) + .saturating_add(Weight::from_parts(0, 3953)) + .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_accept_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `936` - // Estimated: `4401` - // Minimum execution time: 43_570_000 picoseconds. - Weight::from_parts(44_089_000, 0) - .saturating_add(Weight::from_parts(0, 4401)) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `478` + // Estimated: `3943` + // Minimum execution time: 34_560_000 picoseconds. + Weight::from_parts(35_760_000, 0) + .saturating_add(Weight::from_parts(0, 3943)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_close_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `807` - // Estimated: `4272` - // Minimum execution time: 36_594_000 picoseconds. - Weight::from_parts(37_090_000, 0) - .saturating_add(Weight::from_parts(0, 4272)) + // Measured: `591` + // Estimated: `4056` + // Minimum execution time: 35_367_000 picoseconds. + Weight::from_parts(37_000_000, 0) + .saturating_add(Weight::from_parts(0, 4056)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:254 w:254) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:254) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:254 w:254) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:254) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 127]`. /// The range of component `e` is `[0, 127]`. fn force_clean_hrmp(i: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `264 + e * (100 ±0) + i * (100 ±0)` - // Estimated: `3726 + e * (2575 ±0) + i * (2575 ±0)` - // Minimum execution time: 1_085_140_000 picoseconds. - Weight::from_parts(1_100_901_000, 0) - .saturating_add(Weight::from_parts(0, 3726)) - // Standard Error: 98_982 - .saturating_add(Weight::from_parts(3_229_112, 0).saturating_mul(i.into())) - // Standard Error: 98_982 - .saturating_add(Weight::from_parts(3_210_944, 0).saturating_mul(e.into())) + // Measured: `297 + e * (100 ±0) + i * (100 ±0)` + // Estimated: `3759 + e * (2575 ±0) + i * (2575 ±0)` + // Minimum execution time: 1_134_420_000 picoseconds. + Weight::from_parts(1_144_822_000, 0) + .saturating_add(Weight::from_parts(0, 3759)) + // Standard Error: 101_380 + .saturating_add(Weight::from_parts(3_325_898, 0).saturating_mul(i.into())) + // Standard Error: 101_380 + .saturating_add(Weight::from_parts(3_338_565, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(e.into()))) @@ -155,139 +154,141 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf .saturating_add(Weight::from_parts(0, 2575).saturating_mul(e.into())) .saturating_add(Weight::from_parts(0, 2575).saturating_mul(i.into())) } - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:256 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:256 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `779 + c * (136 ±0)` - // Estimated: `2234 + c * (5086 ±0)` - // Minimum execution time: 10_497_000 picoseconds. - Weight::from_parts(6_987_455, 0) - .saturating_add(Weight::from_parts(0, 2234)) - // Standard Error: 18_540 - .saturating_add(Weight::from_parts(18_788_534, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Measured: `525 + c * (136 ±0)` + // Estimated: `1980 + c * (5086 ±0)` + // Minimum execution time: 5_652_000 picoseconds. + Weight::from_parts(2_857_824, 0) + .saturating_add(Weight::from_parts(0, 1980)) + // Standard Error: 26_044 + .saturating_add(Weight::from_parts(20_088_467, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 5086).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:128 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:128) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:128 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:0 w:128) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `335 + c * (124 ±0)` - // Estimated: `1795 + c * (2600 ±0)` - // Minimum execution time: 6_575_000 picoseconds. - Weight::from_parts(1_228_642, 0) - .saturating_add(Weight::from_parts(0, 1795)) - // Standard Error: 14_826 - .saturating_add(Weight::from_parts(11_604_038, 0).saturating_mul(c.into())) + // Measured: `368 + c * (124 ±0)` + // Estimated: `1828 + c * (2600 ±0)` + // Minimum execution time: 4_692_000 picoseconds. + Weight::from_parts(6_637_146, 0) + .saturating_add(Weight::from_parts(0, 1828)) + // Standard Error: 10_238 + .saturating_add(Weight::from_parts(12_201_629, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2600).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1026 + c * (13 ±0)` - // Estimated: `4295 + c * (15 ±0)` - // Minimum execution time: 22_301_000 picoseconds. - Weight::from_parts(26_131_473, 0) - .saturating_add(Weight::from_parts(0, 4295)) - // Standard Error: 830 - .saturating_add(Weight::from_parts(49_448, 0).saturating_mul(c.into())) + // Measured: `1059 + c * (13 ±0)` + // Estimated: `4328 + c * (15 ±0)` + // Minimum execution time: 18_920_000 picoseconds. + Weight::from_parts(27_314_843, 0) + .saturating_add(Weight::from_parts(0, 4328)) + // Standard Error: 2_127 + .saturating_add(Weight::from_parts(90_200, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 15).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `243 + c * (63 ±0)` - // Estimated: `1722 + c * (2538 ±0)` - // Minimum execution time: 5_234_000 picoseconds. - Weight::from_parts(7_350_270, 0) - .saturating_add(Weight::from_parts(0, 1722)) - // Standard Error: 3_105 - .saturating_add(Weight::from_parts(2_981_935, 0).saturating_mul(c.into())) + // Measured: `276 + c * (63 ±0)` + // Estimated: `1755 + c * (2538 ±0)` + // Minimum execution time: 3_502_000 picoseconds. + Weight::from_parts(6_477_323, 0) + .saturating_add(Weight::from_parts(0, 1755)) + // Standard Error: 3_416 + .saturating_add(Weight::from_parts(3_149_674, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2538).saturating_mul(c.into())) } - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - fn force_open_hrmp_channel(_c: u32, ) -> Weight { + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `c` is `[0, 1]`. + fn force_open_hrmp_channel(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `704` - // Estimated: `6644` - // Minimum execution time: 55_611_000 picoseconds. - Weight::from_parts(56_488_000, 0) - .saturating_add(Weight::from_parts(0, 6644)) + // Measured: `488 + c * (235 ±0)` + // Estimated: `6428 + c * (235 ±0)` + // Minimum execution time: 56_234_000 picoseconds. + Weight::from_parts(58_259_646, 0) + .saturating_add(Weight::from_parts(0, 6428)) + // Standard Error: 160_596 + .saturating_add(Weight::from_parts(11_178_353, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(8)) + .saturating_add(Weight::from_parts(0, 235).saturating_mul(c.into())) } /// Storage: `Paras::ParaLifecycles` (r:1 w:0) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -301,6 +302,8 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) @@ -311,34 +314,56 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_system_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `6357` - // Minimum execution time: 629_674_000 picoseconds. - Weight::from_parts(640_174_000, 0) - .saturating_add(Weight::from_parts(0, 6357)) - .saturating_add(T::DbWeight::get().reads(12)) + // Measured: `488` + // Estimated: `6428` + // Minimum execution time: 56_035_000 picoseconds. + Weight::from_parts(58_217_000, 0) + .saturating_add(Weight::from_parts(0, 6428)) + .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(8)) } /// Storage: `Hrmp::HrmpChannels` (r:1 w:1) /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) fn poke_channel_deposits() -> Weight { // Proof Size summary in bytes: - // Measured: `263` - // Estimated: `3728` - // Minimum execution time: 173_371_000 picoseconds. - Weight::from_parts(175_860_000, 0) - .saturating_add(Weight::from_parts(0, 3728)) + // Measured: `296` + // Estimated: `3761` + // Minimum execution time: 11_477_000 picoseconds. + Weight::from_parts(11_845_000, 0) + .saturating_add(Weight::from_parts(0, 3761)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Paras::ParaLifecycles` (r:2 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:2 w:2) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:2 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:2 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:2 w:2) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:2 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:2 w:2) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_channel_with_system() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `6357` - // Minimum execution time: 629_674_000 picoseconds. - Weight::from_parts(640_174_000, 0) - .saturating_add(Weight::from_parts(0, 6357)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(8)) + // Measured: `488` + // Estimated: `6428` + // Minimum execution time: 95_305_000 picoseconds. + Weight::from_parts(97_323_000, 0) + .saturating_add(Weight::from_parts(0, 6428)) + .saturating_add(T::DbWeight::get().reads(21)) + .saturating_add(T::DbWeight::get().writes(11)) } } diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index c7063bd7ad616c2e5cb7b2e3f8c397087e522c33..decbc795143f006ee50cc98d860e795165269cf5 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -224,6 +224,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } parameter_types! { diff --git a/polkadot/runtime/test-runtime/Cargo.toml b/polkadot/runtime/test-runtime/Cargo.toml index 6552ed4ef8aeaa2e36aa1f410879cc4cf0eeaf07..596cc974c82599289eb9203704d37af81811b004 100644 --- a/polkadot/runtime/test-runtime/Cargo.toml +++ b/polkadot/runtime/test-runtime/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true workspace = true [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { workspace = true } diff --git a/polkadot/runtime/test-runtime/constants/src/lib.rs b/polkadot/runtime/test-runtime/constants/src/lib.rs index 77c83b063cf0f8fb7771545faa074b315fa75a03..2422762ca38e925cf9666f1c42e2aa10cf70dd90 100644 --- a/polkadot/runtime/test-runtime/constants/src/lib.rs +++ b/polkadot/runtime/test-runtime/constants/src/lib.rs @@ -45,7 +45,7 @@ pub mod time { // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. // The choice of is done in accordance to the slot duration and expected target // block time, for safely resisting network delays of maximum two seconds. - // + // pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); } diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 87becf73cb745af81ad84312a493cef5a028c698..9eb0fcca6678b234ab2b744e3fbf2f6f837cbdbe 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -29,7 +29,9 @@ use sp_std::{ use polkadot_runtime_parachains::{ assigner_parachains as parachains_assigner_parachains, - configuration as parachains_configuration, disputes as parachains_disputes, + configuration as parachains_configuration, + configuration::ActiveConfigHrmpChannelSizeAndCapacityRatio, + disputes as parachains_disputes, disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras, @@ -78,7 +80,7 @@ use sp_runtime::{ SaturatedConversion, StaticLookup, Verify, }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, + ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent, }; use sp_staking::SessionIndex; #[cfg(any(feature = "std", test))] @@ -556,8 +558,7 @@ parameter_types! { impl parachains_dmp::Config for Runtime {} parameter_types! { - pub const FirstMessageFactorPercent: u64 = 100; - pub const DefaultChannelSizeAndCapacityWithSystem: (u32, u32) = (51200, 500); + pub const HrmpChannelSizeAndCapacityWithSystemRatio: Percent = Percent::from_percent(100); } impl parachains_hrmp::Config for Runtime { @@ -565,7 +566,11 @@ impl parachains_hrmp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ChannelManager = frame_system::EnsureRoot; type Currency = Balances; - type DefaultChannelSizeAndCapacityWithSystem = DefaultChannelSizeAndCapacityWithSystem; + type DefaultChannelSizeAndCapacityWithSystem = ActiveConfigHrmpChannelSizeAndCapacityRatio< + Runtime, + HrmpChannelSizeAndCapacityWithSystemRatio, + >; + type VersionWrapper = crate::Xcm; type WeightInfo = parachains_hrmp::TestWeightInfo; } @@ -1039,11 +1044,11 @@ sp_api::impl_runtime_apis! { fn generate_proof( _block_numbers: Vec, _best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { + ) -> Result<(Vec, mmr::LeafProof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_proof(_leaves: Vec, _proof: mmr::Proof) + fn verify_proof(_leaves: Vec, _proof: mmr::LeafProof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) @@ -1052,7 +1057,7 @@ sp_api::impl_runtime_apis! { fn verify_proof_stateless( _root: Hash, _leaves: Vec, - _proof: mmr::Proof + _proof: mmr::LeafProof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index 8411b79f2529d8e2d26815bd9ab806457e4ca99b..fc3d0dc42a3b93408f15c8363b631aa9761cbe36 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -156,6 +156,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } impl pallet_xcm::Config for crate::Runtime { diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index d726adfb8e6e439edd2b5f378f5b5160ac70e6be..56623272be82e2fd355550b63777477f267ac7c6 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } log = { workspace = true } rustc-hex = { version = "2.1.0", default-features = false } @@ -45,6 +45,7 @@ sp-npos-elections = { path = "../../../substrate/primitives/npos-elections", def frame-election-provider-support = { path = "../../../substrate/frame/election-provider-support", default-features = false } frame-executive = { path = "../../../substrate/frame/executive", default-features = false } +frame-metadata-hash-extension = { path = "../../../substrate/frame/metadata-hash-extension", default-features = false } frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["experimental", "tuples-96"] } frame-system = { path = "../../../substrate/frame/system", default-features = false } frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false } @@ -82,6 +83,7 @@ pallet-society = { path = "../../../substrate/frame/society", default-features = pallet-staking = { path = "../../../substrate/frame/staking", default-features = false } pallet-staking-reward-curve = { package = "pallet-staking-reward-curve", path = "../../../substrate/frame/staking/reward-curve" } pallet-staking-runtime-api = { path = "../../../substrate/frame/staking/runtime-api", default-features = false } +pallet-delegated-staking = { path = "../../../substrate/frame/delegated-staking", default-features = false } pallet-state-trie-migration = { path = "../../../substrate/frame/state-trie-migration", default-features = false } pallet-sudo = { path = "../../../substrate/frame/sudo", default-features = false } pallet-timestamp = { path = "../../../substrate/frame/timestamp", default-features = false } @@ -141,6 +143,7 @@ std = [ "frame-benchmarking?/std", "frame-election-provider-support/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", @@ -159,6 +162,7 @@ std = [ "pallet-beefy/std", "pallet-collective/std", "pallet-conviction-voting/std", + "pallet-delegated-staking/std", "pallet-democracy/std", "pallet-election-provider-multi-phase/std", "pallet-election-provider-support-benchmarking?/std", @@ -242,6 +246,7 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-conviction-voting/runtime-benchmarks", + "pallet-delegated-staking/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-election-provider-multi-phase/runtime-benchmarks", "pallet-election-provider-support-benchmarking/runtime-benchmarks", @@ -283,6 +288,7 @@ runtime-benchmarks = [ "sp-staking/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "frame-election-provider-support/try-runtime", @@ -301,6 +307,7 @@ try-runtime = [ "pallet-beefy/try-runtime", "pallet-collective/try-runtime", "pallet-conviction-voting/try-runtime", + "pallet-delegated-staking/try-runtime", "pallet-democracy/try-runtime", "pallet-election-provider-multi-phase/try-runtime", "pallet-elections-phragmen/try-runtime", @@ -337,6 +344,9 @@ try-runtime = [ "sp-runtime/try-runtime", ] +# Enable the metadata hash generation in the wasm builder. +metadata-hash = ["substrate-wasm-builder/metadata-hash"] + # Set timing constants (e.g. session period) to faster versions to speed up testing. fast-runtime = [] @@ -345,4 +355,4 @@ runtime-metrics = ["runtime-parachains/runtime-metrics", "sp-io/with-tracing"] # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. -on-chain-release-build = ["sp-api/disable-logging"] +on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"] diff --git a/polkadot/runtime/westend/build.rs b/polkadot/runtime/westend/build.rs index 0b3e12c78c746517a32538c8c1e5f9da63747fc5..8ff3a4fb9112c670882cd9794d6291d74cee194f 100644 --- a/polkadot/runtime/westend/build.rs +++ b/polkadot/runtime/westend/build.rs @@ -14,8 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use substrate_wasm_builder::WasmBuilder; +#[cfg(all(not(feature = "metadata-hash"), feature = "std"))] +fn main() { + substrate_wasm_builder::WasmBuilder::build_using_defaults(); +} +#[cfg(all(feature = "metadata-hash", feature = "std"))] fn main() { - WasmBuilder::build_using_defaults(); + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("WND", 12) + .build(); } + +#[cfg(not(feature = "std"))] +fn main() {} diff --git a/polkadot/runtime/westend/constants/src/lib.rs b/polkadot/runtime/westend/constants/src/lib.rs index c98f4b114fd88241dea1e2e5ffcf694848448007..1a4c1f3110614508cf3d934fe82cd5884f49d365 100644 --- a/polkadot/runtime/westend/constants/src/lib.rs +++ b/polkadot/runtime/westend/constants/src/lib.rs @@ -52,7 +52,7 @@ pub mod time { // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. // The choice of is done in accordance to the slot duration and expected target // block time, for safely resisting network delays of maximum two seconds. - // + // pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 7125f5d34c40860ccced972d47530582ccd3d289..4bf132d82c9634609cc4f9c4c3a2790ca4bf36f7 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -68,6 +68,7 @@ use runtime_common::{ use runtime_parachains::{ assigner_coretime as parachains_assigner_coretime, assigner_on_demand as parachains_assigner_on_demand, configuration as parachains_configuration, + configuration::ActiveConfigHrmpChannelSizeAndCapacityRatio, coretime, disputes as parachains_disputes, disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, @@ -107,7 +108,10 @@ use xcm::{ }; use xcm_builder::PayOverXcm; -use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; @@ -153,10 +157,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westend"), impl_name: create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 1_010_000, + spec_version: 1_012_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 24, + transaction_version: 26, state_version: 1, }; @@ -643,7 +647,7 @@ impl pallet_staking::Config for Runtime { type HistoryDepth = frame_support::traits::ConstU32<84>; type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch; type BenchmarkingConfig = runtime_common::StakingBenchmarkingConfig; - type EventListeners = NominationPools; + type EventListeners = (NominationPools, DelegatedStaking); type WeightInfo = weights::pallet_staking::WeightInfo; type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; } @@ -793,6 +797,7 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + frame_metadata_hash_extension::CheckMetadataHash::::new(true), ); let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { @@ -1163,7 +1168,7 @@ impl pallet_message_queue::Config for Runtime { impl parachains_dmp::Config for Runtime {} parameter_types! { - pub const DefaultChannelSizeAndCapacityWithSystem: (u32, u32) = (4096, 4); + pub const HrmpChannelSizeAndCapacityWithSystemRatio: Percent = Percent::from_percent(100); } impl parachains_hrmp::Config for Runtime { @@ -1171,7 +1176,11 @@ impl parachains_hrmp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ChannelManager = EnsureRoot; type Currency = Balances; - type DefaultChannelSizeAndCapacityWithSystem = DefaultChannelSizeAndCapacityWithSystem; + type DefaultChannelSizeAndCapacityWithSystem = ActiveConfigHrmpChannelSizeAndCapacityRatio< + Runtime, + HrmpChannelSizeAndCapacityWithSystemRatio, + >; + type VersionWrapper = crate::XcmPallet; type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo; } @@ -1351,7 +1360,8 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = Staking; + type StakeAdapter = + pallet_nomination_pools::adapter::DelegateStake; type PostUnbondingPoolsWindow = ConstU32<4>; type MaxMetadataLen = ConstU32<256>; // we use the same number of allowed unlocking chunks as with staking. @@ -1361,6 +1371,21 @@ impl pallet_nomination_pools::Config for Runtime { type AdminOrigin = EitherOf, StakingAdmin>; } +parameter_types! { + pub const DelegatedStakingPalletId: PalletId = PalletId(*b"py/dlstk"); + pub const SlashRewardFraction: Perbill = Perbill::from_percent(1); +} + +impl pallet_delegated_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = DelegatedStakingPalletId; + type Currency = Balances; + type OnSlash = (); + type SlashRewardFraction = SlashRewardFraction; + type RuntimeHoldReason = RuntimeHoldReason; + type CoreStaking = Staking; +} + impl pallet_root_testing::Config for Runtime { type RuntimeEvent = RuntimeEvent; } @@ -1509,6 +1534,10 @@ mod runtime { #[runtime::pallet_index(37)] pub type Treasury = pallet_treasury; + // Staking extension for delegation + #[runtime::pallet_index(38)] + pub type DelegatedStaking = pallet_delegated_staking; + // Parachains pallets. Start indices at 40 to leave room. #[runtime::pallet_index(41)] pub type ParachainsOrigin = parachains_origin; @@ -1609,13 +1638,15 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + frame_metadata_hash_extension::CheckMetadataHash, ); -pub struct NominationPoolsMigrationV4OldPallet; -impl Get for NominationPoolsMigrationV4OldPallet { - fn get() -> Perbill { - Perbill::from_percent(100) - } +parameter_types! { + // This is the max pools that will be migrated in the runtime upgrade. Westend has more pools + // than this, but we want to emulate some non migrated pools. In prod runtimes, if weight is not + // a concern, it is recommended to set to (existing pools + 10) to also account for any new + // pools getting created before the migration is actually executed. + pub const MaxPoolsToMigrate: u32 = 250; } /// All migrations that will run on the next runtime upgrade. @@ -1648,7 +1679,15 @@ pub mod migrations { } /// Unreleased migrations. Add new ones here: - pub type Unreleased = (pallet_staking::migrations::v15::MigrateV14ToV15,); + pub type Unreleased = ( + // Migrate NominationPools to `DelegateStake` adapter. This is unversioned upgrade and + // should not be applied yet in Kusama/Polkadot. + pallet_nomination_pools::migration::unversioned::DelegationStakeMigration< + Runtime, + MaxPoolsToMigrate, + >, + pallet_staking::migrations::v15::MigrateV14ToV15, + ); } /// Unchecked extrinsic type as expected by this runtime. @@ -2005,7 +2044,7 @@ sp_api::impl_runtime_apis! { fn generate_proof( block_numbers: Vec, best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { + ) -> Result<(Vec, mmr::LeafProof), mmr::Error> { Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( @@ -2019,7 +2058,7 @@ sp_api::impl_runtime_apis! { ) } - fn verify_proof(leaves: Vec, proof: mmr::Proof) + fn verify_proof(leaves: Vec, proof: mmr::LeafProof) -> Result<(), mmr::Error> { let leaves = leaves.into_iter().map(|leaf| @@ -2032,7 +2071,7 @@ sp_api::impl_runtime_apis! { fn verify_proof_stateless( root: mmr::Hash, leaves: Vec, - proof: mmr::Proof + proof: mmr::LeafProof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); pallet_mmr::verify_leaves_proof::(root, nodes, proof) @@ -2193,26 +2232,34 @@ sp_api::impl_runtime_apis! { } } - impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { + impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { - if !matches!(xcm_version, 3 | 4) { - return Err(XcmPaymentApiError::UnhandledXcmVersion); - } - Ok([VersionedAssetId::V4(xcm_config::TokenLocation::get().into())] + let acceptable = vec![ + // native token + VersionedAssetId::from(AssetId(xcm_config::TokenLocation::get())) + ]; + + Ok(acceptable .into_iter() .filter_map(|asset| asset.into_version(xcm_version).ok()) .collect()) } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { - let local_asset = VersionedAssetId::V4(xcm_config::TokenLocation::get().into()); - let asset = asset - .into_version(4) - .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - - if asset != local_asset { return Err(XcmPaymentApiError::AssetNotFound); } - - Ok(WeightToFee::weight_to_fee(&weight)) + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == xcm_config::TokenLocation::get() => { + // for native token + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!"); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!(target: "xcm::xcm_fee_payment_runtime_api", "query_weight_to_asset_fee - failed to convert asset: {asset:?}!"); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } } fn query_xcm_weight(message: VersionedXcm<()>) -> Result { @@ -2224,6 +2271,66 @@ sp_api::impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::dry_run::XcmDryRunApi for Runtime { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + use xcm_executor::RecordXcm; + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm) -> Result, XcmDryRunApiError> { + use xcm_builder::InspectMessageQueues; + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let xcm: Xcm = xcm.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); + let result = xcm_executor::XcmExecutor::::prepare_and_execute( + origin_location, + xcm, + &mut hash, + Weight::MAX, // Max limit available for execution. + Weight::zero(), + ); + let forwarded_xcms = xcm_config::XcmRouter::get_messages(); + let events: Vec = System::read_events_no_consensus().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } + impl pallet_nomination_pools_runtime_api::NominationPoolsApi< Block, AccountId, diff --git a/polkadot/runtime/westend/src/weights/pallet_balances.rs b/polkadot/runtime/westend/src/weights/pallet_balances.rs index 25626e940209d50859a57dee60f483b15a8db257..5e91f31920cab122d044465fa6c3538053f4acf5 100644 --- a/polkadot/runtime/westend/src/weights/pallet_balances.rs +++ b/polkadot/runtime/westend/src/weights/pallet_balances.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_680_000 picoseconds. - Weight::from_parts(45_012_000, 0) + // Minimum execution time: 43_248_000 picoseconds. + Weight::from_parts(43_872_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_038_000 picoseconds. - Weight::from_parts(35_771_000, 0) + // Minimum execution time: 33_990_000 picoseconds. + Weight::from_parts(34_693_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_609_000 picoseconds. - Weight::from_parts(13_142_000, 0) + // Minimum execution time: 12_681_000 picoseconds. + Weight::from_parts(13_183_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_533_000 picoseconds. - Weight::from_parts(18_061_000, 0) + // Minimum execution time: 17_474_000 picoseconds. + Weight::from_parts(18_063_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 45_278_000 picoseconds. - Weight::from_parts(46_670_000, 0) + // Minimum execution time: 45_699_000 picoseconds. + Weight::from_parts(46_099_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_125_000 picoseconds. - Weight::from_parts(43_925_000, 0) + // Minimum execution time: 42_453_000 picoseconds. + Weight::from_parts(43_133_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_580_000 picoseconds. - Weight::from_parts(16_023_000, 0) + // Minimum execution time: 15_066_000 picoseconds. + Weight::from_parts(15_605_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -139,11 +139,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_868_000 picoseconds. - Weight::from_parts(15_130_000, 0) + // Minimum execution time: 14_180_000 picoseconds. + Weight::from_parts(14_598_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 10_719 - .saturating_add(Weight::from_parts(13_394_926, 0).saturating_mul(u.into())) + // Standard Error: 13_221 + .saturating_add(Weight::from_parts(13_422_901, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -152,8 +152,24 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_174_000 picoseconds. - Weight::from_parts(5_457_000, 0) + // Minimum execution time: 5_130_000 picoseconds. + Weight::from_parts(5_257_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 27_328_000 picoseconds. + Weight::from_parts(27_785_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 17_797_000 picoseconds. + Weight::from_parts(18_103_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs index 6aa5ddd1ec8fb5251ac6bbd5059938e4bad93b22..35eef199fb7a974f7665a83c09318ee06b37fea2 100644 --- a/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs +++ b/polkadot/runtime/westend/src/weights/pallet_nomination_pools.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_nomination_pools` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-dcu62vjg-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -54,7 +54,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) /// Storage: `NominationPools::BondedPools` (r:1 w:1) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) + /// Storage: `Staking::Bonded` (r:2 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) @@ -62,7 +62,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `NominationPools::MaxPoolMembersPerPool` (r:1 w:0) /// Proof: `NominationPools::MaxPoolMembersPerPool` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -70,10 +70,16 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:2 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListNodes` (r:3 w:3) /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListBags` (r:2 w:2) @@ -82,13 +88,13 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3355` + // Measured: `3606` // Estimated: `8877` - // Minimum execution time: 173_707_000 picoseconds. - Weight::from_parts(179_920_000, 0) + // Minimum execution time: 204_877_000 picoseconds. + Weight::from_parts(210_389_000, 0) .saturating_add(Weight::from_parts(0, 8877)) - .saturating_add(T::DbWeight::get().reads(20)) - .saturating_add(T::DbWeight::get().writes(13)) + .saturating_add(T::DbWeight::get().reads(24)) + .saturating_add(T::DbWeight::get().writes(15)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) @@ -98,16 +104,20 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:2) + /// Storage: `System::Account` (r:2 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) + /// Storage: `Staking::Bonded` (r:2 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:2 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListNodes` (r:3 w:3) /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListBags` (r:2 w:2) @@ -116,13 +126,13 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3365` + // Measured: `3762` // Estimated: `8877` - // Minimum execution time: 174_414_000 picoseconds. - Weight::from_parts(178_068_000, 0) + // Minimum execution time: 203_362_000 picoseconds. + Weight::from_parts(209_899_000, 0) .saturating_add(Weight::from_parts(0, 8877)) - .saturating_add(T::DbWeight::get().reads(17)) - .saturating_add(T::DbWeight::get().writes(13)) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(14)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) @@ -134,16 +144,20 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) + /// Storage: `Staking::Bonded` (r:2 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:2 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListNodes` (r:2 w:2) /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListBags` (r:2 w:2) @@ -152,13 +166,13 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3312` - // Estimated: `8799` - // Minimum execution time: 198_864_000 picoseconds. - Weight::from_parts(203_783_000, 0) - .saturating_add(Weight::from_parts(0, 8799)) - .saturating_add(T::DbWeight::get().reads(17)) - .saturating_add(T::DbWeight::get().writes(13)) + // Measured: `3709` + // Estimated: `6248` + // Minimum execution time: 230_686_000 picoseconds. + Weight::from_parts(237_502_000, 0) + .saturating_add(Weight::from_parts(0, 6248)) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(14)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) @@ -176,8 +190,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1138` // Estimated: `4182` - // Minimum execution time: 70_250_000 picoseconds. - Weight::from_parts(72_231_000, 0) + // Minimum execution time: 70_821_000 picoseconds. + Weight::from_parts(72_356_000, 0) .saturating_add(Weight::from_parts(0, 4182)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -194,7 +208,7 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `NominationPools::GlobalMaxCommission` (r:1 w:0) /// Proof: `NominationPools::GlobalMaxCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -202,10 +216,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListNodes` (r:3 w:3) /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) /// Storage: `VoterList::ListBags` (r:2 w:2) @@ -216,13 +228,13 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3545` + // Measured: `3341` // Estimated: `8877` - // Minimum execution time: 155_853_000 picoseconds. - Weight::from_parts(161_032_000, 0) + // Minimum execution time: 156_714_000 picoseconds. + Weight::from_parts(158_305_000, 0) .saturating_add(Weight::from_parts(0, 8877)) - .saturating_add(T::DbWeight::get().reads(20)) - .saturating_add(T::DbWeight::get().writes(13)) + .saturating_add(T::DbWeight::get().reads(18)) + .saturating_add(T::DbWeight::get().writes(11)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) @@ -232,23 +244,25 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1744` - // Estimated: `4764` - // Minimum execution time: 62_933_000 picoseconds. - Weight::from_parts(65_847_171, 0) - .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_476 - .saturating_add(Weight::from_parts(59_648, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `1767` + // Estimated: `4556` + // Minimum execution time: 56_836_000 picoseconds. + Weight::from_parts(59_738_398, 0) + .saturating_add(Weight::from_parts(0, 4556)) + // Standard Error: 1_478 + .saturating_add(Weight::from_parts(60_085, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -259,18 +273,24 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) @@ -278,15 +298,15 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2134` - // Estimated: `4764` - // Minimum execution time: 123_641_000 picoseconds. - Weight::from_parts(127_222_589, 0) - .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 2_493 - .saturating_add(Weight::from_parts(83_361, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(11)) - .saturating_add(T::DbWeight::get().writes(9)) + // Measured: `2405` + // Estimated: `4556` + // Minimum execution time: 136_737_000 picoseconds. + Weight::from_parts(141_757_658, 0) + .saturating_add(Weight::from_parts(0, 4556)) + // Standard Error: 2_609 + .saturating_add(Weight::from_parts(84_538, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(11)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) @@ -296,28 +316,38 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:1) /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:1) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::SlashingSpans` (r:1 w:0) /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:2 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:2 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForVirtualStakers` (r:1 w:1) + /// Proof: `Staking::CounterForVirtualStakers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Staking::Validators` (r:1 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:0) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForAgents` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForAgents` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) @@ -326,6 +356,10 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::CounterForRewardPools` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForSubPoolsStorage` (r:1 w:1) /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `NominationPools::Metadata` (r:1 w:1) /// Proof: `NominationPools::Metadata` (`max_values`: None, `max_size`: Some(270), added: 2745, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForBondedPools` (r:1 w:1) @@ -337,13 +371,13 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(_s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2453` - // Estimated: `8538` - // Minimum execution time: 219_469_000 picoseconds. - Weight::from_parts(227_526_000, 0) - .saturating_add(Weight::from_parts(0, 8538)) - .saturating_add(T::DbWeight::get().reads(24)) - .saturating_add(T::DbWeight::get().writes(20)) + // Measured: `2809` + // Estimated: `6274` + // Minimum execution time: 241_043_000 picoseconds. + Weight::from_parts(250_578_253, 0) + .saturating_add(Weight::from_parts(0, 6274)) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(26)) } /// Storage: `NominationPools::LastPoolId` (r:1 w:1) /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -365,16 +399,30 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:2 w:1) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:2 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:2 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForAgents` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForAgents` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:1) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:2 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:2 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForVirtualStakers` (r:1 w:1) + /// Proof: `Staking::CounterForVirtualStakers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) /// Proof: `NominationPools::RewardPools` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForRewardPools` (r:1 w:1) @@ -391,22 +439,28 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `1102` - // Estimated: `8538` - // Minimum execution time: 166_466_000 picoseconds. - Weight::from_parts(171_425_000, 0) - .saturating_add(Weight::from_parts(0, 8538)) - .saturating_add(T::DbWeight::get().reads(23)) - .saturating_add(T::DbWeight::get().writes(17)) + // Measured: `1168` + // Estimated: `6196` + // Minimum execution time: 180_902_000 picoseconds. + Weight::from_parts(187_769_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().writes(23)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) @@ -426,14 +480,14 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1738` + // Measured: `1921` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 59_650_000 picoseconds. - Weight::from_parts(60_620_077, 0) + // Minimum execution time: 78_369_000 picoseconds. + Weight::from_parts(79_277_958, 0) .saturating_add(Weight::from_parts(0, 4556)) - // Standard Error: 7_316 - .saturating_add(Weight::from_parts(1_467_406, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12)) + // Standard Error: 8_343 + .saturating_add(Weight::from_parts(1_493_255, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(15)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) @@ -446,10 +500,10 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: - // Measured: `1363` + // Measured: `1406` // Estimated: `4556` - // Minimum execution time: 31_170_000 picoseconds. - Weight::from_parts(32_217_000, 0) + // Minimum execution time: 32_631_000 picoseconds. + Weight::from_parts(33_356_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -465,11 +519,11 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `498` // Estimated: `3735` - // Minimum execution time: 12_603_000 picoseconds. - Weight::from_parts(13_241_702, 0) + // Minimum execution time: 12_514_000 picoseconds. + Weight::from_parts(13_232_732, 0) .saturating_add(Weight::from_parts(0, 3735)) - // Standard Error: 116 - .saturating_add(Weight::from_parts(1_428, 0).saturating_mul(n.into())) + // Standard Error: 150 + .saturating_add(Weight::from_parts(2_371, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -489,8 +543,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_608_000 picoseconds. - Weight::from_parts(3_801_000, 0) + // Minimum execution time: 3_107_000 picoseconds. + Weight::from_parts(3_255_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(6)) } @@ -500,18 +554,22 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `498` // Estimated: `3719` - // Minimum execution time: 16_053_000 picoseconds. - Weight::from_parts(16_473_000, 0) + // Minimum execution time: 16_568_000 picoseconds. + Weight::from_parts(17_019_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Validators` (r:1 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) @@ -526,12 +584,12 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `1901` + // Measured: `2138` // Estimated: `4556` - // Minimum execution time: 57_251_000 picoseconds. - Weight::from_parts(59_390_000, 0) + // Minimum execution time: 73_717_000 picoseconds. + Weight::from_parts(77_030_000, 0) .saturating_add(Weight::from_parts(0, 4556)) - .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -546,8 +604,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `770` // Estimated: `3719` - // Minimum execution time: 29_888_000 picoseconds. - Weight::from_parts(31_056_000, 0) + // Minimum execution time: 30_770_000 picoseconds. + Weight::from_parts(31_556_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -560,8 +618,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `538` // Estimated: `3719` - // Minimum execution time: 15_769_000 picoseconds. - Weight::from_parts(16_579_000, 0) + // Minimum execution time: 16_257_000 picoseconds. + Weight::from_parts(16_891_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -572,8 +630,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `498` // Estimated: `3719` - // Minimum execution time: 15_385_000 picoseconds. - Weight::from_parts(16_402_000, 0) + // Minimum execution time: 16_548_000 picoseconds. + Weight::from_parts(18_252_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -584,8 +642,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `498` // Estimated: `3719` - // Minimum execution time: 14_965_000 picoseconds. - Weight::from_parts(15_548_000, 0) + // Minimum execution time: 16_085_000 picoseconds. + Weight::from_parts(17_218_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -598,8 +656,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `508` // Estimated: `4182` - // Minimum execution time: 13_549_000 picoseconds. - Weight::from_parts(14_307_000, 0) + // Minimum execution time: 13_648_000 picoseconds. + Weight::from_parts(13_990_000, 0) .saturating_add(Weight::from_parts(0, 4182)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -616,8 +674,8 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `968` // Estimated: `3719` - // Minimum execution time: 60_153_000 picoseconds. - Weight::from_parts(61_369_000, 0) + // Minimum execution time: 60_321_000 picoseconds. + Weight::from_parts(61_512_000, 0) .saturating_add(Weight::from_parts(0, 3719)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -632,12 +690,135 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn adjust_pool_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `867` + // Measured: `876` // Estimated: `4764` - // Minimum execution time: 64_985_000 picoseconds. - Weight::from_parts(66_616_000, 0) + // Minimum execution time: 65_609_000 picoseconds. + Weight::from_parts(67_320_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:0) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn apply_slash() -> Weight { + // Proof Size summary in bytes: + // Measured: `3328` + // Estimated: `4556` + // Minimum execution time: 99_605_000 picoseconds. + Weight::from_parts(101_986_000, 0) + .saturating_add(Weight::from_parts(0, 4556)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:0) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:1 w:0) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:0) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + fn apply_slash_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `3070` + // Estimated: `4556` + // Minimum execution time: 58_103_000 picoseconds. + Weight::from_parts(59_680_000, 0) + .saturating_add(Weight::from_parts(0, 4556)) + .saturating_add(T::DbWeight::get().reads(7)) + } + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:1) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:2 w:1) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForAgents` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForAgents` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForVirtualStakers` (r:1 w:1) + /// Proof: `Staking::CounterForVirtualStakers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:1) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn pool_migrate() -> Weight { + // Proof Size summary in bytes: + // Measured: `1359` + // Estimated: `6196` + // Minimum execution time: 144_098_000 picoseconds. + Weight::from_parts(146_590_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(16)) + .saturating_add(T::DbWeight::get().writes(11)) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(717), added: 3192, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:2 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:0) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(261), added: 2736, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Delegators` (r:2 w:2) + /// Proof: `DelegatedStaking::Delegators` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:2 w:0) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:2 w:2) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::CounterForDelegators` (r:1 w:1) + /// Proof: `DelegatedStaking::CounterForDelegators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn migrate_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `2275` + // Estimated: `6180` + // Minimum execution time: 148_594_000 picoseconds. + Weight::from_parts(152_119_000, 0) + .saturating_add(Weight::from_parts(0, 6180)) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().writes(6)) + } } diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_hrmp.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_hrmp.rs index 3d2ab827b8fd125b74a2c892803038557998b8be..f1d7932fe8b7c09d069144f624c0f29bce7c4e5b 100644 --- a/polkadot/runtime/westend/src/weights/runtime_parachains_hrmp.rs +++ b/polkadot/runtime/westend/src/weights/runtime_parachains_hrmp.rs @@ -16,28 +16,26 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner--ss9ysm1-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=westend-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=runtime_parachains::hrmp // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/westend/src/weights/runtime_parachains_hrmp.rs +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=runtime_parachains::hrmp +// --chain=westend-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,99 +48,103 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::hrmp`. pub struct WeightInfo(PhantomData); impl runtime_parachains::hrmp::WeightInfo for WeightInfo { - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_init_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `307` - // Estimated: `6247` - // Minimum execution time: 35_676_000 picoseconds. - Weight::from_parts(36_608_000, 0) - .saturating_add(Weight::from_parts(0, 6247)) + // Measured: `455` + // Estimated: `3920` + // Minimum execution time: 35_900_000 picoseconds. + Weight::from_parts(37_587_000, 0) + .saturating_add(Weight::from_parts(0, 3920)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_accept_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `421` - // Estimated: `3886` - // Minimum execution time: 32_773_000 picoseconds. - Weight::from_parts(33_563_000, 0) - .saturating_add(Weight::from_parts(0, 3886)) + // Measured: `445` + // Estimated: `3910` + // Minimum execution time: 35_670_000 picoseconds. + Weight::from_parts(36_853_000, 0) + .saturating_add(Weight::from_parts(0, 3910)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_close_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3703` - // Minimum execution time: 28_134_000 picoseconds. - Weight::from_parts(29_236_000, 0) - .saturating_add(Weight::from_parts(0, 3703)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `558` + // Estimated: `4023` + // Minimum execution time: 36_953_000 picoseconds. + Weight::from_parts(38_638_000, 0) + .saturating_add(Weight::from_parts(0, 4023)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:254 w:254) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:254) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:254 w:254) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:254) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 127]`. /// The range of component `e` is `[0, 127]`. fn force_clean_hrmp(i: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `158 + e * (100 ±0) + i * (100 ±0)` - // Estimated: `3620 + e * (2575 ±0) + i * (2575 ±0)` - // Minimum execution time: 1_217_145_000 picoseconds. - Weight::from_parts(1_251_187_000, 0) - .saturating_add(Weight::from_parts(0, 3620)) - // Standard Error: 118_884 - .saturating_add(Weight::from_parts(4_002_678, 0).saturating_mul(i.into())) - // Standard Error: 118_884 - .saturating_add(Weight::from_parts(3_641_596, 0).saturating_mul(e.into())) + // Measured: `264 + e * (100 ±0) + i * (100 ±0)` + // Estimated: `3726 + e * (2575 ±0) + i * (2575 ±0)` + // Minimum execution time: 1_202_266_000 picoseconds. + Weight::from_parts(1_217_618_000, 0) + .saturating_add(Weight::from_parts(0, 3726)) + // Standard Error: 113_091 + .saturating_add(Weight::from_parts(3_550_787, 0).saturating_mul(i.into())) + // Standard Error: 113_091 + .saturating_add(Weight::from_parts(3_615_215, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(e.into()))) @@ -152,135 +154,141 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf .saturating_add(Weight::from_parts(0, 2575).saturating_mul(e.into())) .saturating_add(Weight::from_parts(0, 2575).saturating_mul(i.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:256 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:256 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `386 + c * (136 ±0)` - // Estimated: `1841 + c * (5086 ±0)` - // Minimum execution time: 6_277_000 picoseconds. - Weight::from_parts(6_357_000, 0) - .saturating_add(Weight::from_parts(0, 1841)) - // Standard Error: 41_189 - .saturating_add(Weight::from_parts(22_159_709, 0).saturating_mul(c.into())) + // Measured: `492 + c * (136 ±0)` + // Estimated: `1947 + c * (5086 ±0)` + // Minimum execution time: 6_105_000 picoseconds. + Weight::from_parts(6_313_000, 0) + .saturating_add(Weight::from_parts(0, 1947)) + // Standard Error: 16_081 + .saturating_add(Weight::from_parts(21_097_410, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 5086).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:128 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:128) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:128 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:0 w:128) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `229 + c * (124 ±0)` - // Estimated: `1689 + c * (2600 ±0)` - // Minimum execution time: 5_070_000 picoseconds. - Weight::from_parts(5_225_000, 0) - .saturating_add(Weight::from_parts(0, 1689)) - // Standard Error: 24_173 - .saturating_add(Weight::from_parts(13_645_307, 0).saturating_mul(c.into())) + // Measured: `335 + c * (124 ±0)` + // Estimated: `1795 + c * (2600 ±0)` + // Minimum execution time: 5_073_000 picoseconds. + Weight::from_parts(5_398_000, 0) + .saturating_add(Weight::from_parts(0, 1795)) + // Standard Error: 12_934 + .saturating_add(Weight::from_parts(13_222_909, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2600).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `920 + c * (13 ±0)` - // Estimated: `4189 + c * (15 ±0)` - // Minimum execution time: 20_449_000 picoseconds. - Weight::from_parts(30_861_799, 0) - .saturating_add(Weight::from_parts(0, 4189)) - // Standard Error: 6_642 - .saturating_add(Weight::from_parts(236_293, 0).saturating_mul(c.into())) + // Measured: `1026 + c * (13 ±0)` + // Estimated: `4295 + c * (15 ±0)` + // Minimum execution time: 16_793_000 picoseconds. + Weight::from_parts(27_430_638, 0) + .saturating_add(Weight::from_parts(0, 4295)) + // Standard Error: 2_996 + .saturating_add(Weight::from_parts(191_905, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 15).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `137 + c * (63 ±0)` - // Estimated: `1616 + c * (2538 ±0)` - // Minimum execution time: 3_911_000 picoseconds. - Weight::from_parts(5_219_837, 0) - .saturating_add(Weight::from_parts(0, 1616)) - // Standard Error: 10_219 - .saturating_add(Weight::from_parts(3_647_782, 0).saturating_mul(c.into())) + // Measured: `243 + c * (63 ±0)` + // Estimated: `1722 + c * (2538 ±0)` + // Minimum execution time: 3_805_000 picoseconds. + Weight::from_parts(445_643, 0) + .saturating_add(Weight::from_parts(0, 1722)) + // Standard Error: 4_991 + .saturating_add(Weight::from_parts(3_459_894, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2538).saturating_mul(c.into())) } - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - fn force_open_hrmp_channel(_c: u32, ) -> Weight { + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `c` is `[0, 1]`. + fn force_open_hrmp_channel(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `307` - // Estimated: `6247` - // Minimum execution time: 50_870_000 picoseconds. - Weight::from_parts(53_335_000, 0) - .saturating_add(Weight::from_parts(0, 6247)) - .saturating_add(T::DbWeight::get().reads(13)) + // Measured: `455 + c * (235 ±0)` + // Estimated: `6395 + c * (235 ±0)` + // Minimum execution time: 53_580_000 picoseconds. + Weight::from_parts(55_701_720, 0) + .saturating_add(Weight::from_parts(0, 6395)) + // Standard Error: 159_757 + .saturating_add(Weight::from_parts(15_601_979, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(8)) + .saturating_add(Weight::from_parts(0, 235).saturating_mul(c.into())) } /// Storage: `Paras::ParaLifecycles` (r:1 w:0) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -294,6 +302,8 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) @@ -304,12 +314,12 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_system_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `6357` - // Minimum execution time: 629_674_000 picoseconds. - Weight::from_parts(640_174_000, 0) - .saturating_add(Weight::from_parts(0, 6357)) - .saturating_add(T::DbWeight::get().reads(12)) + // Measured: `455` + // Estimated: `6395` + // Minimum execution time: 54_226_000 picoseconds. + Weight::from_parts(55_572_000, 0) + .saturating_add(Weight::from_parts(0, 6395)) + .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(8)) } /// Storage: `Hrmp::HrmpChannels` (r:1 w:1) @@ -318,20 +328,42 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `263` // Estimated: `3728` - // Minimum execution time: 173_371_000 picoseconds. - Weight::from_parts(175_860_000, 0) + // Minimum execution time: 11_850_000 picoseconds. + Weight::from_parts(12_428_000, 0) .saturating_add(Weight::from_parts(0, 3728)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Paras::ParaLifecycles` (r:2 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:2 w:2) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:2 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:2 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:2 w:2) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:2 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:2 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:2 w:2) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_channel_with_system() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `6357` - // Minimum execution time: 629_674_000 picoseconds. - Weight::from_parts(640_174_000, 0) - .saturating_add(Weight::from_parts(0, 6357)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(8)) + // Measured: `455` + // Estimated: `6395` + // Minimum execution time: 93_465_000 picoseconds. + Weight::from_parts(95_845_000, 0) + .saturating_add(Weight::from_parts(0, 6395)) + .saturating_add(T::DbWeight::get().reads(21)) + .saturating_add(T::DbWeight::get().writes(11)) } } diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index f661c4b0e4f437a2f2d597d8bdef26e0b76930c3..c6c5fb9e72a46afa70c6db09fd3a2b0f38d7e3a5 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -222,6 +222,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } parameter_types! { diff --git a/polkadot/statement-table/Cargo.toml b/polkadot/statement-table/Cargo.toml index 37b8a99d640a2d23e0d7a532adc0c43b04bba1f2..ad4a053fa3f9e434f8cc3f7ca9ef54f4435eba9c 100644 --- a/polkadot/statement-table/Cargo.toml +++ b/polkadot/statement-table/Cargo.toml @@ -10,7 +10,7 @@ description = "Stores messages other authorities issue about candidates in Polka workspace = true [dependencies] -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } sp-core = { path = "../../substrate/primitives/core" } primitives = { package = "polkadot-primitives", path = "../primitives" } gum = { package = "tracing-gum", path = "../node/gum" } diff --git a/polkadot/xcm/Cargo.toml b/polkadot/xcm/Cargo.toml index b214342d2f4860837ec0d2a56daa9108f1a53fe2..2cd8e822ae16b39b4d9465b91b45869b1776dbf8 100644 --- a/polkadot/xcm/Cargo.toml +++ b/polkadot/xcm/Cargo.toml @@ -10,12 +10,12 @@ license.workspace = true workspace = true [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" bounded-collections = { version = "0.2.0", default-features = false, features = ["serde"] } derivative = { version = "2.2.0", default-features = false, features = ["use_core"] } impl-trait-for-tuples = "0.2.2" log = { workspace = true } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } sp-weights = { path = "../../substrate/primitives/weights", default-features = false, features = ["serde"] } serde = { features = ["alloc", "derive", "rc"], workspace = true } diff --git a/polkadot/xcm/docs/Cargo.toml b/polkadot/xcm/docs/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9820bd36dc0b1fb84fb6c4e43e4b1608308432a2 --- /dev/null +++ b/polkadot/xcm/docs/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "xcm-docs" +description = "Documentation and guides for XCM" +version = "0.1.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true +authors.workspace = true +edition.workspace = true +publish = false + +[dependencies] +# For XCM stuff +xcm = { path = "../../xcm", package = "staging-xcm" } +xcm-executor = { path = "../../xcm/xcm-executor", package = "staging-xcm-executor" } +xcm-builder = { path = "../../xcm/xcm-builder", package = "staging-xcm-builder" } +xcm-simulator = { path = "../../xcm/xcm-simulator" } +pallet-xcm = { path = "../../xcm/pallet-xcm" } + +# For building FRAME runtimes +frame = { package = "polkadot-sdk-frame", path = "../../../substrate/frame", features = ["experimental", "runtime"] } +codec = { package = "parity-scale-codec", version = "3.6.9" } +scale-info = { version = "2.6.0", default-features = false } +polkadot-parachain-primitives = { path = "../../../polkadot/parachain" } +polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains" } +polkadot-primitives = { path = "../../../polkadot/primitives" } +sp-runtime = { path = "../../../substrate/primitives/runtime" } +sp-std = { path = "../../../substrate/primitives/std" } +sp-io = { path = "../../../substrate/primitives/io" } + +# Some pallets +pallet-message-queue = { path = "../../../substrate/frame/message-queue" } +pallet-balances = { path = "../../../substrate/frame/balances" } + +# For building docs +simple-mermaid = { git = "https://github.com/kianenigma/simple-mermaid.git", branch = "main" } +docify = "0.2.6" + +[dev-dependencies] +test-log = "0.2.14" diff --git a/polkadot/xcm/docs/mermaid/location_hierarchy.mmd b/polkadot/xcm/docs/mermaid/location_hierarchy.mmd new file mode 100644 index 0000000000000000000000000000000000000000..54fcfc8072a9aa08032da54f3b4332ef7db5d7c1 --- /dev/null +++ b/polkadot/xcm/docs/mermaid/location_hierarchy.mmd @@ -0,0 +1,9 @@ +flowchart + relay[Relaychain] --> paraA["Parachain(1000)"] + relay --> paraB["Parachain(2000)"] + + paraA --> pallet[Pallet] + pallet --> indexA[Index 1] + pallet --> indexB[Index 2] + + paraA --> account[Account] diff --git a/polkadot/xcm/docs/mermaid/structure.mmd b/polkadot/xcm/docs/mermaid/structure.mmd new file mode 100644 index 0000000000000000000000000000000000000000..17f60467241a351ab3c623b451b8ff4d79df2b9b --- /dev/null +++ b/polkadot/xcm/docs/mermaid/structure.mmd @@ -0,0 +1,4 @@ +flowchart + docs[xcm_docs] --> fundamentals + docs --> guides + docs --> cookbook diff --git a/polkadot/xcm/docs/mermaid/transport_protocols.mmd b/polkadot/xcm/docs/mermaid/transport_protocols.mmd new file mode 100644 index 0000000000000000000000000000000000000000..c0340db0651a3f273bbd35dd5fa51afe15a11c24 --- /dev/null +++ b/polkadot/xcm/docs/mermaid/transport_protocols.mmd @@ -0,0 +1,6 @@ +flowchart + relay[Relaychain] --"DMP"--> paraA["Parachain(2000)"] + relay --"DMP"--> paraB["Parachain(2001)"] + + paraA --"UMP"--> relay + paraB --"UMP"--> relay diff --git a/polkadot/xcm/docs/mermaid/universal_location.mmd b/polkadot/xcm/docs/mermaid/universal_location.mmd new file mode 100644 index 0000000000000000000000000000000000000000..97bfa747319db21dfe07032a3e7fea4d7a54f056 --- /dev/null +++ b/polkadot/xcm/docs/mermaid/universal_location.mmd @@ -0,0 +1,3 @@ +flowchart + universe[Universal Location] --> polkadot[Polkadot] + universe --> ethereum[Ethereum] diff --git a/polkadot/xcm/docs/mermaid/usdt_location.mmd b/polkadot/xcm/docs/mermaid/usdt_location.mmd new file mode 100644 index 0000000000000000000000000000000000000000..5e9222f6098ec900ed18b99a16a51c9e2584ee6e --- /dev/null +++ b/polkadot/xcm/docs/mermaid/usdt_location.mmd @@ -0,0 +1,6 @@ +flowchart + relay[Polkadot] --> assetHub["Asset Hub"] + relay --> anotherPara["Another parachain"] + + assetHub --> assetsPallet["Assets Pallet"] + assetsPallet --> usdt[1984] diff --git a/polkadot/xcm/docs/src/cookbook/mod.rs b/polkadot/xcm/docs/src/cookbook/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..1c69bf0ead6f81e4a11010cbf314f9638dda9ccb --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/mod.rs @@ -0,0 +1,27 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # XCM Cookbook +//! +//! A collection of XCM recipes. +//! +//! Each recipe is tested and explains all the code necessary to run it -- they're not just snippets +//! to copy and paste. + +/// Configuring a parachain that only uses the Relay Chain native token. +/// In the case of Polkadot, this recipe will show you how to launch a parachain with no native +/// token -- dealing only on DOT. +pub mod relay_token_transactor; diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..279dd71a35f7410b6a6899e5c018c4f55ca18d15 --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs @@ -0,0 +1,51 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # Relay Asset Transactor +//! +//! This example shows how to configure a parachain to only deal with the Relay Chain token. +//! +//! The first step is using the [`xcm_builder::FungibleAdapter`] to create an `AssetTransactor` that +//! can handle the relay chain token. +#![doc = docify::embed!("src/cookbook/relay_token_transactor/parachain/xcm_config.rs", asset_transactor)] +//! +//! The second step is to configure `IsReserve` to recognize the relay chain as a reserve for its +//! own asset. +//! With this, you'll be able to easily mint a derivative asset, backed one-to-one from the Relay +//! Chain, by using the xcm pallet's `transfer_assets` extrinsic. +//! +//! The `IsReserve` type takes a type that implements `ContainsPair`. +//! In this case, we want a type that contains the pair `(relay_chain_native_token, relay_chain)`. +#![doc = docify::embed!("src/cookbook/relay_token_transactor/parachain/xcm_config.rs", is_reserve)] +//! +//! With this setup, we are able to do a reserve asset transfer to and from the parachain and relay +//! chain. +#![doc = docify::embed!("src/cookbook/relay_token_transactor/tests.rs", reserve_asset_transfers_work)] +//! +//! For the rest of the code, be sure to check the contents of this module. + +/// The parachain runtime for this example +pub mod parachain; + +/// The relay chain runtime for this example. +pub mod relay_chain; + +/// The network for this example. +pub mod network; + +/// Tests for this example. +#[cfg(test)] +pub mod tests; diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs new file mode 100644 index 0000000000000000000000000000000000000000..46ac0e5df6372babf84b3494436e554353ba2820 --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs @@ -0,0 +1,90 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Mock network + +use frame::deps::{ + frame_system, + sp_io::TestExternalities, + sp_runtime::{AccountId32, BuildStorage}, +}; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +use super::{parachain, relay_chain}; + +pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const BOB: AccountId32 = AccountId32::new([1u8; 32]); +pub const UNITS: u64 = 10_000_000_000; +pub const CENTS: u64 = 100_000_000; +pub const INITIAL_BALANCE: u64 = UNITS; + +decl_test_parachain! { + pub struct ParaA { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MessageQueue, + DmpMessageHandler = parachain::MessageQueue, + new_ext = para_ext(), + } +} + +decl_test_relay_chain! { + pub struct Relay { + Runtime = relay_chain::Runtime, + RuntimeCall = relay_chain::RuntimeCall, + RuntimeEvent = relay_chain::RuntimeEvent, + XcmConfig = relay_chain::XcmConfig, + MessageQueue = relay_chain::MessageQueue, + System = relay_chain::System, + new_ext = relay_ext(), + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (2222, ParaA), + ], + } +} + +pub fn para_ext() -> TestExternalities { + use parachain::{MessageQueue, Runtime, System}; + + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let mut ext = frame::deps::sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MessageQueue::set_para_id(2222.into()); + }); + ext +} + +pub fn relay_ext() -> TestExternalities { + use relay_chain::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..e3fdda2e733376ca3eb780acbc17256c12e6acac --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs @@ -0,0 +1,56 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # Runtime + +use frame::{deps::frame_system, prelude::*, runtime::prelude::*, traits::IdentityLookup}; +use xcm_executor::XcmExecutor; +use xcm_simulator::mock_message_queue; + +mod xcm_config; +use xcm_config::XcmConfig; + +pub type Block = frame_system::mocking::MockBlock; +pub type AccountId = frame::deps::sp_runtime::AccountId32; +pub type Balance = u64; + +construct_runtime! { + pub struct Runtime { + System: frame_system, + MessageQueue: mock_message_queue, + Balances: pallet_balances, + XcmPallet: pallet_xcm, + } +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type AccountData = pallet_balances::AccountData; +} + +impl mock_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type AccountStore = System; +} diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs new file mode 100644 index 0000000000000000000000000000000000000000..99f17693093e7f0472d78caf54f842847a8a3e84 --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs @@ -0,0 +1,189 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # XCM Configuration + +use frame::{ + deps::frame_system, + runtime::prelude::*, + traits::{Everything, Nothing}, +}; +use xcm::v4::prelude::*; +use xcm_builder::{ + AccountId32Aliases, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, + FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete, + SignedToAccountId32, +}; +use xcm_executor::XcmExecutor; + +use super::{AccountId, Balances, MessageQueue, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; + +parameter_types! { + pub RelayLocation: Location = Location::parent(); + pub ThisNetwork: NetworkId = NetworkId::Polkadot; +} + +pub type LocationToAccountId = ( + HashedDescription>, + AccountId32Aliases, +); + +/// Configuration related to asset transactors +#[docify::export] +mod asset_transactor { + use super::*; + + parameter_types! { + pub ParentRelayLocation: Location = Location::parent(); + } + + /// AssetTransactor for handling the relay chain token + pub type FungibleTransactor = FungibleAdapter< + // Use this implementation of the `fungible::*` traits. + // `Balances` is the name given to the balances pallet in this particular recipe. + // Any implementation of the traits would suffice. + Balances, + // This transactor deals with the native token of the Relay Chain. + // This token is referenced by the Location of the Relay Chain relative to this chain + // -- Location::parent(). + IsConcrete, + // How to convert an XCM Location into a local account id. + // This is also something that's configured in the XCM executor. + LocationToAccountId, + // The type for account ids, only needed because `fungible` is generic over it. + AccountId, + // Not tracking teleports. + // This recipe only uses reserve asset transfers to handle the Relay Chain token. + (), + >; + + /// Actual configuration item that'll be set in the XCM config. + /// A tuple could be used here to have multiple transactors, each (potentially) handling + /// different assets. + /// In this recipe, we only have one. + pub type AssetTransactor = FungibleTransactor; +} + +/// Configuration related to token reserves +#[docify::export] +mod is_reserve { + use super::*; + + parameter_types! { + /// Reserves are specified using a pair `(AssetFilter, Location)`. + /// Each pair means that the specified Location is a reserve for all the assets in AssetsFilter. + /// Here, we are specifying that the Relay Chain is the reserve location for its native token. + pub RelayTokenForRelay: (AssetFilter, Location) = + (Wild(AllOf { id: AssetId(Parent.into()), fun: WildFungible }), Parent.into()); + } + + /// The wrapper type xcm_builder::Case is needed in order to use this in the configuration. + pub type IsReserve = xcm_builder::Case; +} + +mod weigher { + use super::*; + use xcm_builder::FixedWeightBounds; + + parameter_types! { + pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); + pub const MaxInstructions: u32 = 100; + } + + pub type Weigher = FixedWeightBounds; +} + +parameter_types! { + pub UniversalLocation: InteriorLocation = [GlobalConsensus(NetworkId::Polkadot), Parachain(2222)].into(); +} + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = (); + type AssetTransactor = asset_transactor::AssetTransactor; + type OriginConverter = (); + // The declaration of which Locations are reserves for which Assets. + type IsReserve = is_reserve::IsReserve; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a + // production chain + type Barrier = xcm_builder::AllowUnpaidExecutionFrom; + type Weigher = weigher::Weigher; + type Trader = (); + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type XcmRecorder = (); +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + // We turn off sending for these tests + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = super::super::network::ParachainXcmRouter; // Provided by xcm-simulator + // Anyone can execute XCM programs + type ExecuteXcmOrigin = EnsureXcmOrigin; + // We execute any type of program + type XcmExecuteFilter = Everything; + // How we execute programs + type XcmExecutor = XcmExecutor; + // We don't allow teleports + type XcmTeleportFilter = Nothing; + // We allow all reserve transfers + type XcmReserveTransferFilter = Everything; + // Same weigher executor uses to weigh XCM programs + type Weigher = weigher::Weigher; + // Same universal location + type UniversalLocation = UniversalLocation; + // No version discovery needed + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; + type AdvertisedXcmVersion = frame::traits::ConstU32<3>; + type AdminOrigin = frame_system::EnsureRoot; + // No locking + type TrustedLockers = (); + type MaxLockers = frame::traits::ConstU32<0>; + type MaxRemoteLockConsumers = frame::traits::ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + // How to turn locations into accounts + type SovereignAccountOf = LocationToAccountId; + // A currency to pay for things and its matcher, we are using the relay token + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + // Pallet benchmarks, no need for this recipe + type WeightInfo = pallet_xcm::TestWeightInfo; + // Runtime types + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; +} diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..25c35dd4aaa83c12b0176ea528d09f7d84bc87ce --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs @@ -0,0 +1,103 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Relay chain runtime mock. + +use frame::{ + deps::{frame_support::weights::WeightMeter, sp_runtime::AccountId32}, + prelude::*, + runtime::prelude::*, + traits::{IdentityLookup, ProcessMessage, ProcessMessageError}, +}; +use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId}; +use xcm::v4::prelude::*; + +mod xcm_config; +pub use xcm_config::LocationToAccountId; +use xcm_config::XcmConfig; + +pub type AccountId = AccountId32; +pub type Balance = u64; + +parameter_types! { + pub const BlockHashCount: u64 = 250; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type AccountData = pallet_balances::AccountData; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Runtime { + type AccountStore = System; +} + +type Block = frame_system::mocking::MockBlock; + +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet. +pub struct MessageProcessor; +impl ProcessMessage for MessageProcessor { + type Origin = AggregateMessageOrigin; + + fn process_message( + message: &[u8], + origin: Self::Origin, + meter: &mut WeightMeter, + id: &mut [u8; 32], + ) -> Result { + let para = match origin { + AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, + }; + xcm_builder::ProcessXcmMessage::< + Junction, + xcm_executor::XcmExecutor, + RuntimeCall, + >::process_message(message, Junction::Parachain(para.into()), meter, id) + } +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Size = u32; + type HeapSize = MessageQueueHeapSize; + type MaxStale = MessageQueueMaxStale; + type ServiceWeight = MessageQueueServiceWeight; + type MessageProcessor = MessageProcessor; + type QueueChangeHandler = (); + type QueuePausedQuery = (); + type WeightInfo = (); + type IdleMaxServiceWeight = MessageQueueServiceWeight; +} + +construct_runtime! { + pub struct Runtime { + System: frame_system, + Balances: pallet_balances, + MessageQueue: pallet_message_queue, + XcmPallet: pallet_xcm, + } +} diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs new file mode 100644 index 0000000000000000000000000000000000000000..987bb3f9ab6649bc299edafa97dc1d06166db440 --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs @@ -0,0 +1,163 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Relay chain XCM configuration + +use frame::{ + deps::frame_system, + runtime::prelude::*, + traits::{Everything, Nothing}, +}; +use xcm::v4::prelude::*; +use xcm_builder::{ + AccountId32Aliases, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, + FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete, + SignedToAccountId32, +}; +use xcm_executor::XcmExecutor; + +use super::{AccountId, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; + +parameter_types! { + pub HereLocation: Location = Location::here(); + pub ThisNetwork: NetworkId = NetworkId::Polkadot; +} + +/// Converter from XCM Locations to accounts. +/// This generates sovereign accounts for Locations and converts +/// local AccountId32 junctions to local accounts. +pub type LocationToAccountId = ( + HashedDescription>, + AccountId32Aliases, +); + +mod asset_transactor { + use super::*; + + /// AssetTransactor for handling the Relay Chain token. + pub type FungibleTransactor = FungibleAdapter< + // Use this `fungible` implementation. + Balances, + // This transactor handles the native token. + IsConcrete, + // How to convert an XCM Location into a local account id. + // Whenever assets are handled, the location is turned into an account. + // This account is the one where balances are withdrawn/deposited. + LocationToAccountId, + // The account id type, needed because `fungible` is generic over it. + AccountId, + // Not tracking teleports. + (), + >; + + /// All asset transactors, in this case only one + pub type AssetTransactor = FungibleTransactor; +} + +mod weigher { + use super::*; + use xcm_builder::FixedWeightBounds; + + parameter_types! { + pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); + pub const MaxInstructions: u32 = 100; + } + + pub type Weigher = FixedWeightBounds; +} + +parameter_types! { + pub UniversalLocation: InteriorLocation = [GlobalConsensus(NetworkId::Polkadot)].into(); +} + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = (); + type AssetTransactor = asset_transactor::AssetTransactor; + type OriginConverter = (); + // We don't need to recognize anyone as a reserve + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a + // production chain + type Barrier = xcm_builder::AllowUnpaidExecutionFrom; + type Weigher = weigher::Weigher; + type Trader = (); + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type XcmRecorder = (); +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + // No one can call `send` + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = super::super::network::RelayChainXcmRouter; // Provided by xcm-simulator + // Anyone can execute XCM programs + type ExecuteXcmOrigin = EnsureXcmOrigin; + // We execute any type of program + type XcmExecuteFilter = Everything; + // How we execute programs + type XcmExecutor = XcmExecutor; + // We don't allow teleports + type XcmTeleportFilter = Nothing; + // We allow all reserve transfers. + // This is so it can act as a reserve for its native token. + type XcmReserveTransferFilter = Everything; + // Same weigher executor uses to weigh XCM programs + type Weigher = weigher::Weigher; + // Same universal location + type UniversalLocation = UniversalLocation; + // No version discovery needed + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; + type AdvertisedXcmVersion = frame::traits::ConstU32<3>; + type AdminOrigin = frame_system::EnsureRoot; + // No locking + type TrustedLockers = (); + type MaxLockers = frame::traits::ConstU32<0>; + type MaxRemoteLockConsumers = frame::traits::ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + // How to turn locations into accounts + type SovereignAccountOf = LocationToAccountId; + // A currency to pay for things and its matcher, we are using the relay token + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + // Pallet benchmarks, no need for this example + type WeightInfo = pallet_xcm::TestWeightInfo; + // Runtime types + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; +} diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..792cf6149e7cb418f5ffa5720f41ae44956ff036 --- /dev/null +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs @@ -0,0 +1,128 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use frame::testing_prelude::*; +use test_log::test; +use xcm::prelude::*; +use xcm_executor::traits::ConvertLocation; +use xcm_simulator::TestExt; + +use super::{ + network::{MockNet, ParaA, Relay, ALICE, BOB, CENTS, INITIAL_BALANCE}, + parachain, relay_chain, +}; + +#[docify::export] +#[test] +fn reserve_asset_transfers_work() { + // Scenario: + // ALICE on the relay chain holds some of Relay Chain's native tokens. + // She transfers them to BOB's account on the parachain using a reserve transfer. + // BOB receives Relay Chain native token derivatives on the parachain, + // which are backed one-to-one with the real tokens on the Relay Chain. + // + // NOTE: We could've used ALICE on both chains because it's a different account, + // but using ALICE and BOB makes it clearer. + + // We restart the mock network. + MockNet::reset(); + + // ALICE starts with INITIAL_BALANCE on the relay chain + Relay::execute_with(|| { + assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE); + }); + + // BOB starts with 0 on the parachain + ParaA::execute_with(|| { + assert_eq!(parachain::Balances::free_balance(&BOB), 0); + }); + + // ALICE on the Relay Chain sends some Relay Chain native tokens to BOB on the parachain. + // The transfer is done with the `transfer_assets` extrinsic in the XCM pallet. + // The extrinsic figures out it should do a reserve asset transfer + // with the local chain as reserve. + Relay::execute_with(|| { + // The parachain id is specified in the network.rs file in this recipe. + let destination: Location = Parachain(2222).into(); + let beneficiary: Location = + AccountId32 { id: BOB.clone().into(), network: Some(NetworkId::Polkadot) }.into(); + // We need to use `u128` here for the conversion to work properly. + // If we don't specify anything, it will be a `u64`, which the conversion + // will turn into a non-fungible token instead of a fungible one. + let assets: Assets = (Here, 50u128 * CENTS as u128).into(); + assert_ok!(relay_chain::XcmPallet::transfer_assets( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(VersionedLocation::V4(destination.clone())), + Box::new(VersionedLocation::V4(beneficiary)), + Box::new(VersionedAssets::V4(assets)), + 0, + WeightLimit::Unlimited, + )); + + // ALICE now has less Relay Chain tokens. + assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - 50 * CENTS); + + // The funds of the sovereign account of the parachain increase by 50 cents, + // the ones transferred over to BOB. + // The funds in this sovereign account represent how many Relay Chain tokens + // have been sent to this parachain. + // If the parachain wants to send those assets somewhere else they have to go + // via the reserve, and this balance is updated accordingly. + // This is why the derivatives are backed one-to-one. + let parachains_sovereign_account = + relay_chain::LocationToAccountId::convert_location(&destination).unwrap(); + assert_eq!(relay_chain::Balances::free_balance(parachains_sovereign_account), 50 * CENTS); + }); + + ParaA::execute_with(|| { + // On the parachain, BOB has received the derivative tokens + assert_eq!(parachain::Balances::free_balance(&BOB), 50 * CENTS); + + // BOB gives back half to ALICE in the relay chain + let destination: Location = Parent.into(); + let beneficiary: Location = + AccountId32 { id: ALICE.clone().into(), network: Some(NetworkId::Polkadot) }.into(); + // We specify `Parent` because we are referencing the Relay Chain token. + // This chain doesn't have a token of its own, so we always refer to this token, + // and we do so by the Location of the Relay Chain. + let assets: Assets = (Parent, 25u128 * CENTS as u128).into(); + assert_ok!(parachain::XcmPallet::transfer_assets( + parachain::RuntimeOrigin::signed(BOB), + Box::new(VersionedLocation::V4(destination)), + Box::new(VersionedLocation::V4(beneficiary)), + Box::new(VersionedAssets::V4(assets)), + 0, + WeightLimit::Unlimited, + )); + + // BOB's balance decreased + assert_eq!(parachain::Balances::free_balance(&BOB), 25 * CENTS); + }); + + Relay::execute_with(|| { + // ALICE's balance increases + assert_eq!( + relay_chain::Balances::free_balance(&ALICE), + INITIAL_BALANCE - 50 * CENTS + 25 * CENTS + ); + + // The funds in the parachain's sovereign account decrease. + let parachain: Location = Parachain(2222).into(); + let parachains_sovereign_account = + relay_chain::LocationToAccountId::convert_location(¶chain).unwrap(); + assert_eq!(relay_chain::Balances::free_balance(parachains_sovereign_account), 25 * CENTS); + }); +} diff --git a/polkadot/xcm/docs/src/fundamentals.rs b/polkadot/xcm/docs/src/fundamentals.rs new file mode 100644 index 0000000000000000000000000000000000000000..28899df801aa4f533cdfedaea8815804dc8bd7c2 --- /dev/null +++ b/polkadot/xcm/docs/src/fundamentals.rs @@ -0,0 +1,177 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # XCM Fundamentals +//! +//! XCM standardizes usual actions users take in consensus systems, for example +//! dealing with assets locally, on other chains, and locking them. +//! XCM programs can both be executed locally or sent to a different consensus system. +//! Examples of consensus systems are blockchains and smart contracts. +//! +//! The goal of XCM is to allow multi-chain ecosystems to thrive via specialization. +//! Very specific functionalities can be abstracted away and standardized in this common language. +//! Then, every member of the ecosystem can implement the subset of the language that makes sense +//! for them. +//! +//! The language evolves over time to accomodate the needs of the community +//! via the [RFC process](https://github.com/paritytech/xcm-format/blob/master/proposals/0032-process.md). +//! +//! XCM is the language, it deals with interpreting and executing programs. +//! It does not deal with actually **sending** these programs from one consensus system to another. +//! This responsibility falls to a transport protocol. +//! XCM can even be interpreted on the local system, with no need of a transport protocol. +//! However, automatic and composable workflows can be achieved via the use of one. +//! +//! At the core of XCM lies the XCVM, the Cross-Consensus Virtual Machine. +//! It's the virtual machine that executes XCM programs. +//! It is a specification that comes with the language. +//! +//! For these docs, we'll use a Rust implementation of XCM and the XCVM, consisting of the following +//! parts: +//! - [`XCM`](xcm): Holds the definition of an XCM program, the instructions and main concepts. +//! - [`Executor`](xcm_executor): Implements the XCVM, capable of executing XCMs. Highly +//! configurable. +//! - [`Builder`](xcm_builder): A collection of types used to configure the executor. +//! - [`XCM Pallet`](pallet_xcm): A FRAME pallet for interacting with the executor. +//! - [`Simulator`](xcm_simulator): A playground to tinker with different XCM programs and executor +//! configurations. +//! +//! XCM programs are composed of Instructions, which reference Locations and Assets. +//! +//! ## Locations +//! +//! Locations are XCM's vocabulary of places we want to talk about in our XCM programs. +//! They are used to reference things like 32-byte accounts, governance bodies, smart contracts, +//! blockchains and more. +//! +//! Locations are hierarchical. +//! This means some places in consensus are wholly encapsulated in other places. +//! Say we have two systems A and B. +//! If any change in A's state implies a change in B's state, then we say A is interior to B. +#![doc = simple_mermaid::mermaid!("../mermaid/location_hierarchy.mmd")] +//! +//! Parachains are interior to their Relay Chain, since a change in their state implies a change in +//! the Relay Chain's state. +//! +//! Because of this hierarchy, the way we represent locations is with both a number of **parents**, +//! times we move __up__ the hierarchy, and a sequence of **junctions**, the steps we take __down__ +//! the hierarchy after going up the specified number of parents. +//! +//! In Rust, this is specified with the following datatype: +//! ```ignore +//! pub struct Location { +//! parents: u8, +//! interior: Junctions, +//! } +//! ``` +//! +//! Many junctions are available; parachains, pallets, 32 and 20 byte accounts, governance bodies, +//! and arbitrary indices are the most common. +//! A full list of available junctions can be found in the [format](https://github.com/paritytech/xcm-format#interior-locations--junctions) +//! and [Junction enum](xcm::v4::prelude::Junction). +//! +//! We'll use a file system notation to represent locations, and start with relative locations. +//! In the diagram, the location of parachain 1000 as seen from all other locations is as follows: +//! - From the relaychain: `Parachain(1000)` +//! - From parachain 1000 itself: `Here` +//! - From parachain 2000: `../Parachain(1000)` +//! +//! Relative locations are interpreted by the system that is executing an XCM program, which is the +//! receiver of a message in the case where it's sent. +//! +//! Locations can also be absolute. +//! Keeping in line with our filesystem analogy, we can imagine the root of our filesystem to exist. +//! This would be a location with no parents, that is also the parent of all systems that derive +//! their own consensus, say Polkadot or Ethereum or Bitcoin. +//! Such a location does not exist concretely, but we can still use this definition for it. +//! This is the **universal location**. +//! We need the universal location to be able to describe locations in an absolute way. +#![doc = simple_mermaid::mermaid!("../mermaid/universal_location.mmd")] +//! +//! Here, the absolute location of parachain 1000 would be +//! `GlobalConsensus(Polkadot)/Parachain(1000)`. +//! +//! ## Assets +//! +//! We want to be able to reference assets in our XCM programs, if only to be able to pay for fees. +//! Assets are represented using locations. +//! +//! The native asset of a chain is represented by the location of that chain. +//! For example, DOT is represented by the location of the Polkadot relaychain. +//! If the interpreting chain has its own asset, it would be represented by `Here`. +//! +//! How do we represent other assets? +//! The asset hub system parachain in Polkadot, for example, holds a lot of assets. +//! To represent each of them, it uses the indices we mentioned, and it makes them interior to the +//! assets pallet instance it uses. +//! USDT, an example asset that lives on asset hub, is identified by the location +//! `Parachain(1000)/PalletInstance(53)/GeneralIndex(1984)`, when seen from the Polkadot relaychain. +#![doc = simple_mermaid::mermaid!("../mermaid/usdt_location.mmd")] +//! +//! Asset Hub also has another type of assets called `ForeignAssets`. +//! These assets are identified by the XCM Location to their origin. +//! Two such assets are a Parachain asset, like Moonbeam's GLMR, and KSM, from the cousin Kusama +//! network. These are represented as `../Parachain(2004)/PalletInstance(10)` and +//! `../../GlobalConsensus(Kusama)` respectively. +//! +//! The whole type can be seen in the [format](https://github.com/paritytech/xcm-format#6-universal-asset-identifiers) +//! and [rust docs](xcm::v4::prelude::Asset). +//! +//! ## Instructions +//! +//! Given the vocabulary to talk about both locations -- chains and accounts -- and assets, we now +//! need a way to express what we want the consensus system to do when executing our programs. +//! We need a way of writing our programs. +//! +//! XCM programs are composed of a sequence of instructions. +//! +//! All available instructions can be seen in the [format](https://github.com/paritytech/xcm-format#5-the-xcvm-instruction-set) +//! and the [Instruction enum](xcm::v4::prelude::Instruction). +//! +//! A very simple example is the following: +//! +//! ```ignore +//! let message = Xcm(vec![ +//! TransferAsset { assets, beneficiary }, +//! ]); +//! ``` +//! +//! This instruction is enough to transfer `assets` from the account of the **origin** of a message +//! to the `beneficiary` account. However, because of XCM's generality, fees need to be paid +//! explicitly. This next example sheds more light on this: +//! +//! ```ignore +//! let message = Xcm(vec![ +//! WithdrawAsset(assets), +//! BuyExecution { fees: assets, weight_limit }, +//! DepositAsset { assets: AssetFilter(Wild(All)), beneficiary }, +//! ]); +//! ``` +//! +//! Here we see the process of transferring assets was broken down into smaller instructions, and we +//! add the explicit fee payment step in the middle. +//! `WithdrawAsset` withdraws assets from the account of the **origin** of the message for usage +//! inside this message's execution. `BuyExecution` explicitly buys execution for this program using +//! the assets specified in `fees`, with a sanity check of `weight_limit`. `DepositAsset` uses a +//! wildcard, specifying all remaining `assets` after subtracting the fees and a `beneficiary` +//! account. +//! +//! ## Next steps +//! +//! Continue with the [guides](crate::guides) for step-by-step tutorials on XCM, +//! or jump to the [cookbook](crate::cookbook) to see examples. +//! +//! The [glossary](crate::glossary) can be useful if some of the terms are confusing. diff --git a/polkadot/xcm/docs/src/glossary.rs b/polkadot/xcm/docs/src/glossary.rs new file mode 100644 index 0000000000000000000000000000000000000000..6035888ab733b2751a4f24d51336132111d6ef57 --- /dev/null +++ b/polkadot/xcm/docs/src/glossary.rs @@ -0,0 +1,123 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # Glossary +//! +//! ## XCM (Cross-Consensus Messaging) +//! +//! A messaging format meant to communicate intentions between consensus systems. +//! XCM could also refer to a single message. +//! +//! ## Instructions +//! +//! XCMs are composed of a sequence of instructions. +//! Each instruction aims to convey a particular intention. +//! There are instructions for transferring and locking assets, handling fees, calling arbitrary +//! blobs, and more. +//! +//! ## Consensus system +//! +//! A system that can reach any kind of consensus. +//! For example, relay chains, parachains, smart contracts. +//! Most messaging between consensus systems has to be done asynchronously, for this, XCM is used. +//! Between two smart contracts on the same parachain, however, communication can be done +//! synchronously. +//! +//! ## [`Location`](xcm::v4::prelude::Location) +//! +//! A way of addressing consensus systems. +//! These could be relative or absolute. +//! +//! ## [`Junction`](xcm::v4::prelude::Junction) +//! +//! The different ways of descending down a [`Location`](xcm::v4::prelude::Location) hierarchy. +//! A junction can be a Parachain, an Account, or more. +//! +//! ## [`Asset`](xcm::v4::prelude::Asset) +//! +//! A way of identifying assets in the same or another consensus system, by using a +//! [`Location`](xcm::v4::prelude::Location). +//! +//! ## Sovereign account +//! +//! An account in a consensus system that is controlled by an account in another consensus system. +//! +//! Runtimes use a converter between a [`Location`](xcm::v4::prelude::Location) and an account. +//! These converters implement the [`ConvertLocation`](xcm_executor::traits::ConvertLocation) trait. +//! +//! ## Teleport +//! +//! A way of transferring assets between two consensus systems without the need of a third party. +//! It consists of the sender system burning the asset that wants to be sent over and the recipient +//! minting an equivalent amount of that asset. It requires a lot of trust between the two systems, +//! since failure to mint or burn will reduce or increase the total issuance of the token. +//! +//! ## Reserve asset transfer +//! +//! A way of transferring assets between two consensus systems that don't trust each other, by using +//! a third system they both trust, called the reserve. The real asset only exists on the reserve, +//! both sender and recipient only deal with derivatives. It consists of the sender burning a +//! certain amount of derivatives, telling the reserve to move real assets from its sovereign +//! account to the destination's sovereign account, and then telling the recipient to mint the right +//! amount of derivatives. +//! In practice, the reserve chain can also be one of the source or destination. +//! +//! ## XCVM +//! +//! The virtual machine behind XCM. +//! Every XCM is an XCVM programme. +//! Holds state in registers. +//! +//! An implementation of the virtual machine is the [`xcm-executor`](xcm_executor::XcmExecutor). +//! +//! ## Holding register +//! +//! An XCVM register used to hold arbitrary `Asset`s during the execution of an XCVM programme. +//! +//! ## Barrier +//! +//! An XCM executor configuration item that works as a firewall for incoming XCMs. +//! All XCMs have to pass the barrier to be executed, else they are dropped. +//! It can be used for whitelisting only certain types or messages or messages from certain senders. +//! +//! Lots of barrier definitions exist in [`xcm-builder`](xcm_builder). +//! +//! ## VMP (Vertical Message Passing) +//! +//! Umbrella term for both UMP (Upward Message Passing) and DMP (Downward Message Passing). +//! +//! The following diagram shows the uses of both protocols: +#![doc = simple_mermaid::mermaid!("../mermaid/transport_protocols.mmd")] +//! +//! ## UMP (Upward Message Passing) +//! +//! Transport-layer protocol that allows parachains to send messages upwards to their relay chain. +//! +//! ## DMP (Downward Message Passing) +//! +//! Transport-layer protocol that allows the relay chain to send messages downwards to one of their +//! parachains. +//! +//! ## XCMP (Cross-Consensus Message Passing) +//! +//! Transport-layer protocol that allows parachains to send messages between themselves, without +//! going through the relay chain. +//! +//! ## HRMP (Horizontal Message Passing) +//! +//! Transport-layer protocol that allows a parachain to send messages to a sibling parachain going +//! through the relay chain. It's a precursor to XCMP, also known as XCMP-lite. +//! It uses a mixture of UMP and DMP. diff --git a/polkadot/xcm/docs/src/guides/mod.rs b/polkadot/xcm/docs/src/guides/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..5af89428d9a4c570831c17f48b5974e5ded5fd58 --- /dev/null +++ b/polkadot/xcm/docs/src/guides/mod.rs @@ -0,0 +1,25 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # XCM Guides +//! +//! These guides aim to get you up and running with XCM. +//! +//! Coming soon. +//! +//! ## Next steps +//! +//! Jump to the [cookbook](crate::cookbook) for different examples. diff --git a/polkadot/xcm/docs/src/lib.rs b/polkadot/xcm/docs/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..287c97140c91b371765257475b0d7a3ade2e2f06 --- /dev/null +++ b/polkadot/xcm/docs/src/lib.rs @@ -0,0 +1,63 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! # XCM Docs +//! +//! Documentation and guides for XCM +//! +//! Welcome to the Cross-Consensus Messaging documentation! +//! +//! XCM is a **language** for communicating **intentions** between **consensus systems**. +//! Whether you're a developer, a blockchain enthusiast, or just interested in Polkadot, this guide +//! aims to provide you with an easy-to-understand and comprehensive introduction to XCM. +//! +//! ## Getting started +//! +//! Head over to the [fundamentals](fundamentals) section. +//! Then, go to the [guides](guides), to learn about how to do things with XCM. +//! +//! ## Cookbook +//! +//! There's also the [cookbook](cookbook) for useful recipes for XCM. +//! +//! ## Glossary +//! +//! There's a [glossary](glossary) with common terms used throughout the docs. +//! +//! ## Contribute +//! +//! To contribute to the format, check out the [RFC process](https://github.com/paritytech/xcm-format/blob/master/proposals/0032-process.md). +//! To contribute to these docs, [make a PR](https://github.com/paritytech/polkadot-sdk). +//! +//! ## Why Rust Docs? +//! +//! Rust Docs allow docs to be as close to the source as possible. +//! They're also available offline automatically for anyone who has the `polkadot-sdk` repo locally. +//! +//! ## Docs structure +#![doc = simple_mermaid::mermaid!("../mermaid/structure.mmd")] + +/// Fundamentals of the XCM language. The virtual machine, instructions, locations and assets. +pub mod fundamentals; + +/// Step-by-step guides to set up an XCM environment and start hacking. +pub mod guides; + +/// Useful recipes for programs and configurations. +pub mod cookbook; + +/// Glossary +pub mod glossary; diff --git a/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml b/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml index 9691ddd48168e5e8339353a10c475ad263ce5f14..8bf3b9abf66349834b3c2b7d7cd367e4b0b835d8 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml +++ b/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml @@ -13,7 +13,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../substrate/frame/system", default-features = false } diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index 7233b46d0cd64d2f649fce9c007da1c1753bcff9..c0dfa91afc7866500b8761753fb83c76b5b23069 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -120,6 +120,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } impl crate::Config for Test { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index a9f4d37d7a55f5fa50cd6767447c2578774a7017..f51d34092616b6191cefcb82803673f43f42e4c3 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -110,6 +110,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } parameter_types! { diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml index 460597e6649ab27acec712e1b055fbf5968005f2..6f9b389ab6f12db50c27fab0f5f20961c7f171c6 100644 --- a/polkadot/xcm/pallet-xcm/Cargo.toml +++ b/polkadot/xcm/pallet-xcm/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] bounded-collections = { version = "0.2.0", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } log = { workspace = true } @@ -69,6 +69,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "xcm-fee-payment-runtime-api/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index 081a4235b7794b72beda33895c2e5e5c9577d219..da46a6a37c0654f6ef34daf7bbd37cd5b655ac45 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -15,12 +15,11 @@ // along with Polkadot. If not, see . use super::*; -use bounded_collections::{ConstU32, WeakBoundedVec}; use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; use frame_support::{assert_ok, weights::Weight}; use frame_system::RawOrigin; use sp_std::prelude::*; -use xcm::{latest::prelude::*, v2}; +use xcm::latest::prelude::*; use xcm_builder::EnsureDelivery; use xcm_executor::traits::FeeReason; @@ -313,15 +312,17 @@ benchmarks! { } notify_target_migration_fail { - let bad_loc: v2::MultiLocation = v2::Junction::Plurality { - id: v2::BodyId::Named(WeakBoundedVec::>::try_from(vec![0; 32]) - .expect("vec has a length of 32 bits; qed")), - part: v2::BodyPart::Voice, - } - .into(); - let bad_loc = VersionedLocation::from(bad_loc); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + let bad_location: Location = Plurality { + id: BodyId::Unit, + part: BodyPart::Voice, + }.into(); + let bad_location = VersionedLocation::from(bad_location) + .into_version(older_xcm_version) + .expect("Version convertion should work"); let current_version = T::AdvertisedXcmVersion::get(); - VersionNotifyTargets::::insert(current_version, bad_loc, (0, Weight::zero(), current_version)); + VersionNotifyTargets::::insert(current_version, bad_location, (0, Weight::zero(), current_version)); }: { crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); } diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index af3b66121ea131bba2b8a0e694e59763cd7eb4cc..37fc121ba2174c95f3a8ac82131d525ff8279f48 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -61,7 +61,7 @@ use xcm_executor::{ }, AssetsInHolding, }; -use xcm_fee_payment_runtime_api::Error as FeePaymentError; +use xcm_fee_payment_runtime_api::fees::Error as XcmPaymentApiError; #[cfg(any(feature = "try-runtime", test))] use sp_runtime::TryRuntimeError; @@ -764,6 +764,25 @@ pub mod pallet { #[pallet::storage] pub(super) type XcmExecutionSuspended = StorageValue<_, bool, ValueQuery>; + /// Whether or not incoming XCMs (both executed locally and received) should be recorded. + /// Only one XCM program will be recorded at a time. + /// This is meant to be used in runtime APIs, and it's advised it stays false + /// for all other use cases, so as to not degrade regular performance. + /// + /// Only relevant if this pallet is being used as the [`xcm_executor::traits::RecordXcm`] + /// implementation in the XCM executor configuration. + #[pallet::storage] + pub(crate) type ShouldRecordXcm = StorageValue<_, bool, ValueQuery>; + + /// If [`ShouldRecordXcm`] is set to true, then the last XCM program executed locally + /// will be stored here. + /// Runtime APIs can fetch the XCM that was executed by accessing this value. + /// + /// Only relevant if this pallet is being used as the [`xcm_executor::traits::RecordXcm`] + /// implementation in the XCM executor configuration. + #[pallet::storage] + pub(crate) type RecordedXcm = StorageValue<_, Xcm<()>>; + #[pallet::genesis_config] pub struct GenesisConfig { #[serde(skip)] @@ -2413,35 +2432,37 @@ impl Pallet { AccountIdConversion::::into_account_truncating(&ID) } - pub fn query_xcm_weight(message: VersionedXcm<()>) -> Result { - let message = - Xcm::<()>::try_from(message).map_err(|_| FeePaymentError::VersionedConversionFailed)?; + pub fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + let message = Xcm::<()>::try_from(message) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; T::Weigher::weight(&mut message.into()).map_err(|()| { log::error!(target: "xcm::pallet_xcm::query_xcm_weight", "Error when querying XCM weight"); - FeePaymentError::WeightNotComputable + XcmPaymentApiError::WeightNotComputable }) } pub fn query_delivery_fees( destination: VersionedLocation, message: VersionedXcm<()>, - ) -> Result { + ) -> Result { let result_version = destination.identify_version().max(message.identify_version()); - let destination = - destination.try_into().map_err(|_| FeePaymentError::VersionedConversionFailed)?; + let destination = destination + .try_into() + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; - let message = message.try_into().map_err(|_| FeePaymentError::VersionedConversionFailed)?; + let message = + message.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; let (_, fees) = validate_send::(destination, message).map_err(|error| { log::error!(target: "xcm::pallet_xcm::query_delivery_fees", "Error when querying delivery fees: {:?}", error); - FeePaymentError::Unroutable + XcmPaymentApiError::Unroutable })?; VersionedAssets::from(fees) .into_version(result_version) - .map_err(|_| FeePaymentError::VersionedConversionFailed) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed) } /// Create a new expectation of a query response with the querier being here. @@ -3105,6 +3126,24 @@ impl CheckSuspension for Pallet { } } +impl xcm_executor::traits::RecordXcm for Pallet { + fn should_record() -> bool { + ShouldRecordXcm::::get() + } + + fn set_record_xcm(enabled: bool) { + ShouldRecordXcm::::put(enabled); + } + + fn recorded_xcm() -> Option> { + RecordedXcm::::get() + } + + fn record(xcm: Xcm<()>) { + RecordedXcm::::put(xcm); + } +} + /// Ensure that the origin `o` represents an XCM (`Transact`) origin. /// /// Returns `Ok` with the location of the XCM sender or an `Err` otherwise. diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 8e94803e84315285391c0f85e5d249330a3db31b..ead98e1d046005360743b921fe3d70cd93c06a1b 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -238,10 +238,6 @@ impl SendXcm for TestPaidForPara3000SendXcm { } } -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; @@ -253,7 +249,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockWeights = (); type BlockLength = (); type Version = (); @@ -531,6 +526,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index f42e220d693203f7fa6e1391676f36a84feb9be0..af81ac9cf43a978f08c4cee86adf4d72cee3a64b 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -76,7 +76,7 @@ fn limited_teleport_assets_works() { )] ); let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + let _check_v3_ok: xcm::v3::Xcm<()> = versioned_sent.try_into().unwrap(); let mut last_events = last_events(3).into_iter(); assert_eq!( diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index 782c8bed478e18181db64256471fed0dca56e6fd..c16c1a1ba986e5c95da3ce63dd58c52393408464 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -21,8 +21,8 @@ pub(crate) mod assets_transfer; use crate::{ mock::*, pallet::SupportedVersion, AssetTraps, Config, CurrentMigration, Error, ExecuteControllerWeightInfo, LatestVersionedLocation, Pallet, Queries, QueryStatus, - VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, VersionNotifyTargets, - WeightInfo, + RecordedXcm, ShouldRecordXcm, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, + VersionNotifyTargets, WeightInfo, }; use frame_support::{ assert_err_ignore_postinfo, assert_noop, assert_ok, @@ -602,11 +602,11 @@ fn basic_subscription_works() { let weight = BaseXcmWeight::get(); let mut message = Xcm::<()>(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(1), + response: Response::Version(3), querier: None, }, ]); @@ -764,14 +764,14 @@ fn subscription_side_upgrades_work_with_notify() { new_test_ext_with_balances(vec![]).execute_with(|| { AdvertisedXcmVersion::set(1); - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + // An entry from a previous runtime with v3 XCM. + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // New version. - AdvertisedXcmVersion::set(3); + AdvertisedXcmVersion::set(4); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -780,13 +780,13 @@ fn subscription_side_upgrades_work_with_notify() { let instr1 = QueryResponse { query_id: 70, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr3 = QueryResponse { query_id: 72, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let mut sent = take_sent_xcm(); @@ -807,8 +807,8 @@ fn subscription_side_upgrades_work_with_notify() { assert_eq!( contents, vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 4)), ] ); }); @@ -817,11 +817,11 @@ fn subscription_side_upgrades_work_with_notify() { #[test] fn subscription_side_upgrades_work_without_notify() { new_test_ext_with_balances(vec![]).execute_with(|| { - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + // An entry from a previous runtime with v3 XCM. + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -854,11 +854,11 @@ fn subscriber_side_subscription_works() { let weight = BaseXcmWeight::get(); let message = Xcm(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(1), + response: Response::Version(3), querier: None, }, ]); @@ -872,18 +872,21 @@ fn subscriber_side_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); assert_eq!(take_sent_xcm(), vec![]); - assert_eq!(XcmPallet::get_version_for(&remote), Some(1)); + assert_eq!(XcmPallet::get_version_for(&remote), Some(3)); - // This message cannot be sent to a v2 remote. - let v2_msg = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - assert_eq!(XcmPallet::wrap_version(&remote, v2_msg.clone()), Err(())); + // This message will be sent as v3. + let v4_msg = xcm::v4::Xcm::<()>(vec![xcm::v4::Instruction::Trap(0)]); + assert_eq!( + XcmPallet::wrap_version(&remote, v4_msg.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::Trap(0)]))) + ); let message = Xcm(vec![ - // Remote upgraded to XCM v2 + // Remote upgraded to XCM v4 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(2), + response: Response::Version(4), querier: None, }, ]); @@ -897,12 +900,12 @@ fn subscriber_side_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); assert_eq!(take_sent_xcm(), vec![]); - assert_eq!(XcmPallet::get_version_for(&remote), Some(2)); + assert_eq!(XcmPallet::get_version_for(&remote), Some(4)); - // This message can now be sent to remote as it's v2. + // This message is now sent as v4. assert_eq!( - XcmPallet::wrap_version(&remote, v2_msg.clone()), - Ok(VersionedXcm::from(v2_msg)) + XcmPallet::wrap_version(&remote, v4_msg.clone()), + Ok(VersionedXcm::from(v4_msg)) ); }); } @@ -911,30 +914,36 @@ fn subscriber_side_subscription_works() { #[test] fn auto_subscription_works() { new_test_ext_with_balances_and_xcm_version(vec![], None).execute_with(|| { - let remote_v2: Location = Parachain(1000).into(); + let remote_v3: Location = Parachain(1000).into(); let remote_v4: Location = Parachain(1001).into(); - assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(2))); + assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(3))); // Wrapping a version for a destination we don't know elicits a subscription. - let msg_v2 = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); + let msg_v3 = xcm::v3::Xcm::<()>(vec![xcm::v3::Instruction::Trap(0)]); let msg_v4 = xcm::v4::Xcm::<()>(vec![xcm::v4::Instruction::ClearTopic]); assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), + XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone())), + ); + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v4.clone()), Err(())); - let expected = vec![(remote_v2.clone().into(), 2)]; + let expected = vec![(remote_v3.clone().into(), 2)]; assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); assert_eq!( - XcmPallet::wrap_version(&remote_v4, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), + XcmPallet::wrap_version(&remote_v4, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone())), + ); + assert_eq!( + XcmPallet::wrap_version(&remote_v4, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v4, msg_v4.clone()), Err(())); - let expected = vec![(remote_v2.clone().into(), 2), (remote_v4.clone().into(), 2)]; + let expected = vec![(remote_v3.clone().into(), 2), (remote_v4.clone().into(), 2)]; assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); XcmPallet::on_initialize(1); @@ -968,10 +977,10 @@ fn auto_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); - // V2 messages can be sent to remote_v4 under XCM v4. + // V3 messages can be sent to remote_v4 under XCM v4. assert_eq!( - XcmPallet::wrap_version(&remote_v4, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone()).into_version(4).unwrap()), + XcmPallet::wrap_version(&remote_v4, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone()).into_version(4).unwrap()), ); // This message can now be sent to remote_v4 as it's v4. assert_eq!( @@ -983,26 +992,26 @@ fn auto_subscription_works() { assert_eq!( take_sent_xcm(), vec![( - remote_v2.clone(), + remote_v3.clone(), Xcm(vec![SubscribeVersion { query_id: 1, max_response_weight: Weight::zero() }]), )] ); - // Assume remote_v2 is working ok and XCM version 2. + // Assume remote_v3 is working ok and XCM version 3. let weight = BaseXcmWeight::get(); let message = Xcm(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 1, max_weight: Weight::zero(), - response: Response::Version(2), + response: Response::Version(3), querier: None, }, ]); let mut hash = fake_message_hash(&message); let r = XcmExecutor::::prepare_and_execute( - remote_v2.clone(), + remote_v3.clone(), message, &mut hash, weight, @@ -1010,12 +1019,15 @@ fn auto_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); - // v4 messages cannot be sent to remote_v2... + // v4 messages cannot be sent to remote_v3... + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), + Ok(VersionedXcm::V3(msg_v3)) + ); assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::V2(msg_v2)) + XcmPallet::wrap_version(&remote_v3, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v4.clone()), Err(())); }) } @@ -1025,15 +1037,15 @@ fn subscription_side_upgrades_work_with_multistage_notify() { AdvertisedXcmVersion::set(1); // An entry from a previous runtime with v0 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 1)); - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1002).into()); - VersionNotifyTargets::::insert(2, v2_location, (71, Weight::zero(), 1)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 1)); + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1002).into()); + VersionNotifyTargets::::insert(3, v3_location, (71, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // New version. - AdvertisedXcmVersion::set(3); + AdvertisedXcmVersion::set(4); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -1049,19 +1061,19 @@ fn subscription_side_upgrades_work_with_multistage_notify() { let instr1 = QueryResponse { query_id: 70, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr2 = QueryResponse { query_id: 71, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr3 = QueryResponse { query_id: 72, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let mut sent = take_sent_xcm(); @@ -1083,9 +1095,9 @@ fn subscription_side_upgrades_work_with_multistage_notify() { assert_eq!( contents, vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 4)), ] ); }); @@ -1245,3 +1257,35 @@ fn multistage_migration_works() { assert!(Pallet::::do_try_state().is_ok()); }) } + +#[test] +fn record_xcm_works() { + let balances = vec![(ALICE, INITIAL_BALANCE)]; + new_test_ext_with_balances(balances).execute_with(|| { + let message = Xcm::::builder() + .withdraw_asset((Here, SEND_AMOUNT)) + .buy_execution((Here, SEND_AMOUNT), Unlimited) + .deposit_asset(AllCounted(1), Junction::AccountId32 { network: None, id: BOB.into() }) + .build(); + // Test default values. + assert_eq!(ShouldRecordXcm::::get(), false); + assert_eq!(RecordedXcm::::get(), None); + + // By default the message won't be recorded. + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(message.clone())), + BaseXcmWeight::get() * 3, + )); + assert_eq!(RecordedXcm::::get(), None); + + // We explicitly set the record flag to true so we record the XCM. + ShouldRecordXcm::::put(true); + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(message.clone())), + BaseXcmWeight::get() * 3, + )); + assert_eq!(RecordedXcm::::get(), Some(message.into())); + }); +} diff --git a/polkadot/xcm/procedural/tests/conversion_functions.rs b/polkadot/xcm/procedural/tests/conversion_functions.rs index 5b6965167fcd318d3a7b10b3e56deeebf13ba7cb..7d2698d2cd776fe13f03a2a361edd32b552482ea 100644 --- a/polkadot/xcm/procedural/tests/conversion_functions.rs +++ b/polkadot/xcm/procedural/tests/conversion_functions.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use xcm::v2::prelude::*; +use xcm::v3::prelude::*; #[test] -fn slice_syntax_in_v2_works() { +fn slice_syntax_in_v3_works() { let old_junctions = Junctions::X2(Parachain(1), PalletInstance(1)); let new_junctions = Junctions::from([Parachain(1), PalletInstance(1)]); assert_eq!(old_junctions, new_junctions); diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index 513dfe5501ba6c6ee8c233717c86b7f24f6eeb5f..8b0030e59b5ffbb8c3af94d30368c0a824f8a119 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -21,6 +21,8 @@ // // Hence, `no_std` rather than sp-runtime. #![cfg_attr(not(feature = "std"), no_std)] +// Because of XCMv2. +#![allow(deprecated)] extern crate alloc; @@ -28,6 +30,9 @@ use derivative::Derivative; use parity_scale_codec::{Decode, DecodeLimit, Encode, Error as CodecError, Input, MaxEncodedLen}; use scale_info::TypeInfo; +#[deprecated( + note = "XCMv2 will be removed once XCMv5 is released. Please use XCMv3 or XCMv4 instead." +)] pub mod v2; pub mod v3; pub mod v4; @@ -425,6 +430,7 @@ pub type VersionedMultiAssets = VersionedAssets; #[scale_info(replace_segment("staging_xcm", "xcm"))] pub enum VersionedXcm { #[codec(index = 2)] + #[deprecated] V2(v2::Xcm), #[codec(index = 3)] V3(v3::Xcm), diff --git a/polkadot/xcm/src/tests.rs b/polkadot/xcm/src/tests.rs index 1aabbcef281d6638b4eabf3c077b5091514d07f0..4c666063f3f4706e77869b7aea5e16000f6dbc1d 100644 --- a/polkadot/xcm/src/tests.rs +++ b/polkadot/xcm/src/tests.rs @@ -158,18 +158,6 @@ fn encode_decode_versioned_multi_assets_v3() { assert_eq!(assets, decoded); } -#[test] -fn encode_decode_versioned_xcm_v2() { - let xcm = VersionedXcm::V2(v2::Xcm::<()>::new()); - let encoded = xcm.encode(); - - assert_eq!(encoded, hex_literal::hex!("0200"), "encode format changed"); - assert_eq!(encoded[0], 2, "bad version number"); - - let decoded = VersionedXcm::decode(&mut &encoded[..]).unwrap(); - assert_eq!(xcm, decoded); -} - #[test] fn encode_decode_versioned_xcm_v3() { let xcm = VersionedXcm::V3(v3::Xcm::<()>::new()); diff --git a/polkadot/xcm/src/v2/mod.rs b/polkadot/xcm/src/v2/mod.rs index 347f3f2c29206222ca546b7d543409da83cbedcf..7b6858e6a5c212cd50326390a1fa995f88f95d2d 100644 --- a/polkadot/xcm/src/v2/mod.rs +++ b/polkadot/xcm/src/v2/mod.rs @@ -15,6 +15,9 @@ // along with Cumulus. If not, see . //! # XCM Version 2 +//! +//! WARNING: DEPRECATED, please use version 3 or 4. +//! //! Version 2 of the Cross-Consensus Message format data structures. The comprehensive list of //! changes can be found in //! [this PR description](https://github.com/paritytech/polkadot/pull/3629#issue-968428279). @@ -52,8 +55,8 @@ use super::{ v3::{ BodyId as NewBodyId, BodyPart as NewBodyPart, Instruction as NewInstruction, - NetworkId as NewNetworkId, Response as NewResponse, WeightLimit as NewWeightLimit, - Xcm as NewXcm, + NetworkId as NewNetworkId, OriginKind as NewOriginKind, Response as NewResponse, + WeightLimit as NewWeightLimit, Xcm as NewXcm, }, DoubleEncoded, }; @@ -104,6 +107,18 @@ pub enum OriginKind { Xcm, } +impl From for OriginKind { + fn from(new: NewOriginKind) -> Self { + use NewOriginKind::*; + match new { + Native => Self::Native, + SovereignAccount => Self::SovereignAccount, + Superuser => Self::Superuser, + Xcm => Self::Xcm, + } + } +} + /// A global identifier of an account-bearing consensus system. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] @@ -262,6 +277,7 @@ pub const VERSION: super::Version = 2; /// An identifier for a query. pub type QueryId = u64; +/// DEPRECATED. Please use XCMv3 or XCMv4 instead. #[derive(Derivative, Default, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] @@ -1065,7 +1081,7 @@ impl TryFrom> for Instruction Self::HrmpChannelClosing { initiator, sender, recipient }, Transact { origin_kind, require_weight_at_most, call } => Self::Transact { - origin_type: origin_kind, + origin_type: origin_kind.into(), require_weight_at_most: require_weight_at_most.ref_time(), call: call.into(), }, diff --git a/polkadot/xcm/src/v3/mod.rs b/polkadot/xcm/src/v3/mod.rs index e7c57f414eb786a50f3689a3d3706632bdc4f902..8ff661a9bbac8b3a8236f783f0dc7b24129aa005 100644 --- a/polkadot/xcm/src/v3/mod.rs +++ b/polkadot/xcm/src/v3/mod.rs @@ -16,15 +16,14 @@ //! Version 3 of the Cross-Consensus Message format data structures. -use super::{ - v2::{ - Instruction as OldInstruction, Response as OldResponse, WeightLimit as OldWeightLimit, - Xcm as OldXcm, - }, - v4::{ - Instruction as NewInstruction, PalletInfo as NewPalletInfo, - QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm, - }, +#[allow(deprecated)] +use super::v2::{ + Instruction as OldInstruction, OriginKind as OldOriginKind, Response as OldResponse, + WeightLimit as OldWeightLimit, Xcm as OldXcm, +}; +use super::v4::{ + Instruction as NewInstruction, PalletInfo as NewPalletInfo, + QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm, }; use crate::DoubleEncoded; use alloc::{vec, vec::Vec}; @@ -53,11 +52,46 @@ pub use multilocation::{ Ancestor, AncestorThen, InteriorMultiLocation, Location, MultiLocation, Parent, ParentThen, }; pub use traits::{ - send_xcm, validate_send, Error, ExecuteXcm, Outcome, PreparedMessage, Result, SendError, - SendResult, SendXcm, Weight, XcmHash, + send_xcm, validate_send, Error, ExecuteXcm, GetWeight, Outcome, PreparedMessage, Result, + SendError, SendResult, SendXcm, Weight, XcmHash, }; -// These parts of XCM v2 are unchanged in XCM v3, and are re-imported here. -pub use super::v2::{GetWeight, OriginKind}; + +/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`. +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] +#[scale_info(replace_segment("staging_xcm", "xcm"))] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +pub enum OriginKind { + /// Origin should just be the native dispatch origin representation for the sender in the + /// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin + /// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a + /// primary/native dispatch origin form. + Native, + + /// Origin should just be the standard account-based origin with the sovereign account of + /// the sender. For Cumulus/Frame chains, this is the `Signed` origin. + SovereignAccount, + + /// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin. + /// This will not usually be an available option. + Superuser, + + /// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be + /// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be + /// the `pallet_xcm::Origin::Xcm` type. + Xcm, +} + +impl From for OriginKind { + fn from(old: OldOriginKind) -> Self { + use OldOriginKind::*; + match old { + Native => Self::Native, + SovereignAccount => Self::SovereignAccount, + Superuser => Self::Superuser, + Xcm => Self::Xcm, + } + } +} /// This module's XCM version. pub const VERSION: super::Version = 3; @@ -1310,6 +1344,7 @@ impl TryFrom for Response { } // Convert from a v2 XCM to a v3 XCM. +#[allow(deprecated)] impl TryFrom> for Xcm { type Error = (); fn try_from(old_xcm: OldXcm) -> result::Result { @@ -1500,7 +1535,7 @@ impl TryFrom> for Instruction { HrmpChannelClosing { initiator, sender, recipient } => Self::HrmpChannelClosing { initiator, sender, recipient }, Transact { origin_type, require_weight_at_most, call } => Self::Transact { - origin_kind: origin_type, + origin_kind: origin_type.into(), require_weight_at_most: Weight::from_parts( require_weight_at_most, DEFAULT_PROOF_SIZE, @@ -1572,118 +1607,6 @@ impl TryFrom> for Instruction { #[cfg(test)] mod tests { use super::{prelude::*, *}; - use crate::v2::{ - Junctions::Here as OldHere, MultiAssetFilter as OldMultiAssetFilter, - WildMultiAsset as OldWildMultiAsset, - }; - - #[test] - fn basic_roundtrip_works() { - let xcm = Xcm::<()>(vec![TransferAsset { - assets: (Here, 1u128).into(), - beneficiary: Here.into(), - }]); - let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset { - assets: (OldHere, 1).into(), - beneficiary: OldHere.into(), - }]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn teleport_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - ReceiveTeleportedAsset((Here, 1u128).into()), - ClearOrigin, - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm: OldXcm<()> = OldXcm::<()>(vec![ - OldInstruction::ReceiveTeleportedAsset((OldHere, 1).into()), - OldInstruction::ClearOrigin, - OldInstruction::DepositAsset { - assets: crate::v2::MultiAssetFilter::Wild(crate::v2::WildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn reserve_deposit_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - ReserveAssetDeposited((Here, 1u128).into()), - ClearOrigin, - BuyExecution { - fees: (Here, 1u128).into(), - weight_limit: Some(Weight::from_parts(1, DEFAULT_PROOF_SIZE)).into(), - }, - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::ReserveAssetDeposited((OldHere, 1).into()), - OldInstruction::ClearOrigin, - OldInstruction::BuyExecution { - fees: (OldHere, 1).into(), - weight_limit: Some(1).into(), - }, - OldInstruction::DepositAsset { - assets: crate::v2::MultiAssetFilter::Wild(crate::v2::WildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn deposit_asset_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - WithdrawAsset((Here, 1u128).into()), - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::WithdrawAsset((OldHere, 1).into()), - OldInstruction::DepositAsset { - assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn deposit_reserve_asset_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - WithdrawAsset((Here, 1u128).into()), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - dest: Here.into(), - xcm: Xcm::<()>(vec![]), - }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::WithdrawAsset((OldHere, 1).into()), - OldInstruction::DepositReserveAsset { - assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::All), - max_assets: 1, - dest: OldHere.into(), - xcm: OldXcm::<()>(vec![]), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } #[test] fn decoding_respects_limit() { diff --git a/polkadot/xcm/src/v3/traits.rs b/polkadot/xcm/src/v3/traits.rs index cfe387df1a86c3aa21da69ce37eadb307df1c51b..680e0bacd0c9b96832b646d2896cdf4ec2c064e0 100644 --- a/polkadot/xcm/src/v3/traits.rs +++ b/polkadot/xcm/src/v3/traits.rs @@ -25,6 +25,11 @@ pub use sp_weights::Weight; use super::*; +// A simple trait to get the weight of some object. +pub trait GetWeight { + fn weight(&self) -> sp_weights::Weight; +} + /// Error codes used in XCM. The first errors codes have explicit indices and are part of the XCM /// format. Those trailing are merely part of the XCM implementation; there is no expectation that /// they will retain the same index over time. diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs index 77b6d915fcb5fa902e5168e46b38cdb677f98cbf..e1ca60087b19024e88a9a1345f1e00a624e77fda 100644 --- a/polkadot/xcm/src/v4/mod.rs +++ b/polkadot/xcm/src/v4/mod.rs @@ -16,7 +16,7 @@ //! Version 4 of the Cross-Consensus Message format data structures. -pub use super::v2::GetWeight; +pub use super::v3::GetWeight; use super::v3::{ Instruction as OldInstruction, PalletInfo as OldPalletInfo, QueryResponseInfo as OldQueryResponseInfo, Response as OldResponse, Xcm as OldXcm, diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml index 997ca99fb12c831ea63d7dbb199f2c029dabb495..707e4aac7968a3032f717e802122903014d669ef 100644 --- a/polkadot/xcm/xcm-builder/Cargo.toml +++ b/polkadot/xcm/xcm-builder/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] impl-trait-for-tuples = "0.2.1" -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } xcm = { package = "staging-xcm", path = "..", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false } diff --git a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs index 21c828922b333e85e9332d16c768aef0d34cbd9f..45a0e2bdca2862c2142f3ecae17ae19ac6ec1839 100644 --- a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs @@ -19,7 +19,11 @@ use super::MintLocation; use frame_support::traits::{ tokens::{ - fungible, Fortitude::Polite, Precision::Exact, Preservation::Preserve, Provenance::Minted, + fungible, + Fortitude::Polite, + Precision::Exact, + Preservation::{Expendable, Preserve}, + Provenance::Minted, }, Get, }; @@ -100,7 +104,7 @@ impl< } fn reduce_checked(checking_account: AccountId, amount: Fungible::Balance) { - let ok = Fungible::burn_from(&checking_account, amount, Exact, Polite).is_ok(); + let ok = Fungible::burn_from(&checking_account, amount, Expendable, Exact, Polite).is_ok(); debug_assert!(ok, "`can_reduce_checked` must have returned `true` immediately prior; qed"); } } @@ -210,7 +214,7 @@ impl< let amount = Matcher::matches_fungible(what).ok_or(MatchError::AssetNotHandled)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Fungible::burn_from(&who, amount, Exact, Polite) + Fungible::burn_from(&who, amount, Expendable, Exact, Polite) .map_err(|error| XcmError::FailedToTransactAsset(error.into()))?; Ok(what.clone().into()) } diff --git a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs index b4c418ebf1c9cf7d9d26540e998f966665993585..88bbf01d9e1f8c35d2b884be6a0c5a43f24c1073 100644 --- a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs @@ -18,7 +18,11 @@ use frame_support::traits::{ tokens::{ - fungibles, Fortitude::Polite, Precision::Exact, Preservation::Preserve, Provenance::Minted, + fungibles, + Fortitude::Polite, + Precision::Exact, + Preservation::{Expendable, Preserve}, + Provenance::Minted, }, Contains, Get, }; @@ -176,7 +180,8 @@ impl< } fn reduce_checked(asset_id: Assets::AssetId, amount: Assets::Balance) { let checking_account = CheckingAccount::get(); - let ok = Assets::burn_from(asset_id, &checking_account, amount, Exact, Polite).is_ok(); + let ok = Assets::burn_from(asset_id, &checking_account, amount, Expendable, Exact, Polite) + .is_ok(); debug_assert!(ok, "`can_reduce_checked` must have returned `true` immediately prior; qed"); } } @@ -295,7 +300,7 @@ impl< let (asset_id, amount) = Matcher::matches_fungibles(what)?; let who = AccountIdConverter::convert_location(who) .ok_or(MatchError::AccountIdConversionFailed)?; - Assets::burn_from(asset_id, &who, amount, Exact, Polite) + Assets::burn_from(asset_id, &who, amount, Expendable, Exact, Polite) .map_err(|e| XcmError::FailedToTransactAsset(e.into()))?; Ok(what.clone().into()) } diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index 1ba38d0db836b4e73e3f7785cf0e96f079666441..cc06c298a418d56f6a70d58b5f24bf8ccb14db5d 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -120,7 +120,9 @@ mod process_xcm_message; pub use process_xcm_message::ProcessXcmMessage; mod routing; -pub use routing::{EnsureDecodableXcm, EnsureDelivery, WithTopicSource, WithUniqueTopic}; +pub use routing::{ + EnsureDecodableXcm, EnsureDelivery, InspectMessageQueues, WithTopicSource, WithUniqueTopic, +}; mod transactional; pub use transactional::FrameTransactionalProcessor; diff --git a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs index 7760274f6e2451f1b5f695884086a31cd36f3209..449cda3d2323372ea5fddbb9a08d81dbadeba632 100644 --- a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs +++ b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs @@ -124,7 +124,7 @@ mod tests { }; use parity_scale_codec::Encode; use polkadot_test_runtime::*; - use xcm::{v2, v3, VersionedXcm}; + use xcm::{v3, v4, VersionedXcm}; const ORIGIN: Junction = Junction::OnlyChild; /// The processor to use for tests. @@ -134,8 +134,8 @@ mod tests { #[test] fn process_message_trivial_works() { // ClearOrigin works. - assert!(process(v2_xcm(true)).unwrap()); assert!(process(v3_xcm(true)).unwrap()); + assert!(process(v4_xcm(true)).unwrap()); } #[test] @@ -194,7 +194,7 @@ mod tests { #[test] fn process_message_overweight_fails() { - for msg in [v3_xcm(true), v3_xcm(false), v3_xcm(false), v2_xcm(false)] { + for msg in [v4_xcm(true), v4_xcm(false), v4_xcm(false), v3_xcm(false)] { let msg = &msg.encode()[..]; // Errors if we stay below a weight limit of 1000. @@ -216,7 +216,7 @@ mod tests { } } - fn v2_xcm(success: bool) -> VersionedXcm { + fn v3_xcm(success: bool) -> VersionedXcm { let instr = if success { v3::Instruction::::ClearOrigin } else { @@ -225,13 +225,13 @@ mod tests { VersionedXcm::V3(v3::Xcm::(vec![instr])) } - fn v3_xcm(success: bool) -> VersionedXcm { + fn v4_xcm(success: bool) -> VersionedXcm { let instr = if success { - v2::Instruction::::ClearOrigin + v4::Instruction::::ClearOrigin } else { - v2::Instruction::::Trap(1) + v4::Instruction::::Trap(1) }; - VersionedXcm::V2(v2::Xcm::(vec![instr])) + VersionedXcm::V4(v4::Xcm::(vec![instr])) } fn process(msg: VersionedXcm) -> Result { diff --git a/polkadot/xcm/xcm-builder/src/routing.rs b/polkadot/xcm/xcm-builder/src/routing.rs index 921b9ac5922eaf37e65151b8e3a115e010b0abcb..5c284aaf1475fce0fba7e5cfa042428ceff8268d 100644 --- a/polkadot/xcm/xcm-builder/src/routing.rs +++ b/polkadot/xcm/xcm-builder/src/routing.rs @@ -18,7 +18,7 @@ use frame_system::unique; use parity_scale_codec::Encode; -use sp_std::{marker::PhantomData, result::Result}; +use sp_std::{marker::PhantomData, result::Result, vec::Vec}; use xcm::prelude::*; use xcm_executor::{traits::FeeReason, FeesMode}; @@ -60,6 +60,11 @@ impl SendXcm for WithUniqueTopic { Ok(unique_id) } } +impl InspectMessageQueues for WithUniqueTopic { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + Inner::get_messages() + } +} pub trait SourceTopic { fn source_topic(entropy: impl Encode) -> XcmHash; @@ -140,6 +145,26 @@ impl EnsureDelivery for Tuple { } } +/// Inspects messages in queues. +/// Meant to be used in runtime APIs, not in runtimes. +pub trait InspectMessageQueues { + /// Get queued messages and their destinations. + fn get_messages() -> Vec<(VersionedLocation, Vec>)>; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl InspectMessageQueues for Tuple { + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + let mut messages = Vec::new(); + + for_tuples!( #( + messages.append(&mut Tuple::get_messages()); + )* ); + + messages + } +} + /// A wrapper router that attempts to *encode* and *decode* passed XCM `message` to ensure that the /// receiving side will be able to decode, at least with the same XCM version. /// diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index 7532b97d97b3ba0a8c4ac648d68accc3cadfd6cd..f45650ec5404d14780a3bff3d9bbef0d72a57a25 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -748,6 +748,7 @@ impl Config for TestConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } pub fn fungible_multi_asset(location: Location, amount: u128) -> Asset { diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 019113a12b2fb127142c9e59d00ef0faca84b688..076ff4184f0cb9c8ba0b7a633534384e9dd7ef7c 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -54,7 +54,6 @@ impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; type AccountId = AccountId; - type BlockHashCount = ConstU32<256>; type Lookup = sp_runtime::traits::IdentityLookup; } @@ -221,6 +220,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } parameter_types! { diff --git a/polkadot/xcm/xcm-builder/src/universal_exports.rs b/polkadot/xcm/xcm-builder/src/universal_exports.rs index d0e3ef3032ea1c0aeae698d1e275d4a401a7bb0d..04ceb7e51688994b65701419020ffd5fd5bfdcd7 100644 --- a/polkadot/xcm/xcm-builder/src/universal_exports.rs +++ b/polkadot/xcm/xcm-builder/src/universal_exports.rs @@ -16,6 +16,7 @@ //! Traits and utilities to help with origin mutation and bridging. +use crate::InspectMessageQueues; use frame_support::{ensure, traits::Get}; use parity_scale_codec::{Decode, Encode}; use sp_std::{convert::TryInto, marker::PhantomData, prelude::*}; @@ -335,6 +336,14 @@ impl InspectMessageQueues + for SovereignPaidRemoteExporter +{ + fn get_messages() -> Vec<(VersionedLocation, Vec>)> { + Router::get_messages() + } +} + pub trait DispatchBlob { /// Takes an incoming blob from over some point-to-point link (usually from some sort of /// inter-consensus bridge) and then does what needs to be done with it. Usually this means diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 46ec23beebc1e33c1f3e0d3e25363944f4836cdc..7f7ff17e2115a96f0f7f3e53191759b4da6d8f20 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -74,10 +74,6 @@ pub type TestXcmRouter = EnsureDecodableXcm; pub const UNITS: Balance = 1_000_000_000_000; pub const CENTS: Balance = UNITS / 30_000; -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -89,7 +85,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockWeights = (); type BlockLength = (); type Version = (); @@ -209,6 +204,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-executor/Cargo.toml b/polkadot/xcm/xcm-executor/Cargo.toml index aebc768bb906fd38d372d6d735a9e6bc0390ae9b..64b2d405b9068213d88582ec79ca2897d78dcc1f 100644 --- a/polkadot/xcm/xcm-executor/Cargo.toml +++ b/polkadot/xcm/xcm-executor/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" environmental = { version = "1.1.4", default-features = false } -parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } xcm = { package = "staging-xcm", path = "..", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } diff --git a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml index 9c9c53f0ee1ba497f044477ec857afb6774a1f05..37c2117e7b06fc62f33e71c3c57164caf26d4c9b 100644 --- a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml +++ b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml @@ -11,7 +11,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } frame-support = { path = "../../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../../substrate/frame/system" } futures = "0.3.30" diff --git a/polkadot/xcm/xcm-executor/src/config.rs b/polkadot/xcm/xcm-executor/src/config.rs index b296d32ca2adb6761f815aa74397211e3bc17d5f..63b113bc250fa34db10336f7575771bbdbf76b01 100644 --- a/polkadot/xcm/xcm-executor/src/config.rs +++ b/polkadot/xcm/xcm-executor/src/config.rs @@ -17,8 +17,8 @@ use crate::traits::{ AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, DropAssets, ExportXcm, FeeManager, HandleHrmpChannelAccepted, HandleHrmpChannelClosing, - HandleHrmpNewChannelOpenRequest, OnResponse, ProcessTransaction, ShouldExecute, TransactAsset, - VersionChangeNotifier, WeightBounds, WeightTrader, + HandleHrmpNewChannelOpenRequest, OnResponse, ProcessTransaction, RecordXcm, ShouldExecute, + TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, }; use frame_support::{ dispatch::{GetDispatchInfo, Parameter, PostDispatchInfo}, @@ -122,4 +122,6 @@ pub trait Config { type HrmpChannelAcceptedHandler: HandleHrmpChannelAccepted; /// Allows optional logic execution for the `HrmpChannelClosing` XCM notification. type HrmpChannelClosingHandler: HandleHrmpChannelClosing; + /// Allows recording the last executed XCM (used by dry-run runtime APIs). + type XcmRecorder: RecordXcm; } diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index a7052328da00140faf90d5391f27d126dc953a27..e0b8a8a9c73e4aba1274993d23ac27a77c2a6c78 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -37,6 +37,8 @@ use traits::{ XcmAssetTransfers, }; +pub use traits::RecordXcm; + mod assets; pub use assets::AssetsInHolding; mod config; @@ -211,6 +213,13 @@ impl ExecuteXcm for XcmExecutor. + +//! Trait for recording XCMs and a dummy implementation. + +use xcm::latest::Xcm; + +/// Trait for recording XCMs. +pub trait RecordXcm { + /// Whether or not we should record incoming XCMs. + fn should_record() -> bool; + /// Enable or disable recording. + fn set_record_xcm(enabled: bool); + /// Get recorded XCM. + /// Returns `None` if no message was sent, or if recording was off. + fn recorded_xcm() -> Option>; + /// Record `xcm`. + fn record(xcm: Xcm<()>); +} + +impl RecordXcm for () { + fn should_record() -> bool { + false + } + + fn set_record_xcm(_: bool) {} + + fn recorded_xcm() -> Option> { + None + } + + fn record(_: Xcm<()>) {} +} diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml b/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml index 30c7c0bac14f7936d57ec5c86f94bc24ba17013f..6fa0236dfb41d5e2a4ec2749a402a8f73be60eb4 100644 --- a/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml @@ -11,7 +11,7 @@ description = "XCM fee payment runtime API" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } @@ -26,15 +26,46 @@ sp-weights = { path = "../../../substrate/primitives/weights", default-features xcm = { package = "staging-xcm", path = "../", default-features = false } frame-support = { path = "../../../substrate/frame/support", default-features = false } +[dev-dependencies] +frame-system = { path = "../../../substrate/frame/system", default-features = false } +pallet-xcm = { path = "../pallet-xcm", default-features = false } +xcm-builder = { package = "staging-xcm-builder", path = "../xcm-builder", default-features = false } +sp-io = { path = "../../../substrate/primitives/io", default-features = false } +pallet-balances = { path = "../../../substrate/frame/balances", default-features = false } +pallet-assets = { path = "../../../substrate/frame/assets", default-features = false } +xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false } +frame-executive = { path = "../../../substrate/frame/executive", default-features = false } +log = { workspace = true } +env_logger = "0.9.0" + [features] default = ["std"] std = [ "codec/std", + "frame-executive/std", "frame-support/std", + "frame-system/std", + "log/std", + "pallet-assets/std", + "pallet-balances/std", + "pallet-xcm/std", "scale-info/std", "sp-api/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-weights/std", + "xcm-builder/std", + "xcm-executor/std", "xcm/std", ] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/src/dry_run.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/src/dry_run.rs new file mode 100644 index 0000000000000000000000000000000000000000..62a422d6efeb0928e4f279798382dd139d95ee0a --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/src/dry_run.rs @@ -0,0 +1,83 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Runtime API definition for dry-running XCM-related extrinsics. +//! This API can be used to simulate XCMs and, for example, find the fees +//! that need to be paid. + +use codec::{Decode, Encode}; +use frame_support::pallet_prelude::{DispatchResult, TypeInfo}; +use sp_runtime::traits::Block as BlockT; +use sp_std::vec::Vec; +use xcm::prelude::*; + +/// Effects of dry-running an extrinsic. +#[derive(Encode, Decode, Debug, TypeInfo)] +pub struct ExtrinsicDryRunEffects { + /// The result of executing the extrinsic. + pub execution_result: DispatchResult, + /// The list of events fired by the extrinsic. + pub emitted_events: Vec, + /// The local XCM that was attempted to be executed, if any. + pub local_xcm: Option>, + /// The list of XCMs that were queued for sending. + pub forwarded_xcms: Vec<(VersionedLocation, Vec>)>, +} + +/// Effects of dry-running an XCM program. +#[derive(Encode, Decode, Debug, TypeInfo)] +pub struct XcmDryRunEffects { + /// The outcome of the XCM program execution. + pub execution_result: Outcome, + /// List of events fired by the XCM program execution. + pub emitted_events: Vec, + /// List of queued messages for sending. + pub forwarded_xcms: Vec<(VersionedLocation, Vec>)>, +} + +sp_api::decl_runtime_apis! { + /// API for dry-running extrinsics and XCM programs to get the programs that need to be passed to the fees API. + /// + /// All calls return a vector of tuples (location, xcm) where each "xcm" is executed in "location". + /// If there's local execution, the location will be "Here". + /// This vector can be used to calculate both execution and delivery fees. + /// + /// Extrinsics or XCMs might fail when executed, this doesn't mean the result of these calls will be an `Err`. + /// In those cases, there might still be a valid result, with the execution error inside it. + /// The only reasons why these calls might return an error are listed in the [`Error`] enum. + pub trait XcmDryRunApi { + /// Dry run extrinsic. + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, Error>; + + /// Dry run XCM program + fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm) -> Result, Error>; + } +} + +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] +pub enum Error { + /// An API call is unsupported. + #[codec(index = 0)] + Unimplemented, + + /// Converting a versioned data structure from one version to another failed. + #[codec(index = 1)] + VersionedConversionFailed, + + /// Extrinsic was invalid. + #[codec(index = 2)] + InvalidExtrinsic, +} diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/src/fees.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/src/fees.rs new file mode 100644 index 0000000000000000000000000000000000000000..572d4edf533865e66299eba7bd0d22a890547603 --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/src/fees.rs @@ -0,0 +1,97 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Runtime API definition for getting XCM fees. + +use codec::{Decode, Encode}; +use frame_support::pallet_prelude::TypeInfo; +use sp_std::vec::Vec; +use sp_weights::Weight; +use xcm::{Version, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; + +sp_api::decl_runtime_apis! { + /// A trait of XCM payment API. + /// + /// API provides functionality for obtaining: + /// + /// * the weight required to execute an XCM message, + /// * a list of acceptable `AssetId`s for message execution payment, + /// * the cost of the weight in the specified acceptable `AssetId`. + /// * the fees for an XCM message delivery. + /// + /// To determine the execution weight of the calls required for + /// [`xcm::latest::Instruction::Transact`] instruction, `TransactionPaymentCallApi` can be used. + pub trait XcmPaymentApi { + /// Returns a list of acceptable payment assets. + /// + /// # Arguments + /// + /// * `xcm_version`: Version. + fn query_acceptable_payment_assets(xcm_version: Version) -> Result, Error>; + + /// Returns a weight needed to execute a XCM. + /// + /// # Arguments + /// + /// * `message`: `VersionedXcm`. + fn query_xcm_weight(message: VersionedXcm<()>) -> Result; + + /// Converts a weight into a fee for the specified `AssetId`. + /// + /// # Arguments + /// + /// * `weight`: convertible `Weight`. + /// * `asset`: `VersionedAssetId`. + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result; + + /// Get delivery fees for sending a specific `message` to a `destination`. + /// These always come in a specific asset, defined by the chain. + /// + /// # Arguments + /// * `message`: The message that'll be sent, necessary because most delivery fees are based on the + /// size of the message. + /// * `destination`: The destination to send the message to. Different destinations may use + /// different senders that charge different fees. + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result; + } +} + +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] +pub enum Error { + /// An API part is unsupported. + #[codec(index = 0)] + Unimplemented, + + /// Converting a versioned data structure from one version to another failed. + #[codec(index = 1)] + VersionedConversionFailed, + + /// XCM message weight calculation failed. + #[codec(index = 2)] + WeightNotComputable, + + /// XCM version not able to be handled. + #[codec(index = 3)] + UnhandledXcmVersion, + + /// The given asset is not handled as a fee asset. + #[codec(index = 4)] + AssetNotFound, + + /// Destination is known to be unroutable. + #[codec(index = 5)] + Unroutable, +} diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs index 20bf9236f1fbbb46ca50a1b42d6dc4e519a5ae1a..616ee4c2eccb0aeed1cdb5e2aa524855d8b2df82 100644 --- a/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs @@ -14,86 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Runtime API definition for xcm transaction payment. +//! Runtime APIs for estimating xcm fee payment. +//! This crate offers two APIs, one for estimating fees, +//! which can be used for any type of message, and another one +//! for returning the specific messages used for transfers, a common +//! feature. +//! Users of these APIs should call the transfers API and pass the result to the +//! fees API. #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode}; -use frame_support::pallet_prelude::TypeInfo; -use sp_std::vec::Vec; -use sp_weights::Weight; -use xcm::{Version, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; - -sp_api::decl_runtime_apis! { - /// A trait of XCM payment API. - /// - /// API provides functionality for obtaining: - /// - /// * the weight required to execute an XCM message, - /// * a list of acceptable `AssetId`s for message execution payment, - /// * the cost of the weight in the specified acceptable `AssetId`. - /// * the fees for an XCM message delivery. - /// - /// To determine the execution weight of the calls required for - /// [`xcm::latest::Instruction::Transact`] instruction, `TransactionPaymentCallApi` can be used. - pub trait XcmPaymentApi { - /// Returns a list of acceptable payment assets. - /// - /// # Arguments - /// - /// * `xcm_version`: Version. - fn query_acceptable_payment_assets(xcm_version: Version) -> Result, Error>; - - /// Returns a weight needed to execute a XCM. - /// - /// # Arguments - /// - /// * `message`: `VersionedXcm`. - fn query_xcm_weight(message: VersionedXcm<()>) -> Result; - - /// Converts a weight into a fee for the specified `AssetId`. - /// - /// # Arguments - /// - /// * `weight`: convertible `Weight`. - /// * `asset`: `VersionedAssetId`. - fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result; - - /// Get delivery fees for sending a specific `message` to a `destination`. - /// These always come in a specific asset, defined by the chain. - /// - /// # Arguments - /// * `message`: The message that'll be sent, necessary because most delivery fees are based on the - /// size of the message. - /// * `destination`: The destination to send the message to. Different destinations may use - /// different senders that charge different fees. - fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result; - } -} - -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] -pub enum Error { - /// An API part is unsupported. - #[codec(index = 0)] - Unimplemented, - - /// Converting a versioned data structure from one version to another failed. - #[codec(index = 1)] - VersionedConversionFailed, - - /// XCM message weight calculation failed. - #[codec(index = 2)] - WeightNotComputable, - - /// XCM version not able to be handled. - #[codec(index = 3)] - UnhandledXcmVersion, - - /// The given asset is not handled as a fee asset. - #[codec(index = 4)] - AssetNotFound, - - /// Destination is known to be unroutable. - #[codec(index = 5)] - Unroutable, -} +/// Dry-run API. +/// Given an extrinsic or an XCM program, it returns the outcome of its execution. +pub mod dry_run; +/// Fee estimation API. +/// Given an XCM program, it will return the fees needed to execute it properly or send it. +pub mod fees; diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/tests/fee_estimation.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/tests/fee_estimation.rs new file mode 100644 index 0000000000000000000000000000000000000000..25a68090c22f5da9c86f8e40c0457d26880f44fe --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/tests/fee_estimation.rs @@ -0,0 +1,377 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Tests for using both the XCM fee payment API and the dry-run API. + +use frame_support::{ + dispatch::DispatchInfo, + pallet_prelude::{DispatchClass, Pays}, +}; +use sp_api::ProvideRuntimeApi; +use sp_runtime::testing::H256; +use xcm::prelude::*; +use xcm_fee_payment_runtime_api::{dry_run::XcmDryRunApi, fees::XcmPaymentApi}; + +mod mock; +use mock::{ + extra, fake_message_hash, new_test_ext_with_balances, new_test_ext_with_balances_and_assets, + DeliveryFees, ExistentialDeposit, HereLocation, RuntimeCall, RuntimeEvent, TestClient, TestXt, +}; + +// Scenario: User `1` in the local chain (id 2000) wants to transfer assets to account `[0u8; 32]` +// on "AssetHub". He wants to make sure he has enough for fees, so before he calls the +// `transfer_asset` extrinsic to do the transfer, he decides to use the `XcmDryRunApi` and +// `XcmPaymentApi` runtime APIs to estimate fees. This uses a teleport because we're dealing with +// the native token of the chain, which is registered on "AssetHub". The fees are sent as a reserve +// asset transfer, since they're paid in the relay token. +// +// Teleport Parachain(2000) Token +// Reserve Asset Transfer Relay Token for fees +// Parachain(2000) -------------------------------------------> Parachain(1000) +#[test] +fn fee_estimation_for_teleport() { + let _ = env_logger::builder().is_test(true).try_init(); + let who = 1; // AccountId = u64. + let balances = vec![(who, 100 + DeliveryFees::get() + ExistentialDeposit::get())]; + let assets = vec![(1, who, 50)]; + new_test_ext_with_balances_and_assets(balances, assets).execute_with(|| { + let client = TestClient; + let runtime_api = client.runtime_api(); + let extrinsic = TestXt::new( + RuntimeCall::XcmPallet(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::from((Parent, Parachain(1000)))), + beneficiary: Box::new(VersionedLocation::from(AccountId32 { + id: [0u8; 32], + network: None, + })), + assets: Box::new(VersionedAssets::from(vec![ + (Here, 100u128).into(), + (Parent, 20u128).into(), + ])), + fee_asset_item: 1, // Fees are paid with the RelayToken + weight_limit: Unlimited, + }), + Some((who, extra())), + ); + let dry_run_effects = + runtime_api.dry_run_extrinsic(H256::zero(), extrinsic).unwrap().unwrap(); + + assert_eq!( + dry_run_effects.local_xcm, + Some(VersionedXcm::from( + Xcm::builder_unsafe() + .withdraw_asset((Parent, 20u128)) + .burn_asset((Parent, 20u128)) + .withdraw_asset((Here, 100u128)) + .burn_asset((Here, 100u128)) + .build() + )), + ); + let send_destination = Location::new(1, [Parachain(1000)]); + let send_message = Xcm::<()>::builder_unsafe() + .withdraw_asset((Parent, 20u128)) + .buy_execution((Parent, 20u128), Unlimited) + .receive_teleported_asset(((Parent, Parachain(2000)), 100u128)) + .clear_origin() + .deposit_asset(AllCounted(2), [0u8; 32]) + .build(); + assert_eq!( + dry_run_effects.forwarded_xcms, + vec![( + VersionedLocation::from(send_destination.clone()), + vec![VersionedXcm::from(send_message.clone())], + ),], + ); + + assert_eq!( + dry_run_effects.emitted_events, + vec![ + RuntimeEvent::System(frame_system::Event::NewAccount { + account: 8660274132218572653 // TODO: Why is this not `1`? + }), + RuntimeEvent::Balances(pallet_balances::Event::Endowed { + account: 8660274132218572653, + free_balance: 100 + }), + RuntimeEvent::Balances(pallet_balances::Event::Minted { + who: 8660274132218572653, + amount: 100 + }), + RuntimeEvent::AssetsPallet(pallet_assets::Event::Burned { + asset_id: 1, + owner: 1, + balance: 20 + }), + RuntimeEvent::Balances(pallet_balances::Event::Burned { who: 1, amount: 100 }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { + outcome: Outcome::Complete { used: Weight::from_parts(400, 40) }, + }), + RuntimeEvent::Balances(pallet_balances::Event::Burned { who: 1, amount: 20 }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::FeesPaid { + paying: AccountIndex64 { index: 1, network: None }.into(), + fees: (Here, 20u128).into(), + }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { + origin: AccountIndex64 { index: 1, network: None }.into(), + destination: (Parent, Parachain(1000)).into(), + message: send_message.clone(), + message_id: fake_message_hash(&send_message), + }), + RuntimeEvent::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { + weight: Weight::from_parts(107074070, 0), /* Will break if weights get + * updated. */ + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + } + }), + ] + ); + + // Weighing the local program is not relevant for extrinsics that already + // take this weight into account. + // In this case, we really only care about delivery fees. + let local_xcm = dry_run_effects.local_xcm.unwrap(); + + // We get a double result since the actual call returns a result and the runtime api returns + // results. + let weight = + runtime_api.query_xcm_weight(H256::zero(), local_xcm.clone()).unwrap().unwrap(); + assert_eq!(weight, Weight::from_parts(400, 40)); + let execution_fees = runtime_api + .query_weight_to_asset_fee( + H256::zero(), + weight, + VersionedAssetId::from(AssetId(HereLocation::get())), + ) + .unwrap() + .unwrap(); + assert_eq!(execution_fees, 440); + + let mut forwarded_xcms_iter = dry_run_effects.forwarded_xcms.into_iter(); + + let (destination, remote_messages) = forwarded_xcms_iter.next().unwrap(); + let remote_message = &remote_messages[0]; + + let delivery_fees = runtime_api + .query_delivery_fees(H256::zero(), destination.clone(), remote_message.clone()) + .unwrap() + .unwrap(); + assert_eq!(delivery_fees, VersionedAssets::from((Here, 20u128))); + + // This would have to be the runtime API of the destination, + // which we have the location for. + // If I had a mock runtime configured for "AssetHub" then I would use the + // runtime APIs from that. + let remote_execution_weight = runtime_api + .query_xcm_weight(H256::zero(), remote_message.clone()) + .unwrap() + .unwrap(); + let remote_execution_fees = runtime_api + .query_weight_to_asset_fee( + H256::zero(), + remote_execution_weight, + VersionedAssetId::from(AssetId(HereLocation::get())), + ) + .unwrap() + .unwrap(); + assert_eq!(remote_execution_fees, 550); + + // Now we know that locally we need to use `execution_fees` and + // `delivery_fees`. + // On the message we forward to the destination, we need to + // put `remote_execution_fees` in `BuyExecution`. + // For the `transfer_assets` extrinsic, it just means passing the correct amount + // of fees in the parameters. + }); +} + +// Same scenario as in `fee_estimation_for_teleport`, but the user in parachain 2000 wants +// to send relay tokens over to parachain 1000. +// +// Reserve Asset Transfer Relay Token +// Reserve Asset Transfer Relay Token for fees +// Parachain(2000) -------------------------------------------> Parachain(1000) +#[test] +fn dry_run_reserve_asset_transfer() { + let _ = env_logger::builder().is_test(true).try_init(); + let who = 1; // AccountId = u64. + // Native token used for fees. + let balances = vec![(who, DeliveryFees::get() + ExistentialDeposit::get())]; + // Relay token is the one we want to transfer. + let assets = vec![(1, who, 100)]; // id, account_id, balance. + new_test_ext_with_balances_and_assets(balances, assets).execute_with(|| { + let client = TestClient; + let runtime_api = client.runtime_api(); + let extrinsic = TestXt::new( + RuntimeCall::XcmPallet(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::from((Parent, Parachain(1000)))), + beneficiary: Box::new(VersionedLocation::from(AccountId32 { + id: [0u8; 32], + network: None, + })), + assets: Box::new(VersionedAssets::from((Parent, 100u128))), + fee_asset_item: 0, + weight_limit: Unlimited, + }), + Some((who, extra())), + ); + let dry_run_effects = + runtime_api.dry_run_extrinsic(H256::zero(), extrinsic).unwrap().unwrap(); + + assert_eq!( + dry_run_effects.local_xcm, + Some(VersionedXcm::from( + Xcm::builder_unsafe() + .withdraw_asset((Parent, 100u128)) + .burn_asset((Parent, 100u128)) + .build() + )), + ); + + // In this case, the transfer type is `DestinationReserve`, so the remote xcm just withdraws + // the assets. + let send_destination = Location::new(1, Parachain(1000)); + let send_message = Xcm::<()>::builder_unsafe() + .withdraw_asset((Parent, 100u128)) + .clear_origin() + .buy_execution((Parent, 100u128), Unlimited) + .deposit_asset(AllCounted(1), [0u8; 32]) + .build(); + assert_eq!( + dry_run_effects.forwarded_xcms, + vec![( + VersionedLocation::from(send_destination.clone()), + vec![VersionedXcm::from(send_message.clone())], + ),], + ); + + assert_eq!( + dry_run_effects.emitted_events, + vec![ + RuntimeEvent::AssetsPallet(pallet_assets::Event::Burned { + asset_id: 1, + owner: 1, + balance: 100 + }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { + outcome: Outcome::Complete { used: Weight::from_parts(200, 20) } + }), + RuntimeEvent::Balances(pallet_balances::Event::Burned { who: 1, amount: 20 }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::FeesPaid { + paying: AccountIndex64 { index: 1, network: None }.into(), + fees: (Here, 20u128).into() + }), + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { + origin: AccountIndex64 { index: 1, network: None }.into(), + destination: send_destination.clone(), + message: send_message.clone(), + message_id: fake_message_hash(&send_message), + }), + RuntimeEvent::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { + weight: Weight::from_parts(107074066, 0), /* Will break if weights get + * updated. */ + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + } + }), + ] + ); + }); +} + +#[test] +fn dry_run_xcm() { + let _ = env_logger::builder().is_test(true).try_init(); + let who = 1; // AccountId = u64. + let transfer_amount = 100u128; + // We need to build the XCM to weigh it and then build the real XCM that can pay for fees. + let inner_xcm = Xcm::<()>::builder_unsafe() + .buy_execution((Here, 1u128), Unlimited) // We'd need to query the destination chain for fees. + .deposit_asset(AllCounted(1), [0u8; 32]) + .build(); + let xcm_to_weigh = Xcm::::builder_unsafe() + .withdraw_asset((Here, transfer_amount)) + .clear_origin() + .buy_execution((Here, transfer_amount), Unlimited) + .deposit_reserve_asset(AllCounted(1), (Parent, Parachain(2100)), inner_xcm.clone()) + .build(); + let client = TestClient; + let runtime_api = client.runtime_api(); + let xcm_weight = runtime_api + .query_xcm_weight(H256::zero(), VersionedXcm::from(xcm_to_weigh.clone().into())) + .unwrap() + .unwrap(); + let execution_fees = runtime_api + .query_weight_to_asset_fee( + H256::zero(), + xcm_weight, + VersionedAssetId::from(AssetId(Here.into())), + ) + .unwrap() + .unwrap(); + let xcm = Xcm::::builder_unsafe() + .withdraw_asset((Here, transfer_amount + execution_fees)) + .clear_origin() + .buy_execution((Here, execution_fees), Unlimited) + .deposit_reserve_asset(AllCounted(1), (Parent, Parachain(2100)), inner_xcm.clone()) + .build(); + let balances = vec![( + who, + transfer_amount + execution_fees + DeliveryFees::get() + ExistentialDeposit::get(), + )]; + new_test_ext_with_balances(balances).execute_with(|| { + let dry_run_effects = runtime_api + .dry_run_xcm( + H256::zero(), + VersionedLocation::from([AccountIndex64 { index: 1, network: None }]), + VersionedXcm::from(xcm), + ) + .unwrap() + .unwrap(); + assert_eq!( + dry_run_effects.forwarded_xcms, + vec![( + VersionedLocation::from((Parent, Parachain(2100))), + vec![VersionedXcm::from( + Xcm::<()>::builder_unsafe() + .reserve_asset_deposited(( + (Parent, Parachain(2000)), + transfer_amount + execution_fees - DeliveryFees::get() + )) + .clear_origin() + .buy_execution((Here, 1u128), Unlimited) + .deposit_asset(AllCounted(1), [0u8; 32]) + .build() + )], + ),] + ); + + assert_eq!( + dry_run_effects.emitted_events, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Burned { who: 1, amount: 540 }), + RuntimeEvent::System(frame_system::Event::NewAccount { account: 2100 }), + RuntimeEvent::Balances(pallet_balances::Event::Endowed { + account: 2100, + free_balance: 520 + }), + RuntimeEvent::Balances(pallet_balances::Event::Minted { who: 2100, amount: 520 }), + ] + ); + }); +} diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/tests/mock.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/tests/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..a1794ab99de71a2e1dd77c05060fddebe5ce8d3a --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/tests/mock.rs @@ -0,0 +1,539 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Mock runtime for tests. +//! Implements both runtime APIs for fee estimation and getting the messages for transfers. + +use codec::Encode; +use frame_support::{ + construct_runtime, derive_impl, parameter_types, + traits::{ + AsEnsureOriginWithArg, ConstU128, ConstU32, Contains, ContainsPair, Everything, Nothing, + OriginTrait, + }, + weights::WeightToFee as WeightToFeeT, +}; +use frame_system::{EnsureRoot, RawOrigin as SystemRawOrigin}; +use pallet_xcm::TestWeightInfo; +use sp_runtime::{ + traits::{Block as BlockT, Get, IdentityLookup, MaybeEquivalence, TryConvert}, + BuildStorage, SaturatedConversion, +}; +use sp_std::{cell::RefCell, marker::PhantomData}; +use xcm::{prelude::*, Version as XcmVersion}; +use xcm_builder::{ + AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, + FixedWeightBounds, FungibleAdapter, FungiblesAdapter, IsConcrete, MintLocation, NoChecking, + TakeWeightCredit, +}; +use xcm_executor::{ + traits::{ConvertLocation, JustTry}, + XcmExecutor, +}; + +use xcm_fee_payment_runtime_api::{ + dry_run::{Error as XcmDryRunApiError, ExtrinsicDryRunEffects, XcmDryRunApi, XcmDryRunEffects}, + fees::{Error as XcmPaymentApiError, XcmPaymentApi}, +}; + +construct_runtime! { + pub enum TestRuntime { + System: frame_system, + Balances: pallet_balances, + AssetsPallet: pallet_assets, + XcmPallet: pallet_xcm, + } +} + +pub type SignedExtra = ( + // frame_system::CheckEra, + // frame_system::CheckNonce, + frame_system::CheckWeight, +); +pub type TestXt = sp_runtime::testing::TestXt; +type Block = sp_runtime::testing::Block; +type Balance = u128; +type AssetIdForAssetsPallet = u32; +type AccountId = u64; + +pub fn extra() -> SignedExtra { + (frame_system::CheckWeight::new(),) +} + +type Executive = frame_executive::Executive< + TestRuntime, + Block, + frame_system::ChainContext, + TestRuntime, + AllPalletsWithSystem, + (), +>; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for TestRuntime { + type Block = Block; + type AccountId = AccountId; + type AccountData = pallet_balances::AccountData; + type Lookup = IdentityLookup; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] +impl pallet_balances::Config for TestRuntime { + type AccountStore = System; + type Balance = Balance; + type ExistentialDeposit = ExistentialDeposit; +} + +#[derive_impl(pallet_assets::config_preludes::TestDefaultConfig)] +impl pallet_assets::Config for TestRuntime { + type AssetId = AssetIdForAssetsPallet; + type Balance = Balance; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = frame_system::EnsureRoot; + type Freezer = (); + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +thread_local! { + pub static SENT_XCM: RefCell)>> = const { RefCell::new(Vec::new()) }; +} + +pub(crate) fn sent_xcm() -> Vec<(Location, Xcm<()>)> { + SENT_XCM.with(|q| (*q.borrow()).clone()) +} + +pub struct TestXcmSender; +impl SendXcm for TestXcmSender { + type Ticket = (Location, Xcm<()>); + fn validate( + dest: &mut Option, + msg: &mut Option>, + ) -> SendResult { + let ticket = (dest.take().unwrap(), msg.take().unwrap()); + let fees: Assets = (HereLocation::get(), DeliveryFees::get()).into(); + Ok((ticket, fees)) + } + fn deliver(ticket: Self::Ticket) -> Result { + let hash = fake_message_hash(&ticket.1); + SENT_XCM.with(|q| q.borrow_mut().push(ticket)); + Ok(hash) + } +} + +pub(crate) fn fake_message_hash(message: &Xcm) -> XcmHash { + message.using_encoded(sp_io::hashing::blake2_256) +} + +pub type XcmRouter = TestXcmSender; + +parameter_types! { + pub const DeliveryFees: u128 = 20; // Random value. + pub const ExistentialDeposit: u128 = 1; // Random value. + pub const BaseXcmWeight: Weight = Weight::from_parts(100, 10); // Random value. + pub const MaxInstructions: u32 = 100; + pub const NativeTokenPerSecondPerByte: (AssetId, u128, u128) = (AssetId(HereLocation::get()), 1, 1); + pub UniversalLocation: InteriorLocation = [GlobalConsensus(NetworkId::Westend), Parachain(2000)].into(); + pub static AdvertisedXcmVersion: XcmVersion = 4; + pub const HereLocation: Location = Location::here(); + pub const RelayLocation: Location = Location::parent(); + pub const MaxAssetsIntoHolding: u32 = 64; + pub CheckAccount: AccountId = XcmPallet::check_account(); + pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local); + pub const AnyNetwork: Option = None; +} + +/// Simple `WeightToFee` implementation that adds the ref_time by the proof_size. +pub struct WeightToFee; +impl WeightToFeeT for WeightToFee { + type Balance = Balance; + fn weight_to_fee(weight: &Weight) -> Self::Balance { + Self::Balance::saturated_from(weight.ref_time()) + .saturating_add(Self::Balance::saturated_from(weight.proof_size())) + } +} + +type Weigher = FixedWeightBounds; + +/// Matches the pair (NativeToken, AssetHub). +/// This is used in the `IsTeleporter` configuration item, meaning we accept our native token +/// coming from AssetHub as a teleport. +pub struct NativeTokenToAssetHub; +impl ContainsPair for NativeTokenToAssetHub { + fn contains(asset: &Asset, origin: &Location) -> bool { + matches!(asset.id.0.unpack(), (0, [])) && matches!(origin.unpack(), (1, [Parachain(1000)])) + } +} + +/// Matches the pair (RelayToken, AssetHub). +/// This is used in the `IsReserve` configuration item, meaning we accept the relay token +/// coming from AssetHub as a reserve asset transfer. +pub struct RelayTokenToAssetHub; +impl ContainsPair for RelayTokenToAssetHub { + fn contains(asset: &Asset, origin: &Location) -> bool { + matches!(asset.id.0.unpack(), (1, [])) && matches!(origin.unpack(), (1, [Parachain(1000)])) + } +} + +/// Converts locations that are only the `AccountIndex64` junction into local u64 accounts. +pub struct AccountIndex64Aliases(PhantomData<(Network, AccountId)>); +impl>, AccountId: From> ConvertLocation + for AccountIndex64Aliases +{ + fn convert_location(location: &Location) -> Option { + let index = match location.unpack() { + (0, [AccountIndex64 { index, network: None }]) => index, + (0, [AccountIndex64 { index, network }]) if *network == Network::get() => index, + _ => return None, + }; + Some((*index).into()) + } +} + +/// Custom location converter to turn sibling chains into u64 accounts. +pub struct SiblingChainToIndex64; +impl ConvertLocation for SiblingChainToIndex64 { + fn convert_location(location: &Location) -> Option { + let index = match location.unpack() { + (1, [Parachain(id)]) => id, + _ => return None, + }; + Some((*index).into()) + } +} + +/// We alias local account locations to actual local accounts. +/// We also allow sovereign accounts for other sibling chains. +pub type LocationToAccountId = (AccountIndex64Aliases, SiblingChainToIndex64); + +pub type NativeTokenTransactor = FungibleAdapter< + // We use pallet-balances for handling this fungible asset. + Balances, + // The fungible asset handled by this transactor is the native token of the chain. + IsConcrete, + // How we convert locations to accounts. + LocationToAccountId, + // We need to specify the AccountId type. + AccountId, + // We mint the native tokens locally, so we track how many we've sent away via teleports. + LocalCheckAccount, +>; + +pub struct LocationToAssetIdForAssetsPallet; +impl MaybeEquivalence for LocationToAssetIdForAssetsPallet { + fn convert(location: &Location) -> Option { + match location.unpack() { + (1, []) => Some(1 as AssetIdForAssetsPallet), + _ => None, + } + } + + fn convert_back(id: &AssetIdForAssetsPallet) -> Option { + match id { + 1 => Some(Location::new(1, [])), + _ => None, + } + } +} + +/// AssetTransactor for handling the relay chain token. +pub type RelayTokenTransactor = FungiblesAdapter< + // We use pallet-assets for handling the relay token. + AssetsPallet, + // Matches the relay token. + ConvertedConcreteId, + // How we convert locations to accounts. + LocationToAccountId, + // We need to specify the AccountId type. + AccountId, + // We don't track teleports. + NoChecking, + (), +>; + +pub type AssetTransactors = (NativeTokenTransactor, RelayTokenTransactor); + +pub struct HereAndInnerLocations; +impl Contains for HereAndInnerLocations { + fn contains(location: &Location) -> bool { + matches!(location.unpack(), (0, []) | (0, _)) + } +} + +pub type Barrier = ( + TakeWeightCredit, // We need this for pallet-xcm's extrinsics to work. + AllowTopLevelPaidExecutionFrom, /* TODO: Technically, we should allow + * messages from "AssetHub". */ +); + +pub type Trader = FixedRateOfFungible; + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = (); + type IsReserve = RelayTokenToAssetHub; + type IsTeleporter = NativeTokenToAssetHub; + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = Weigher; + type Trader = Trader; + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = (); + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Nothing; + type Aliasers = Nothing; + type TransactionalProcessor = (); + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; +} + +/// Converts a signed origin of a u64 account into a location with only the `AccountIndex64` +/// junction. +pub struct SignedToAccountIndex64( + PhantomData<(RuntimeOrigin, AccountId)>, +); +impl> TryConvert + for SignedToAccountIndex64 +where + RuntimeOrigin::PalletsOrigin: From> + + TryInto, Error = RuntimeOrigin::PalletsOrigin>, +{ + fn try_convert(origin: RuntimeOrigin) -> Result { + origin.try_with_caller(|caller| match caller.try_into() { + Ok(SystemRawOrigin::Signed(who)) => + Ok(Junction::AccountIndex64 { network: None, index: who.into() }.into()), + Ok(other) => Err(other.into()), + Err(other) => Err(other), + }) + } +} + +pub type LocalOriginToLocation = SignedToAccountIndex64; + +impl pallet_xcm::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; // Put everything instead of something more restricted. + type XcmReserveTransferFilter = Everything; // Same. + type Weigher = Weigher; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = AdvertisedXcmVersion; + type AdminOrigin = EnsureRoot; + type TrustedLockers = (); + type SovereignAccountOf = (); + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type MaxLockers = ConstU32<0>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type WeightInfo = TestWeightInfo; +} + +pub fn new_test_ext_with_balances(balances: Vec<(AccountId, Balance)>) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +pub fn new_test_ext_with_balances_and_assets( + balances: Vec<(AccountId, Balance)>, + assets: Vec<(AssetIdForAssetsPallet, AccountId, Balance)>, +) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_assets::GenesisConfig:: { + assets: vec![ + // id, owner, is_sufficient, min_balance. + // We don't actually need this to be sufficient, since we use the native assets in + // tests for the existential deposit. + (1, 0, true, 1), + ], + metadata: vec![ + // id, name, symbol, decimals. + (1, "Relay Token".into(), "RLY".into(), 12), + ], + accounts: assets, + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +#[derive(Clone)] +pub(crate) struct TestClient; + +pub(crate) struct RuntimeApi { + _inner: TestClient, +} + +impl sp_api::ProvideRuntimeApi for TestClient { + type Api = RuntimeApi; + fn runtime_api(&self) -> sp_api::ApiRef { + RuntimeApi { _inner: self.clone() }.into() + } +} + +sp_api::mock_impl_runtime_apis! { + impl XcmPaymentApi for RuntimeApi { + fn query_acceptable_payment_assets(xcm_version: XcmVersion) -> Result, XcmPaymentApiError> { + Ok(vec![ + VersionedAssetId::from(AssetId(HereLocation::get())) + .into_version(xcm_version) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)? + ]) + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + XcmPallet::query_xcm_weight(message) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + match asset.try_as::() { + Ok(asset_id) if asset_id.0 == HereLocation::get() => { + Ok(WeightToFee::weight_to_fee(&weight)) + }, + Ok(asset_id) => { + log::trace!( + target: "xcm::XcmPaymentApi::query_weight_to_asset_fee", + "query_weight_to_asset_fee - unhandled asset_id: {asset_id:?}!" + ); + Err(XcmPaymentApiError::AssetNotFound) + }, + Err(_) => { + log::trace!( + target: "xcm::XcmPaymentApi::query_weight_to_asset_fee", + "query_weight_to_asset_fee - failed to convert asset: {asset:?}!" + ); + Err(XcmPaymentApiError::VersionedConversionFailed) + } + } + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + XcmPallet::query_delivery_fees(destination, message) + } + } + + impl XcmDryRunApi for RuntimeApi { + fn dry_run_extrinsic(extrinsic: ::Extrinsic) -> Result, XcmDryRunApiError> { + use xcm_executor::RecordXcm; + // We want to record the XCM that's executed, so we can return it. + pallet_xcm::Pallet::::set_record_xcm(true); + let result = Executive::apply_extrinsic(extrinsic).map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_extrinsic", + "Applying extrinsic failed with error {:?}", + error, + ); + XcmDryRunApiError::InvalidExtrinsic + })?; + // Nothing gets committed to storage in runtime APIs, so there's no harm in leaving the flag as true. + let local_xcm = pallet_xcm::Pallet::::recorded_xcm(); + let forwarded_xcms = sent_xcm() + .into_iter() + .map(|(location, message)| ( + VersionedLocation::from(location), + vec![VersionedXcm::from(message)], + )).collect(); + let events: Vec = System::events().iter().map(|record| record.event.clone()).collect(); + Ok(ExtrinsicDryRunEffects { + local_xcm: local_xcm.map(VersionedXcm::<()>::from), + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + + fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm) -> Result, XcmDryRunApiError> { + let origin_location: Location = origin_location.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Location version conversion failed with error: {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let xcm: Xcm = xcm.try_into().map_err(|error| { + log::error!( + target: "xcm::XcmDryRunApi::dry_run_xcm", + "Xcm version conversion failed with error {:?}", + error, + ); + XcmDryRunApiError::VersionedConversionFailed + })?; + let mut hash = fake_message_hash(&xcm); + let result = XcmExecutor::::prepare_and_execute( + origin_location, + xcm, + &mut hash, + Weight::MAX, // Max limit available for execution. + Weight::zero(), + ); + let forwarded_xcms = sent_xcm() + .into_iter() + .map(|(location, message)| ( + VersionedLocation::from(location), + vec![VersionedXcm::from(message)], + )).collect(); + let events: Vec = System::events().iter().map(|record| record.event.clone()).collect(); + Ok(XcmDryRunEffects { + forwarded_xcms, + emitted_events: events, + execution_result: result, + }) + } + } +} diff --git a/polkadot/xcm/xcm-simulator/Cargo.toml b/polkadot/xcm/xcm-simulator/Cargo.toml index c1c48b6d4c5eb6195a60152f29bdb61e2ad80a79..fc09b5e31861c0cb6470e7d7c121e8c94e1f60f8 100644 --- a/polkadot/xcm/xcm-simulator/Cargo.toml +++ b/polkadot/xcm/xcm-simulator/Cargo.toml @@ -10,16 +10,20 @@ license.workspace = true workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } +scale-info = { version = "2.6.0", default-features = false } paste = "1.0.7" frame-support = { path = "../../../substrate/frame/support" } +frame-system = { path = "../../../substrate/frame/system" } sp-io = { path = "../../../substrate/primitives/io" } sp-std = { path = "../../../substrate/primitives/std" } +sp-runtime = { path = "../../../substrate/primitives/runtime" } xcm = { package = "staging-xcm", path = ".." } xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor" } xcm-builder = { package = "staging-xcm-builder", path = "../xcm-builder" } +polkadot-primitives = { path = "../../primitives" } polkadot-core-primitives = { path = "../../core-primitives" } polkadot-parachain-primitives = { path = "../../parachain" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } diff --git a/polkadot/xcm/xcm-simulator/example/Cargo.toml b/polkadot/xcm/xcm-simulator/example/Cargo.toml index 0e13a10a14106c92d56d288d210b57f3888068b2..8b04170e3032f90adb6f4c3c5d3954729e009b20 100644 --- a/polkadot/xcm/xcm-simulator/example/Cargo.toml +++ b/polkadot/xcm/xcm-simulator/example/Cargo.toml @@ -10,7 +10,7 @@ version = "7.0.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } scale-info = { version = "2.11.1", features = ["derive"] } log = { workspace = true } diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain/mod.rs b/polkadot/xcm/xcm-simulator/example/src/parachain/mod.rs index 8021f9551658075fa672c02306ade1bd12298e4d..93c8302757cb061bc1f97d003ce8b7de2374448e 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain/mod.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain/mod.rs @@ -16,7 +16,6 @@ //! Parachain runtime mock. -mod mock_msg_queue; mod xcm_config; pub use xcm_config::*; @@ -36,6 +35,7 @@ use sp_std::prelude::*; use xcm::latest::prelude::*; use xcm_builder::{EnsureXcmOrigin, SignedToAccountId32}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; +use xcm_simulator::mock_message_queue; pub type AccountId = AccountId32; pub type Balance = u128; @@ -121,7 +121,7 @@ parameter_types! { pub const ReservedDmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); } -impl mock_msg_queue::Config for Runtime { +impl mock_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; } @@ -175,7 +175,7 @@ construct_runtime!( pub struct Runtime { System: frame_system, Balances: pallet_balances, - MsgQueue: mock_msg_queue, + MsgQueue: mock_message_queue, PolkadotXcm: pallet_xcm, ForeignUniques: pallet_uniques, } diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/constants.rs b/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/constants.rs index f6d0174def8f40162f8f2c75231f9b2bad7df0fd..0769507ec37b70e5f6d60886c4db7db9a866dc0d 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/constants.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/constants.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use crate::parachain::MsgQueue; +use crate::parachain::Runtime; use frame_support::parameter_types; use xcm::latest::prelude::*; +use xcm_simulator::mock_message_queue::ParachainId; parameter_types! { pub KsmPerSecondPerByte: (AssetId, u128, u128) = (AssetId(Parent.into()), 1, 1); @@ -26,5 +27,5 @@ parameter_types! { parameter_types! { pub const KsmLocation: Location = Location::parent(); pub const RelayNetwork: NetworkId = NetworkId::Kusama; - pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into(); + pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(ParachainId::::get().into())].into(); } diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/mod.rs b/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/mod.rs index 0ba02aab9bf92ac699485fcd5803e2c658574d13..a6b55d1bd9be05641db343f2f301ae560e0fea29 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/mod.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain/xcm_config/mod.rs @@ -60,4 +60,5 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain/mod.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain/mod.rs index f698eba41d445d5eb70e59873b5c64c50c4a2810..c843f52d41a97f6e70a2320bb3f60a31a9504b50 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain/mod.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain/mod.rs @@ -121,10 +121,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; } -parameter_types! { - pub const FirstMessageFactorPercent: u64 = 100; -} - impl origin::Config for Runtime {} type Block = frame_system::mocking::MockBlock; diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain/xcm_config/mod.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain/xcm_config/mod.rs index a7a8bae51567b3a526333fc56e14ff38c337c776..c5d5fa66732b939b9a03e1da2cf9c658c4e61acb 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain/xcm_config/mod.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain/xcm_config/mod.rs @@ -59,4 +59,5 @@ impl Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } diff --git a/polkadot/xcm/xcm-simulator/example/src/tests.rs b/polkadot/xcm/xcm-simulator/example/src/tests.rs index 6486a849af363af6b41bb40ff440efa5424e92eb..34c1feb6e946876bb62a5624915e414df65ed35e 100644 --- a/polkadot/xcm/xcm-simulator/example/src/tests.rs +++ b/polkadot/xcm/xcm-simulator/example/src/tests.rs @@ -19,7 +19,7 @@ use crate::*; use codec::Encode; use frame_support::{assert_ok, weights::Weight}; use xcm::latest::QueryResponseInfo; -use xcm_simulator::TestExt; +use xcm_simulator::{mock_message_queue::ReceivedDmp, TestExt}; // Helper function for forming buy execution message fn buy_execution(fees: impl Into) -> Instruction { @@ -171,7 +171,7 @@ fn remote_locking_and_unlocking() { ParaA::execute_with(|| { assert_eq!( - parachain::MsgQueue::received_dmp(), + ReceivedDmp::::get(), vec![Xcm(vec![NoteUnlockable { owner: (Parent, Parachain(2)).into(), asset: (Parent, locked_amount).into() @@ -501,7 +501,7 @@ fn query_holding() { // Check that QueryResponse message was received ParaA::execute_with(|| { assert_eq!( - parachain::MsgQueue::received_dmp(), + ReceivedDmp::::get(), vec![Xcm(vec![QueryResponse { query_id: query_id_set, response: Response::Assets(Assets::new()), diff --git a/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml b/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml index ca794a07bfb0c73df251d49c2e08a970ea5cf994..6b3b4018d9fbb30862eee8fa5ea1408c96b2f68e 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml +++ b/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml @@ -11,7 +11,7 @@ publish = false workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } honggfuzz = "0.5.55" arbitrary = "1.3.2" scale-info = { version = "2.11.1", features = ["derive"] } diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index d8d65fbf0ce74a17b75e6bff8c9acfc02dbf928c..502bcca2d44270263a45eeaf305b924d8b37c509 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -159,6 +159,7 @@ impl Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 47209b765d15b7dc00b82e45b9dcdd92947efed5..4740aee83d870a0e260512ac15a982c515a1e803 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -160,6 +160,7 @@ impl Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = (); } pub type LocalOriginToLocation = SignedToAccountId32; @@ -191,10 +192,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; } -parameter_types! { - pub const FirstMessageFactorPercent: u64 = 100; -} - impl origin::Config for Runtime {} parameter_types! { diff --git a/polkadot/xcm/xcm-simulator/src/lib.rs b/polkadot/xcm/xcm-simulator/src/lib.rs index 7efbc658bbfb8bc3fadfa037ae966ca935816ba6..a6747a4789edf8065462b831893ebc8b0284dd18 100644 --- a/polkadot/xcm/xcm-simulator/src/lib.rs +++ b/polkadot/xcm/xcm-simulator/src/lib.rs @@ -16,6 +16,10 @@ //! Test kit to simulate cross-chain message passing and XCM execution. +/// Implementation of a simple message queue. +/// Used for sending messages. +pub mod mock_message_queue; + pub use codec::Encode; pub use paste; diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain/mock_msg_queue.rs b/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs similarity index 72% rename from polkadot/xcm/xcm-simulator/example/src/parachain/mock_msg_queue.rs rename to polkadot/xcm/xcm-simulator/src/mock_message_queue.rs index 17cde921f3e20cbfe4da23c68009e30afbd6fca6..96b47999fe952145b09faa93aaf2cefd5143acb9 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain/mock_msg_queue.rs +++ b/polkadot/xcm/xcm-simulator/src/mock_message_queue.rs @@ -1,4 +1,4 @@ -// Copyright (C) Parity Technologies (UK) Ltd. +// Copyright Parity Technologies (UK) Ltd. // This file is part of Polkadot. // Polkadot is free software: you can redistribute it and/or modify @@ -14,14 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -pub use pallet::*; -use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +//! Simple mock message queue. + +use codec::{Decode, Encode}; + use polkadot_parachain_primitives::primitives::{ DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler, }; +use polkadot_primitives::BlockNumber as RelayBlockNumber; use sp_runtime::traits::{Get, Hash}; + +use sp_std::prelude::*; use xcm::{latest::prelude::*, VersionedXcm}; +pub use pallet::*; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -41,15 +48,15 @@ pub mod pallet { pub struct Pallet(_); #[pallet::storage] - pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery>; + pub type ParachainId = StorageValue<_, ParaId, ValueQuery>; #[pallet::storage] /// A queue of received DMP messages - pub(super) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; + pub type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; impl Get for Pallet { fn get() -> ParaId { - Self::parachain_id() + ParachainId::::get() } } @@ -60,45 +67,34 @@ pub mod pallet { pub enum Event { // XCMP /// Some XCM was executed OK. - Success(Option), + Success { message_id: Option }, /// Some XCM failed. - Fail(Option, XcmError), + Fail { message_id: Option, error: XcmError }, /// Bad XCM version used. - BadVersion(Option), + BadVersion { message_id: Option }, /// Bad XCM format used. - BadFormat(Option), + BadFormat { message_id: Option }, // DMP /// Downward message is invalid XCM. - InvalidFormat(MessageId), + InvalidFormat { message_id: MessageId }, /// Downward message is unsupported version of XCM. - UnsupportedVersion(MessageId), + UnsupportedVersion { message_id: MessageId }, /// Downward message executed with the given outcome. - ExecutedDownward(MessageId, Outcome), + ExecutedDownward { message_id: MessageId, outcome: Outcome }, } impl Pallet { - /// Get the Parachain Id. - pub fn parachain_id() -> ParaId { - ParachainId::::get() - } - - /// Set the Parachain Id. pub fn set_para_id(para_id: ParaId) { ParachainId::::put(para_id); } - /// Get the queue of receieved DMP messages. - pub fn received_dmp() -> Vec> { - ReceivedDmp::::get() - } - fn handle_xcmp_message( sender: ParaId, _sent_at: RelayBlockNumber, xcm: VersionedXcm, - max_weight: Weight, - ) -> Result { + max_weight: xcm::latest::Weight, + ) -> Result { let hash = Encode::using_encoded(&xcm, T::Hashing::hash); let mut message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256); let (result, event) = match Xcm::::try_from(xcm) { @@ -111,15 +107,20 @@ pub mod pallet { max_weight, Weight::zero(), ) { - Outcome::Error { error } => (Err(error), Event::Fail(Some(hash), error)), - Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))), + Outcome::Error { error } => + (Err(error), Event::Fail { message_id: Some(hash), error }), + Outcome::Complete { used } => + (Ok(used), Event::Success { message_id: Some(hash) }), // As far as the caller is concerned, this was dispatched without error, so // we just report the weight used. Outcome::Incomplete { used, error } => - (Ok(used), Event::Fail(Some(hash), error)), + (Ok(used), Event::Fail { message_id: Some(hash), error }), } }, - Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))), + Err(()) => ( + Err(XcmError::UnhandledXcmVersion), + Event::BadVersion { message_id: Some(hash) }, + ), }; Self::deposit_event(event); result @@ -129,8 +130,8 @@ pub mod pallet { impl XcmpMessageHandler for Pallet { fn handle_xcmp_messages<'a, I: Iterator>( iter: I, - max_weight: Weight, - ) -> Weight { + max_weight: xcm::latest::Weight, + ) -> xcm::latest::Weight { for (sender, sent_at, data) in iter { let mut data_ref = data; let _ = XcmpMessageFormat::decode(&mut data_ref) @@ -156,15 +157,16 @@ pub mod pallet { iter: impl Iterator)>, limit: Weight, ) -> Weight { - for (_i, (_sent_at, data)) in iter.enumerate() { + for (_sent_at, data) in iter { let mut id = sp_io::hashing::blake2_256(&data[..]); let maybe_versioned = VersionedXcm::::decode(&mut &data[..]); match maybe_versioned { Err(_) => { - Self::deposit_event(Event::InvalidFormat(id)); + Self::deposit_event(Event::InvalidFormat { message_id: id }); }, Ok(versioned) => match Xcm::try_from(versioned) { - Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)), + Err(()) => + Self::deposit_event(Event::UnsupportedVersion { message_id: id }), Ok(x) => { let outcome = T::XcmExecutor::prepare_and_execute( Parent, @@ -173,8 +175,11 @@ pub mod pallet { limit, Weight::zero(), ); - >::append(x); - Self::deposit_event(Event::ExecutedDownward(id, outcome)); + ReceivedDmp::::append(x); + Self::deposit_event(Event::ExecutedDownward { + message_id: id, + outcome, + }); }, }, } diff --git a/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.toml b/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.toml new file mode 100644 index 0000000000000000000000000000000000000000..14208425d62bac4a7c227211c99da4e01dd89866 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.toml @@ -0,0 +1,43 @@ +[settings] +timeout = 1000 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config] + needed_approvals = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 5 + +[relaychain] +default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" +chain = "rococo-local" +default_command = "polkadot" + +[relaychain.default_resources] +limits = { memory = "4G", cpu = "2" } +requests = { memory = "2G", cpu = "1" } + + [[relaychain.node_groups]] + name = "honest" + count = 4 + args = ["-lparachain=debug,parachain::statement-distribution=trace"] + + [[relaychain.nodes]] + image = "{{MALUS_IMAGE}}" + name = "malus" + command = "malus spam-statement-requests" + args = [ "--alice", "-lparachain=debug,MALUS=trace", "--spam-factor=1000" ] + +{% for id in range(2000,2001) %} +[[parachains]] +id = {{id}} + [parachains.collator] + image = "{{COL_IMAGE}}" + name = "collator" + command = "undying-collator" + args = ["-lparachain=debug"] +{% endfor %} + +[types.Header] +number = "u64" +parent_hash = "Hash" +post_state = "Hash" diff --git a/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.zndsl b/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.zndsl new file mode 100644 index 0000000000000000000000000000000000000000..9985dd24ee38a56c823e07d07556fd77eb7a1ac5 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-spam-statement-distribution-requests.zndsl @@ -0,0 +1,27 @@ +Description: Test if parachains progress when group is getting spammed by statement distribution requests. +Network: ./0012-spam-statement-distribution-requests.toml +Creds: config + +# Check authority status and peers. +malus: reports node_roles is 4 +honest: reports node_roles is 4 + +# Ensure parachains are registered. +honest: parachain 2000 is registered within 60 seconds + +# Ensure that malus is already attempting to DoS +malus: log line contains "😈 Duplicating AttestedCandidateV2 request" within 90 seconds + +# Ensure parachains made progress. +honest: parachain 2000 block height is at least 10 within 200 seconds + +# Ensure that honest nodes drop extra requests +honest: log line contains "Peer already being served, dropping request" within 60 seconds + +# Check lag - approval +honest: reports polkadot_parachain_approval_checking_finality_lag is 0 + +# Check lag - dispute conclusion +honest: reports polkadot_parachain_disputes_finality_lag is 0 + + diff --git a/polkadot/zombienet_tests/functional/0013-enable-node-feature.js b/polkadot/zombienet_tests/functional/0013-enable-node-feature.js new file mode 100644 index 0000000000000000000000000000000000000000..5fe2e38dad7d4f0ba340e48617445ae7f907fce5 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0013-enable-node-feature.js @@ -0,0 +1,35 @@ +async function run(nodeName, networkInfo, index) { + const { wsUri, userDefinedTypes } = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + await zombie.util.cryptoWaitReady(); + + // account to submit tx + const keyring = new zombie.Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + await new Promise(async (resolve, reject) => { + const unsub = await api.tx.sudo + .sudo(api.tx.configuration.setNodeFeature(Number(index), true)) + .signAndSend(alice, ({ status, isError }) => { + if (status.isInBlock) { + console.log( + `Transaction included at blockhash ${status.asInBlock}`, + ); + } else if (status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${status.asFinalized}`, + ); + unsub(); + return resolve(); + } else if (isError) { + console.log(`Transaction error`); + reject(`Transaction error`); + } + }); + }); + + return 0; +} + +module.exports = { run }; diff --git a/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.toml b/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.toml new file mode 100644 index 0000000000000000000000000000000000000000..67925a3d3a7c64201cede004b20fc52dfbae181c --- /dev/null +++ b/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.toml @@ -0,0 +1,46 @@ +[settings] +timeout = 1000 +bootnode = true + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config] + needed_approvals = 4 + +[relaychain] +default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" +chain = "rococo-local" +default_command = "polkadot" + +[relaychain.default_resources] +limits = { memory = "4G", cpu = "2" } +requests = { memory = "2G", cpu = "1" } + + [[relaychain.nodes]] + name = "alice" + validator = "true" + + [[relaychain.node_groups]] + name = "validator" + count = 3 + args = ["-lparachain=debug,parachain::availability-recovery=trace,parachain::availability-distribution=trace"] + +{% for id in range(2000,2002) %} +[[parachains]] +id = {{id}} +addToGenesis = true +cumulus_based = true +chain = "glutton-westend-local-{{id}}" + [parachains.genesis.runtimeGenesis.patch.glutton] + compute = "50000000" + storage = "2500000000" + trashDataCount = 5120 + + [parachains.collator] + name = "collator" + image = "{{CUMULUS_IMAGE}}" + command = "polkadot-parachain" + args = ["-lparachain=debug"] + +{% endfor %} diff --git a/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.zndsl b/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.zndsl new file mode 100644 index 0000000000000000000000000000000000000000..e9e5a429e2a2c4913a61e30fc45114f65a939300 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0013-systematic-chunk-recovery.zndsl @@ -0,0 +1,43 @@ +Description: Systematic chunk recovery is used if the chunk mapping feature is enabled. +Network: ./0013-systematic-chunk-recovery.toml +Creds: config + +# Check authority status. +alice: reports node_roles is 4 +validator: reports node_roles is 4 + +# Ensure parachains are registered. +validator: parachain 2000 is registered within 60 seconds +validator: parachain 2001 is registered within 60 seconds + +# Ensure parachains made progress and approval checking works. +validator: parachain 2000 block height is at least 15 within 600 seconds +validator: parachain 2001 block height is at least 15 within 600 seconds + +validator: reports substrate_block_height{status="finalized"} is at least 30 within 400 seconds + +validator: reports polkadot_parachain_approval_checking_finality_lag < 3 + +validator: reports polkadot_parachain_approvals_no_shows_total < 3 within 100 seconds + +# Ensure we used regular chunk recovery and that there are no failed recoveries. +validator: count of log lines containing "Data recovery from chunks complete" is at least 10 within 300 seconds +validator: count of log lines containing "Data recovery from systematic chunks complete" is 0 within 10 seconds +validator: count of log lines containing "Data recovery from systematic chunks is not possible" is 0 within 10 seconds +validator: count of log lines containing "Data recovery from chunks is not possible" is 0 within 10 seconds +validator: reports polkadot_parachain_availability_recovery_recoveries_finished{result="failure"} is 0 within 10 seconds + +# Enable the chunk mapping feature +alice: js-script ./0013-enable-node-feature.js with "2" return is 0 within 600 seconds + +validator: reports substrate_block_height{status="finalized"} is at least 60 within 400 seconds + +validator: reports polkadot_parachain_approval_checking_finality_lag < 3 + +validator: reports polkadot_parachain_approvals_no_shows_total < 3 within 100 seconds + +# Ensure we used systematic chunk recovery and that there are no failed recoveries. +validator: count of log lines containing "Data recovery from systematic chunks complete" is at least 10 within 300 seconds +validator: count of log lines containing "Data recovery from systematic chunks is not possible" is 0 within 10 seconds +validator: count of log lines containing "Data recovery from chunks is not possible" is 0 within 10 seconds +validator: reports polkadot_parachain_availability_recovery_recoveries_finished{result="failure"} is 0 within 10 seconds diff --git a/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.toml b/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.toml new file mode 100644 index 0000000000000000000000000000000000000000..881abab64fd07b8495189982119b3f985332b8a7 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.toml @@ -0,0 +1,48 @@ +[settings] +timeout = 1000 +bootnode = true + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config] + needed_approvals = 4 + +[relaychain] +default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" +chain = "rococo-local" +default_command = "polkadot" + +[relaychain.default_resources] +limits = { memory = "4G", cpu = "2" } +requests = { memory = "2G", cpu = "1" } + + [[relaychain.node_groups]] + # Use an image that doesn't speak /req_chunk/2 protocol. + image = "{{POLKADOT_IMAGE}}:master-bde0bbe5" + name = "old" + count = 2 + args = ["-lparachain=debug,parachain::availability-recovery=trace,parachain::availability-distribution=trace"] + + [[relaychain.node_groups]] + name = "new" + count = 2 + args = ["-lparachain=debug,parachain::availability-recovery=trace,parachain::availability-distribution=trace,sub-libp2p=trace"] + +{% for id in range(2000,2002) %} +[[parachains]] +id = {{id}} +addToGenesis = true +cumulus_based = true +chain = "glutton-westend-local-{{id}}" + [parachains.genesis.runtimeGenesis.patch.glutton] + compute = "50000000" + storage = "2500000000" + trashDataCount = 5120 + + [parachains.collator] + name = "collator" + image = "{{CUMULUS_IMAGE}}" + args = ["-lparachain=debug"] + +{% endfor %} diff --git a/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.zndsl b/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.zndsl new file mode 100644 index 0000000000000000000000000000000000000000..2ac5012db668d102b1078b4bf694e98b6c0ff302 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0014-chunk-fetching-network-compatibility.zndsl @@ -0,0 +1,53 @@ +Description: Validators preserve backwards compatibility with peers speaking an older version of the /req_chunk protocol +Network: ./0014-chunk-fetching-network-compatibility.toml +Creds: config + +# Check authority status. +new: reports node_roles is 4 +old: reports node_roles is 4 + +# Ensure parachains are registered. +new: parachain 2000 is registered within 60 seconds +old: parachain 2000 is registered within 60 seconds +old: parachain 2001 is registered within 60 seconds +new: parachain 2001 is registered within 60 seconds + +# Ensure parachains made progress and approval checking works. +new: parachain 2000 block height is at least 15 within 600 seconds +old: parachain 2000 block height is at least 15 within 600 seconds +new: parachain 2001 block height is at least 15 within 600 seconds +old: parachain 2001 block height is at least 15 within 600 seconds + +new: reports substrate_block_height{status="finalized"} is at least 30 within 400 seconds +old: reports substrate_block_height{status="finalized"} is at least 30 within 400 seconds + +new: reports polkadot_parachain_approval_checking_finality_lag < 3 +old: reports polkadot_parachain_approval_checking_finality_lag < 3 + +new: reports polkadot_parachain_approvals_no_shows_total < 3 within 10 seconds +old: reports polkadot_parachain_approvals_no_shows_total < 3 within 10 seconds + +# Ensure that there are no failed recoveries. +new: count of log lines containing "Data recovery from chunks complete" is at least 10 within 300 seconds +old: count of log lines containing "Data recovery from chunks complete" is at least 10 within 300 seconds +new: count of log lines containing "Data recovery from chunks is not possible" is 0 within 10 seconds +old: count of log lines containing "Data recovery from chunks is not possible" is 0 within 10 seconds +new: reports polkadot_parachain_availability_recovery_recoveries_finished{result="failure"} is 0 within 10 seconds +old: reports polkadot_parachain_availability_recovery_recoveries_finished{result="failure"} is 0 within 10 seconds + +# Ensure we used the fallback network request. +new: log line contains "Trying the fallback protocol" within 100 seconds + +# Ensure systematic recovery was not used. +old: count of log lines containing "Data recovery from systematic chunks complete" is 0 within 10 seconds +new: count of log lines containing "Data recovery from systematic chunks complete" is 0 within 10 seconds + +# Ensure availability-distribution worked fine +new: reports polkadot_parachain_fetched_chunks_total{success="succeeded"} is at least 10 within 400 seconds +old: reports polkadot_parachain_fetched_chunks_total{success="succeeded"} is at least 10 within 400 seconds + +new: reports polkadot_parachain_fetched_chunks_total{success="failed"} is 0 within 10 seconds +old: reports polkadot_parachain_fetched_chunks_total{success="failed"} is 0 within 10 seconds + +new: reports polkadot_parachain_fetched_chunks_total{success="not-found"} is 0 within 10 seconds +old: reports polkadot_parachain_fetched_chunks_total{success="not-found"} is 0 within 10 seconds diff --git a/prdoc/pr_2119.prdoc b/prdoc/1.11.0/pr_2119.prdoc similarity index 100% rename from prdoc/pr_2119.prdoc rename to prdoc/1.11.0/pr_2119.prdoc diff --git a/prdoc/pr_2292.prdoc b/prdoc/1.11.0/pr_2292.prdoc similarity index 100% rename from prdoc/pr_2292.prdoc rename to prdoc/1.11.0/pr_2292.prdoc diff --git a/prdoc/pr_2714.prdoc b/prdoc/1.11.0/pr_2714.prdoc similarity index 100% rename from prdoc/pr_2714.prdoc rename to prdoc/1.11.0/pr_2714.prdoc diff --git a/prdoc/pr_2944.prdoc b/prdoc/1.11.0/pr_2944.prdoc similarity index 100% rename from prdoc/pr_2944.prdoc rename to prdoc/1.11.0/pr_2944.prdoc diff --git a/prdoc/pr_3250.prdoc b/prdoc/1.11.0/pr_3250.prdoc similarity index 100% rename from prdoc/pr_3250.prdoc rename to prdoc/1.11.0/pr_3250.prdoc diff --git a/prdoc/pr_3251.prdoc b/prdoc/1.11.0/pr_3251.prdoc similarity index 100% rename from prdoc/pr_3251.prdoc rename to prdoc/1.11.0/pr_3251.prdoc diff --git a/prdoc/pr_3455.prdoc b/prdoc/1.11.0/pr_3455.prdoc similarity index 100% rename from prdoc/pr_3455.prdoc rename to prdoc/1.11.0/pr_3455.prdoc diff --git a/prdoc/pr_3485.prdoc b/prdoc/1.11.0/pr_3485.prdoc similarity index 100% rename from prdoc/pr_3485.prdoc rename to prdoc/1.11.0/pr_3485.prdoc diff --git a/prdoc/pr_3512.prdoc b/prdoc/1.11.0/pr_3512.prdoc similarity index 100% rename from prdoc/pr_3512.prdoc rename to prdoc/1.11.0/pr_3512.prdoc diff --git a/prdoc/pr_3630.prdoc b/prdoc/1.11.0/pr_3630.prdoc similarity index 100% rename from prdoc/pr_3630.prdoc rename to prdoc/1.11.0/pr_3630.prdoc diff --git a/prdoc/pr_3659.prdoc b/prdoc/1.11.0/pr_3659.prdoc similarity index 100% rename from prdoc/pr_3659.prdoc rename to prdoc/1.11.0/pr_3659.prdoc diff --git a/prdoc/pr_3660.prdoc b/prdoc/1.11.0/pr_3660.prdoc similarity index 100% rename from prdoc/pr_3660.prdoc rename to prdoc/1.11.0/pr_3660.prdoc diff --git a/prdoc/pr_3695.prdoc b/prdoc/1.11.0/pr_3695.prdoc similarity index 100% rename from prdoc/pr_3695.prdoc rename to prdoc/1.11.0/pr_3695.prdoc diff --git a/prdoc/pr_3708.prdoc b/prdoc/1.11.0/pr_3708.prdoc similarity index 100% rename from prdoc/pr_3708.prdoc rename to prdoc/1.11.0/pr_3708.prdoc diff --git a/prdoc/pr_3721.prdoc b/prdoc/1.11.0/pr_3721.prdoc similarity index 100% rename from prdoc/pr_3721.prdoc rename to prdoc/1.11.0/pr_3721.prdoc diff --git a/prdoc/pr_3789.prdoc b/prdoc/1.11.0/pr_3789.prdoc similarity index 100% rename from prdoc/pr_3789.prdoc rename to prdoc/1.11.0/pr_3789.prdoc diff --git a/prdoc/pr_3801.prdoc b/prdoc/1.11.0/pr_3801.prdoc similarity index 100% rename from prdoc/pr_3801.prdoc rename to prdoc/1.11.0/pr_3801.prdoc diff --git a/prdoc/pr_3813.prdoc b/prdoc/1.11.0/pr_3813.prdoc similarity index 100% rename from prdoc/pr_3813.prdoc rename to prdoc/1.11.0/pr_3813.prdoc diff --git a/prdoc/pr_3852.prdoc b/prdoc/1.11.0/pr_3852.prdoc similarity index 100% rename from prdoc/pr_3852.prdoc rename to prdoc/1.11.0/pr_3852.prdoc diff --git a/prdoc/pr_3875.prdoc b/prdoc/1.11.0/pr_3875.prdoc similarity index 100% rename from prdoc/pr_3875.prdoc rename to prdoc/1.11.0/pr_3875.prdoc diff --git a/prdoc/pr_3889.prdoc b/prdoc/1.11.0/pr_3889.prdoc similarity index 100% rename from prdoc/pr_3889.prdoc rename to prdoc/1.11.0/pr_3889.prdoc diff --git a/prdoc/pr_3915.prdoc b/prdoc/1.11.0/pr_3915.prdoc similarity index 100% rename from prdoc/pr_3915.prdoc rename to prdoc/1.11.0/pr_3915.prdoc diff --git a/prdoc/pr_3930.prdoc b/prdoc/1.11.0/pr_3930.prdoc similarity index 100% rename from prdoc/pr_3930.prdoc rename to prdoc/1.11.0/pr_3930.prdoc diff --git a/prdoc/pr_3934.prdoc b/prdoc/1.11.0/pr_3934.prdoc similarity index 100% rename from prdoc/pr_3934.prdoc rename to prdoc/1.11.0/pr_3934.prdoc diff --git a/prdoc/pr_3953.prdoc b/prdoc/1.11.0/pr_3953.prdoc similarity index 100% rename from prdoc/pr_3953.prdoc rename to prdoc/1.11.0/pr_3953.prdoc diff --git a/prdoc/pr_3959.prdoc b/prdoc/1.11.0/pr_3959.prdoc similarity index 100% rename from prdoc/pr_3959.prdoc rename to prdoc/1.11.0/pr_3959.prdoc diff --git a/prdoc/pr_3976.prdoc b/prdoc/1.11.0/pr_3976.prdoc similarity index 100% rename from prdoc/pr_3976.prdoc rename to prdoc/1.11.0/pr_3976.prdoc diff --git a/prdoc/pr_3979.prdoc b/prdoc/1.11.0/pr_3979.prdoc similarity index 100% rename from prdoc/pr_3979.prdoc rename to prdoc/1.11.0/pr_3979.prdoc diff --git a/prdoc/pr_3983.prdoc b/prdoc/1.11.0/pr_3983.prdoc similarity index 100% rename from prdoc/pr_3983.prdoc rename to prdoc/1.11.0/pr_3983.prdoc diff --git a/prdoc/pr_3997.prdoc b/prdoc/1.11.0/pr_3997.prdoc similarity index 100% rename from prdoc/pr_3997.prdoc rename to prdoc/1.11.0/pr_3997.prdoc diff --git a/prdoc/pr_4006.prdoc b/prdoc/1.11.0/pr_4006.prdoc similarity index 100% rename from prdoc/pr_4006.prdoc rename to prdoc/1.11.0/pr_4006.prdoc diff --git a/prdoc/pr_4015.prdoc b/prdoc/1.11.0/pr_4015.prdoc similarity index 100% rename from prdoc/pr_4015.prdoc rename to prdoc/1.11.0/pr_4015.prdoc diff --git a/prdoc/pr_4017.prdoc b/prdoc/1.11.0/pr_4017.prdoc similarity index 100% rename from prdoc/pr_4017.prdoc rename to prdoc/1.11.0/pr_4017.prdoc diff --git a/prdoc/pr_4021.prdoc b/prdoc/1.11.0/pr_4021.prdoc similarity index 100% rename from prdoc/pr_4021.prdoc rename to prdoc/1.11.0/pr_4021.prdoc diff --git a/prdoc/pr_4027.prdoc b/prdoc/1.11.0/pr_4027.prdoc similarity index 100% rename from prdoc/pr_4027.prdoc rename to prdoc/1.11.0/pr_4027.prdoc diff --git a/prdoc/pr_4037.prdoc b/prdoc/1.11.0/pr_4037.prdoc similarity index 100% rename from prdoc/pr_4037.prdoc rename to prdoc/1.11.0/pr_4037.prdoc diff --git a/prdoc/pr_4059.prdoc b/prdoc/1.11.0/pr_4059.prdoc similarity index 100% rename from prdoc/pr_4059.prdoc rename to prdoc/1.11.0/pr_4059.prdoc diff --git a/prdoc/pr_4060.prdoc b/prdoc/1.11.0/pr_4060.prdoc similarity index 100% rename from prdoc/pr_4060.prdoc rename to prdoc/1.11.0/pr_4060.prdoc diff --git a/prdoc/pr_4070.prdoc b/prdoc/1.11.0/pr_4070.prdoc similarity index 100% rename from prdoc/pr_4070.prdoc rename to prdoc/1.11.0/pr_4070.prdoc diff --git a/prdoc/pr_4072.prdoc b/prdoc/1.11.0/pr_4072.prdoc similarity index 100% rename from prdoc/pr_4072.prdoc rename to prdoc/1.11.0/pr_4072.prdoc diff --git a/prdoc/pr_4075.prdoc b/prdoc/1.11.0/pr_4075.prdoc similarity index 100% rename from prdoc/pr_4075.prdoc rename to prdoc/1.11.0/pr_4075.prdoc diff --git a/prdoc/pr_4089.prdoc b/prdoc/1.11.0/pr_4089.prdoc similarity index 100% rename from prdoc/pr_4089.prdoc rename to prdoc/1.11.0/pr_4089.prdoc diff --git a/prdoc/pr_4118.prdoc b/prdoc/1.11.0/pr_4118.prdoc similarity index 100% rename from prdoc/pr_4118.prdoc rename to prdoc/1.11.0/pr_4118.prdoc diff --git a/prdoc/pr_4151.prdoc b/prdoc/1.11.0/pr_4151.prdoc similarity index 100% rename from prdoc/pr_4151.prdoc rename to prdoc/1.11.0/pr_4151.prdoc diff --git a/prdoc/pr_4156.prdoc b/prdoc/1.11.0/pr_4156.prdoc similarity index 100% rename from prdoc/pr_4156.prdoc rename to prdoc/1.11.0/pr_4156.prdoc diff --git a/prdoc/pr_4168.prdoc b/prdoc/1.11.0/pr_4168.prdoc similarity index 100% rename from prdoc/pr_4168.prdoc rename to prdoc/1.11.0/pr_4168.prdoc diff --git a/prdoc/pr_4169.prdoc b/prdoc/1.11.0/pr_4169.prdoc similarity index 100% rename from prdoc/pr_4169.prdoc rename to prdoc/1.11.0/pr_4169.prdoc diff --git a/prdoc/pr_4171.prdoc b/prdoc/1.11.0/pr_4171.prdoc similarity index 100% rename from prdoc/pr_4171.prdoc rename to prdoc/1.11.0/pr_4171.prdoc diff --git a/prdoc/pr_4177.prdoc b/prdoc/1.11.0/pr_4177.prdoc similarity index 100% rename from prdoc/pr_4177.prdoc rename to prdoc/1.11.0/pr_4177.prdoc diff --git a/prdoc/pr_4189.prdoc b/prdoc/1.11.0/pr_4189.prdoc similarity index 100% rename from prdoc/pr_4189.prdoc rename to prdoc/1.11.0/pr_4189.prdoc diff --git a/prdoc/pr_4199.prdoc b/prdoc/1.11.0/pr_4199.prdoc similarity index 100% rename from prdoc/pr_4199.prdoc rename to prdoc/1.11.0/pr_4199.prdoc diff --git a/prdoc/pr_4208.prdoc b/prdoc/1.11.0/pr_4208.prdoc similarity index 100% rename from prdoc/pr_4208.prdoc rename to prdoc/1.11.0/pr_4208.prdoc diff --git a/prdoc/pr_4221.prdoc b/prdoc/1.11.0/pr_4221.prdoc similarity index 100% rename from prdoc/pr_4221.prdoc rename to prdoc/1.11.0/pr_4221.prdoc diff --git a/prdoc/pr_4229.prdoc b/prdoc/1.11.0/pr_4229.prdoc similarity index 100% rename from prdoc/pr_4229.prdoc rename to prdoc/1.11.0/pr_4229.prdoc diff --git a/prdoc/pr_4252.prdoc b/prdoc/1.11.0/pr_4252.prdoc similarity index 100% rename from prdoc/pr_4252.prdoc rename to prdoc/1.11.0/pr_4252.prdoc diff --git a/prdoc/pr_2226.prdoc b/prdoc/1.12.0/pr_2226.prdoc similarity index 62% rename from prdoc/pr_2226.prdoc rename to prdoc/1.12.0/pr_2226.prdoc index f03540a50f6cc986ed529b80453a94ac4ee79acb..9047dca44558c72bd680fe30239a7905255f0ae6 100644 --- a/prdoc/pr_2226.prdoc +++ b/prdoc/1.12.0/pr_2226.prdoc @@ -4,7 +4,8 @@ doc: - audience: Node Operator description: | On each committed offence (no matter slashable or not) the offending validator will be - disabled for a whole era. + disabled for a whole era. Offenders are no longer chilled so the node operator should monitor + the behavior of their validators and act swiftly if they are raising disputes. - audience: Runtime Dev description: | The disabling strategy in staking pallet is no longer hardcoded but abstracted away via @@ -14,7 +15,13 @@ doc: will be used on Kusama and Polkadot. In nutshell `UpToLimitDisablingStrategy` disables offenders up to the configured threshold. Offending validators are not disabled for offences in previous eras. The threshold is controlled via `DISABLING_LIMIT_FACTOR` (a generic - parameter of `UpToLimitDisablingStrategy`). + parameter of `UpToLimitDisablingStrategy`). Also offending validators are no longer chilled + after an offence is committed. This change is made to protect the network in case of honest nodes being slashed. + - audience: RuntimeUser + description: | + Nominators should be aware that the validators are no longer chilled if they commit an offence. + This means that token holders should be extra careful, monitor closely the behavior of their + nominees and take measures if they commit an offence. migrations: db: [] diff --git a/prdoc/1.12.0/pr_3444.prdoc b/prdoc/1.12.0/pr_3444.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..3afb38106417bdb3784fba0f7306b04c7705b9cf --- /dev/null +++ b/prdoc/1.12.0/pr_3444.prdoc @@ -0,0 +1,25 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Rate-limiting of statement distribution v2 requests to 1 per peer + +doc: + - audience: Node Dev + description: | + A new malicious node variant that sends duplicate statement + distribution messages to spam other peers. + + - audience: Node Operator + description: | + Added rate-limiting in the statement distribution request-response + protocol. Requesters will not issue another request to a peer if one + is already pending with that peer and receiving nodes will reject + requests from peers that they are currently serving. + This should reduce the risk of validator-validator DoS attacks and + better load-balance statement distribution. + +crates: + - name: polkadot-test-malus + bump: minor + - name: polkadot-statement-distribution + bump: minor diff --git a/prdoc/1.12.0/pr_3701.prdoc b/prdoc/1.12.0/pr_3701.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..6f9fcc92ad3050df4011a8984053057a3ec91167 --- /dev/null +++ b/prdoc/1.12.0/pr_3701.prdoc @@ -0,0 +1,11 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: add option to whitelist peers in rpc rate limiting + +doc: + - audience: Node Operator + description: | + This PR adds two new CLI options to disable rate limiting for certain ip addresses and whether to trust "proxy headers". + +crates: [ ] diff --git a/prdoc/pr_3865.prdoc b/prdoc/1.12.0/pr_3865.prdoc similarity index 100% rename from prdoc/pr_3865.prdoc rename to prdoc/1.12.0/pr_3865.prdoc diff --git a/prdoc/1.12.0/pr_3872.prdoc b/prdoc/1.12.0/pr_3872.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..3a5be3d2bc74d08ec83aa1cacaceb294e948c563 --- /dev/null +++ b/prdoc/1.12.0/pr_3872.prdoc @@ -0,0 +1,86 @@ +title: XcmDryRunApi - Runtime API for dry-running extrinsics and XCM programs. + +doc: + - audience: Runtime Dev + description: | + This PR introduces a new runtime API, the XcmDryRunApi, that allows dry-running + extrinsics and XCM programs to get their execution effects. + These effects include: + - Local execution result, either pass or fail + - Emitted events + - Forwarded XCMs + - In the case of extrinsics, the XCM program that they execute + This API can be used on its own to test extrinsics or XCM programs, + or used alongside the XcmPaymentApi to estimate execution and delivery + fees. + + This PR also adds a new configuration item to XCM: XcmRecorder. + This can be set to either (), the xcm pallet, or some custom implementation. + If set to (), the dry run API will not return the local XCM program executed + by running an extrinsic. + After this PR, it is necessary to add the new configuration item to your xcm + configs. + - audience: Runtime User + description: | + This PR introduces a new runtime API, the XcmDryRunApi, that allows dry-running + extrinsics and XCM programs to get their execution effects. + These effects include: + - Local execution result, either pass or fail + - Emitted events + - Forwarded XCMs + - In the case of extrinsics, the XCM program that they execute + This API can be used on its own to test extrinsics or XCM programs, + or used alongside the XcmPaymentApi to estimate execution and delivery + fees. + +crates: + - name: xcm-fee-payment-runtime-api + bump: major + - name: pallet-xcm + bump: minor + - name: staging-xcm-executor + bump: minor + - name: staging-xcm-builder + bump: minor + - name: rococo-runtime + bump: minor + - name: westend-runtime + bump: minor + - name: pallet-xcm-benchmarks + bump: minor + - name: asset-hub-rococo-runtime + bump: minor + - name: asset-hub-westend-runtime + bump: minor + - name: bridge-hub-rococo-runtime + bump: minor + - name: bridge-hub-westend-runtime + bump: minor + - name: collectives-westend-runtime + bump: minor + - name: contracts-rococo-runtime + bump: minor + - name: coretime-rococo-runtime + bump: minor + - name: coretime-westend-runtime + bump: minor + - name: glutton-westend-runtime + bump: minor + - name: people-rococo-runtime + bump: minor + - name: people-westend-runtime + bump: minor + - name: shell-runtime + bump: minor + - name: penpal-runtime + bump: minor + - name: rococo-parachain-runtime + bump: minor + - name: polkadot-service + bump: minor + - name: polkadot-test-runtime + bump: minor + - name: parachain-template-runtime + bump: minor + - name: pallet-contracts-mock-network + bump: minor diff --git a/prdoc/1.12.0/pr_3904.prdoc b/prdoc/1.12.0/pr_3904.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..694f9b443877329e02f47d12de4d375b42fefb36 --- /dev/null +++ b/prdoc/1.12.0/pr_3904.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Introduce pallet-delegated-staking + +doc: + - audience: Runtime Dev + description: | + Adds a new pallet `delegated-staking` that allows delegators to delegate their funds to agents who can stake + these funds on behalf of them. This would be used by Nomination Pools to migrate into a delegation staking based + pool. + +crates: + - name: pallet-delegated-staking + bump: patch + - name: pallet-staking + bump: patch + - name: sp-staking + bump: minor diff --git a/prdoc/1.12.0/pr_3962.prdoc b/prdoc/1.12.0/pr_3962.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..7ef59d38ce5cdea9dbf623e71f14c07752d06828 --- /dev/null +++ b/prdoc/1.12.0/pr_3962.prdoc @@ -0,0 +1,12 @@ +title: Change fork calculation algorithm. + +doc: + - audience: Node Dev + description: | + This PR changes the fork calculation and pruning algorithm to enable future block header pruning. + During the finalization of the block we prune known stale forks, so forks are pruned faster. + +crates: + - name: sc-client-api + - name: sc-client-db + - name: sp-blockchain diff --git a/prdoc/1.12.0/pr_3964.prdoc b/prdoc/1.12.0/pr_3964.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..adf0d95b36a41fe3d4f1b1438c47a276e990d76b --- /dev/null +++ b/prdoc/1.12.0/pr_3964.prdoc @@ -0,0 +1,16 @@ +title: Burn extrinsic call and `fn burn_from` `Preservation` argument + +doc: + - audience: Runtime Dev + description: | + pallet-balances extrinsic calls has been expanded with `burn` call. + An argument flag is allowed to specify whether the account should be kept alive or not. + This in turn required a change to the fungible's `pub trait Mutate` `burn_from` function which now + also accepts `Preservation` as an argument. + In order to keep the behavior same as before, developers should simply specify `Preservation::Expandable`. + +crates: + - name: frame-support + bump: major + - name: pallet-balances + bump: minor diff --git a/prdoc/1.12.0/pr_4034.prdoc b/prdoc/1.12.0/pr_4034.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..994811b5d672e8a267a2c647af442eacdf724bcb --- /dev/null +++ b/prdoc/1.12.0/pr_4034.prdoc @@ -0,0 +1,14 @@ +title: "Introduces `TypeWithDefault>`" + +doc: + - audience: Runtime Dev + description: | + This PR introduces a new type `TypeWithDefault>` to be able to provide a + custom default for any type. This can, then, be used to provide the nonce type that returns + the current block number as the default, to avoid replay of immortal transactions. + +crates: +- name: sp-runtime + bump: minor +- name: frame-system + bump: patch diff --git a/prdoc/1.12.0/pr_4035.prdoc b/prdoc/1.12.0/pr_4035.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..0617a6a261898b743d74dc8fa55224012080391b --- /dev/null +++ b/prdoc/1.12.0/pr_4035.prdoc @@ -0,0 +1,24 @@ +title: "Prospective parachains rework" + +doc: + - audience: Node Dev + description: | + Changes prospective-parachains from dealing with trees of unincluded candidates to maintaining only candidate chains + and a number of unconnected candidates (for which we don't yet know the parent candidate but which otherwise seem potentially viable). + This is needed for elastic scaling, in order to have full throughput even if a candidate is validated by a backing group before the parent candidate + is fetched from the other backing group. + Also simplifies the subsystem by no longer allowing parachain cycles. + +crates: + - name: polkadot-node-core-prospective-parachains + bump: major + - name: polkadot-node-core-backing + bump: minor + - name: polkadot-collator-protocol + bump: minor + - name: polkadot-statement-distribution + bump: minor + - name: polkadot-node-subsystem-types + bump: major + - name: polkadot-node-subsystem-util + bump: major diff --git a/prdoc/1.12.0/pr_4091.prdoc b/prdoc/1.12.0/pr_4091.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..5c38a344bd8ad1405dd8d1daaf8f16ee7ffaf06b --- /dev/null +++ b/prdoc/1.12.0/pr_4091.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removed `pallet::getter` usage from the authority-discovery pallet + +doc: + - audience: Runtime Dev + description: | + This PR removed `pallet::getter`s from `pallet-authority-discovery`s storage items. + When accessed inside the pallet, use the syntax `StorageItem::::get()`. + When accessed outside the pallet, use the getters current_authorities() and next_authorities() instead. + +crates: + - name: pallet-authority-discovery + bump: major diff --git a/prdoc/pr_4102.prdoc b/prdoc/1.12.0/pr_4102.prdoc similarity index 100% rename from prdoc/pr_4102.prdoc rename to prdoc/1.12.0/pr_4102.prdoc diff --git a/prdoc/pr_4157.prdoc b/prdoc/1.12.0/pr_4157.prdoc similarity index 100% rename from prdoc/pr_4157.prdoc rename to prdoc/1.12.0/pr_4157.prdoc diff --git a/prdoc/pr_4175.prdoc b/prdoc/1.12.0/pr_4175.prdoc similarity index 100% rename from prdoc/pr_4175.prdoc rename to prdoc/1.12.0/pr_4175.prdoc diff --git a/prdoc/1.12.0/pr_4185.prdoc b/prdoc/1.12.0/pr_4185.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..88cb6772e5d499cfd542c6cb8f39ca6147877299 --- /dev/null +++ b/prdoc/1.12.0/pr_4185.prdoc @@ -0,0 +1,20 @@ +title: "State trie migration on asset-hub westend and collectives westend" + +doc: + - audience: Node Dev + description: | + On westend and rococo asset-hub and collectives westend the state version is switched to one + and a manual migration will be operate as describe in https://hackmd.io/JagpUd8tTjuKf9HQtpvHIQ + `2.2 Running the signed migration` with account `5F4EbSkZz18X36xhbsjvDNs6NuZ82HyYtq5UiJ1h9SBHJXZD`. + - audience: Runtime User + description: | + On westend and rococo asset-hub and collectives westend the parachain state will migrate + and warpsync will be broken during migration. + +crates: + - name: asset-hub-rococo-runtime + bump: minor + - name: asset-hub-westend-runtime + bump: minor + - name: collectives-westend-runtime + bump: minor diff --git a/prdoc/pr_4202.prdoc b/prdoc/1.12.0/pr_4202.prdoc similarity index 100% rename from prdoc/pr_4202.prdoc rename to prdoc/1.12.0/pr_4202.prdoc diff --git a/prdoc/pr_4211.prdoc b/prdoc/1.12.0/pr_4211.prdoc similarity index 100% rename from prdoc/pr_4211.prdoc rename to prdoc/1.12.0/pr_4211.prdoc diff --git a/prdoc/pr_4213.prdoc b/prdoc/1.12.0/pr_4213.prdoc similarity index 100% rename from prdoc/pr_4213.prdoc rename to prdoc/1.12.0/pr_4213.prdoc diff --git a/prdoc/pr_4220.prdoc b/prdoc/1.12.0/pr_4220.prdoc similarity index 100% rename from prdoc/pr_4220.prdoc rename to prdoc/1.12.0/pr_4220.prdoc diff --git a/prdoc/1.12.0/pr_4281.prdoc b/prdoc/1.12.0/pr_4281.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..ab2156a9505a666c16e1c079a4cff071a271b21b --- /dev/null +++ b/prdoc/1.12.0/pr_4281.prdoc @@ -0,0 +1,16 @@ +title: "Add support for versioned notification for HRMP pallet" + +doc: + - audience: Runtime Dev + description: | + The configuration of the HRMP pallet has been expanded to include the `VersionWrapper` type, + which controls the encoding of XCM notifications related to the opening/closing of HRMP channels. + If your runtime does not concern itself with the XCM version used for notifications, + you can set it as `type VersionWrapper = ()` to always use the latest XCM. + If your runtime does care about the XCM version when sending to child parachains, + you can provide an instance of the `pallet_xcm` with `type VersionWrapper = XcmPallet`, + which can manage XCM versions for destinations. + +crates: +- name: polkadot-runtime-parachains + bump: major diff --git a/prdoc/1.12.0/pr_4295.prdoc b/prdoc/1.12.0/pr_4295.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..e8b2010a8496fcb5f04bb449139c075b0e8894b5 --- /dev/null +++ b/prdoc/1.12.0/pr_4295.prdoc @@ -0,0 +1,14 @@ +title: "Make parachain template async backing ready" + +doc: + - audience: Node Dev + description: | + Promotes the parachain template (both node and runtime) to use async backing APIs so that + developers starting a new project from the template could get async backing integrated out + of the box. + +crates: + - name: parachain-template-node + bump: major + - name: parachain-template-runtime + bump: major diff --git a/prdoc/pr_4301.prdoc b/prdoc/1.12.0/pr_4301.prdoc similarity index 100% rename from prdoc/pr_4301.prdoc rename to prdoc/1.12.0/pr_4301.prdoc diff --git a/prdoc/1.12.0/pr_4302.prdoc b/prdoc/1.12.0/pr_4302.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..bb4331f280239ffb3a8ee44d912916f8b23b91cb --- /dev/null +++ b/prdoc/1.12.0/pr_4302.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "migrations: take() should consume read and write operation weight" + +doc: + - audience: Runtime Dev + description: | + `take()` consumes only 1 read worth of weight in `single-block-migrations` example, while `take()` is `get() + kill()`, + i.e should be 1 read + 1 write. Since this could mislead developers writing migrations following the example, + this PR fixes the weight calculation. + +crates: + - name: pallet-example-single-block-migrations + bump: minor diff --git a/prdoc/pr_4311.prdoc b/prdoc/1.12.0/pr_4311.prdoc similarity index 100% rename from prdoc/pr_4311.prdoc rename to prdoc/1.12.0/pr_4311.prdoc diff --git a/prdoc/pr_4312.prdoc b/prdoc/1.12.0/pr_4312.prdoc similarity index 100% rename from prdoc/pr_4312.prdoc rename to prdoc/1.12.0/pr_4312.prdoc diff --git a/prdoc/1.12.0/pr_4326.prdoc b/prdoc/1.12.0/pr_4326.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..b448bd7e52e76be92924761b8fd925e9b5083247 --- /dev/null +++ b/prdoc/1.12.0/pr_4326.prdoc @@ -0,0 +1,16 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: CheckWeight checks for combined extrinsic length and proof size + +doc: + - audience: Runtime Dev + description: | + The `CheckWeight` `SignedExtension` will now perform an additional check. The extension was verifying the extrinsic length and + weight limits individually. However, the proof size dimension of the weight and extrinsic length together are bound by the PoV size limit. + The `CheckWeight` extension will now check that the combined size of the proof and the extrinsic lengths will not + exceed the PoV size limit. + +crates: + - name: frame-system + bump: minor diff --git a/prdoc/1.12.0/pr_4329.prdoc b/prdoc/1.12.0/pr_4329.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..2fe11a60f4baad8374c751a6b533c495ed7152b3 --- /dev/null +++ b/prdoc/1.12.0/pr_4329.prdoc @@ -0,0 +1,14 @@ +title: "Deprecate `NativeElseWasmExecutor`" + +doc: + - audience: Node Dev + description: | + Deprecates the `NativeElseWasmExecutor` as native execution is already + discouraged and should be removed entirely. The executor should be + replaced by `WasmExecutor` which can be found in `sc-executor`. + + The `NativeElseWasmExecutor` will be removed at the end of 2024. + +crates: + - name: sc-executor + bump: minor diff --git a/prdoc/1.12.0/pr_4346.prdoc b/prdoc/1.12.0/pr_4346.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..e222dec885ced40df8b4b783078e88b0b1e42f40 --- /dev/null +++ b/prdoc/1.12.0/pr_4346.prdoc @@ -0,0 +1,17 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Allow for 0 existential deposit in benchmarks for pallet_staking, pallet_session, and pallet_balances + +doc: + - audience: Runtime Dev + description: | + Changes were made to benchmarks for `pallet_staking`, `pallet_session`, and `pallet-balances` to accommodate runtimes with 0 existential deposit. This should not affect the vast majority of runtimes. For runtimes with 0 existential deposit, the benchmarks for `pallet_staking` and `pallet_session` will still fail when using `U128CurrencyToVote` in the `pallet-staking` config; developers can use or write another `CurrencyToVote` implementation for benchmarking to work around this. + +crates: + - name: pallet-staking + bump: patch + - name: pallet-session-benchmarking + bump: patch + - name: pallet-balances + bump: patch diff --git a/prdoc/1.12.0/pr_4349.prdoc b/prdoc/1.12.0/pr_4349.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..fdc9e816e1b9630cb505f7d8270850ad9450c57e --- /dev/null +++ b/prdoc/1.12.0/pr_4349.prdoc @@ -0,0 +1,9 @@ +title: "Store Header in RemoteExt Snapshot" + +doc: + - audience: Runtime Dev + description: Replaces the block hash in the RemoteExt snapshot with the block header. + +crates: + - name: frame-remote-externalities + bump: major diff --git a/prdoc/1.12.0/pr_4364.prdoc b/prdoc/1.12.0/pr_4364.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..88ee8d12286dbc31f2ae1a6ef64b78ad223d836f --- /dev/null +++ b/prdoc/1.12.0/pr_4364.prdoc @@ -0,0 +1,10 @@ +title: Fix dust unbonded for zero existential deposit + +doc: + - audience: Runtime Dev + description: | + When a staker unbonds and withdraws, it is possible that their stash will contain less currency than the existential deposit. If that happens, their stash is reaped. But if the existential deposit is zero, the reap is not triggered. This PR adjusts pallet_staking to reap a stash in the special case that the stash value is zero and the existential deposit is zero. + +crates: + - name: pallet-staking + bump: patch diff --git a/prdoc/1.12.0/pr_4394.prdoc b/prdoc/1.12.0/pr_4394.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..16409236c94f9240623a56ae9481f3040e27958d --- /dev/null +++ b/prdoc/1.12.0/pr_4394.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Add Kusama People Chain genesis chainspec + +doc: + - audience: Node Operator + description: | + Adds the Kusama People Chain chain spec with the genesis head data and add to + `polkadot-parachain`. + +crates: + - name: polkadot-parachain-bin + bump: minor diff --git a/prdoc/1.12.0/pr_4406.prdoc b/prdoc/1.12.0/pr_4406.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..9372b532512b57f6895076f3b5cf561c1bd4a059 --- /dev/null +++ b/prdoc/1.12.0/pr_4406.prdoc @@ -0,0 +1,10 @@ +title: Adds benchmarking and try-runtime support in `polkadot-sdk-frame` crate + +doc: + - audience: Runtime Dev + description: | + Adds benchmarking and try-runtime support in `polkadot-sdk-frame` crate + +crates: + - name: polkadot-sdk-frame + bump: minor diff --git a/prdoc/1.12.0/pr_4414.prdoc b/prdoc/1.12.0/pr_4414.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..864e816be91a9632859c9b11bf992af5ae7832b4 --- /dev/null +++ b/prdoc/1.12.0/pr_4414.prdoc @@ -0,0 +1,10 @@ +title: "Rococo Asset Hub: undeploy state-trie migration" + +doc: + - audience: Runtime Dev + description: | + The state-trie migration on the Rococo Asset Hub is completed and is now removed. + +crates: + - name: asset-hub-rococo-runtime + bump: major diff --git a/prdoc/1.12.0/pr_4417.prdoc b/prdoc/1.12.0/pr_4417.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..5aa72edd066a7de2a8e66ca1464446c503802644 --- /dev/null +++ b/prdoc/1.12.0/pr_4417.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removed `pallet::getter` usage from pallet-contracts-mock-network + +doc: + - audience: Runtime Dev + description: | + This PR removed the `pallet::getter`s from `pallet-contracts-mock-network`s storage items. + +crates: + - name: pallet-contracts-mock-network + bump: minor diff --git a/prdoc/1.12.0/pr_4426.prdoc b/prdoc/1.12.0/pr_4426.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..5beccbd2a57a593b4937b9f9fbd7c3552d80cc2c --- /dev/null +++ b/prdoc/1.12.0/pr_4426.prdoc @@ -0,0 +1,15 @@ +title: "Remove warning about `BadCertificate`" + +doc: + - audience: Node Operator + description: | + The node was printing the following warning from time to time: + ``` + Sending fatal alert BadCertificate + ``` + + This is not an user error and thus, the warning will now not be printed + anymore. + +crates: + - name: sc-cli diff --git a/prdoc/1.12.0/pr_4442.prdoc b/prdoc/1.12.0/pr_4442.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..ee6ac29e1a1045c67679d4014b893f3eafa8a9f8 --- /dev/null +++ b/prdoc/1.12.0/pr_4442.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Improve mock relay in --dev mode to support async backing + +doc: + - audience: Node Dev + description: | + Support async backing in --dev mode. Improve the relay mock MockValidationDataInherentDataProvider to mach expectations of async backing runtimes. + +crates: + - name: cumulus-client-parachain-inherent + bump: patch diff --git a/prdoc/1.12.0/pr_4457.prdoc b/prdoc/1.12.0/pr_4457.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..5c9bd9822769745adcb916b52e98923fc3e555a5 --- /dev/null +++ b/prdoc/1.12.0/pr_4457.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "sc-service: export all public functions" + +doc: + - audience: Node Dev + description: | + A PR #3166 converted private functions used in `spawn_tasks()` to public to make it possible to have custom + implementation of the `spawn_tasks()`. However, not all functions were included in the list of exports from + `sc-service` crate. + +crates: + - name: sc-service + bump: minor diff --git a/prdoc/1.12.0/pr_4461.prdoc b/prdoc/1.12.0/pr_4461.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..2dafa3812878b4a2767a91d5ad2121bd23652310 --- /dev/null +++ b/prdoc/1.12.0/pr_4461.prdoc @@ -0,0 +1,10 @@ +title: Fix extrinsics count logging in frame-system + +doc: + - audience: Runtime Dev + description: | + Fixes the issue of the number of extrinsics in the block always being 0 in the log of frame-system. + +crates: + - name: frame-system + bump: patch diff --git a/prdoc/pr_1644.prdoc b/prdoc/pr_1644.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..cc43847fa09b2fee66924b08ea0aa9ff9842b036 --- /dev/null +++ b/prdoc/pr_1644.prdoc @@ -0,0 +1,59 @@ +title: Add availability-recovery from systematic chunks + +doc: + - audience: Node Operator + description: | + Implements https://github.com/polkadot-fellows/RFCs/pull/47. This optimisation is guarded by a configuration bit in + the runtime and will only be enabled once a supermajority of the validators have upgraded to this version. + It's strongly advised to upgrade to this version. + - audience: Node Dev + description: | + Implements https://github.com/polkadot-fellows/RFCs/pull/47 and adds the logic for availability recovery from systematic chunks. + The /req_chunk/1 req-response protocol is now considered deprecated in favour of /req_chunk/2. Systematic recovery is guarded + by a configuration bit in the runtime (bit with index 2 of the node_features field from the HostConfiguration) + and must not be enabled until all (or almost all) validators have upgraded to the node version that includes + this PR. + +crates: + - name: sc-network + bump: minor + - name: polkadot-primitives + bump: minor + - name: cumulus-client-pov-recovery + bump: none + - name: polkadot-overseer + bump: none + - name: polkadot-node-primitives + bump: major + - name: polkadot-erasure-coding + bump: major + - name: polkadot-node-jaeger + bump: major + - name: polkadot-node-subsystem-types + bump: major + - name: polkadot-node-network-protocol + bump: major + - name: polkadot-service + bump: major + - name: polkadot-node-subsystem-util + bump: major + - name: polkadot-availability-distribution + bump: major + - name: polkadot-availability-recovery + bump: major + - name: polkadot-node-core-approval-voting + bump: minor + - name: polkadot-node-core-av-store + bump: major + - name: polkadot-network-bridge + bump: minor + - name: polkadot-node-core-backing + bump: none + - name: polkadot-node-core-bitfield-signing + bump: none + - name: polkadot-node-core-dispute-coordinator + bump: none + - name: cumulus-relay-chain-minimal-node + bump: minor + - name: polkadot + bump: minor diff --git a/prdoc/pr_3393.prdoc b/prdoc/pr_3393.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..27ebb385930324f0b0821af3d3ac9d3a6d98f531 --- /dev/null +++ b/prdoc/pr_3393.prdoc @@ -0,0 +1,12 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Add `MaxRank` Config to `pallet-core-fellowship` + +doc: + - audience: Runtime User + description: | + This PR adds a new Config `MaxRank` to the core fellowship pallet. Initially, the maximum rank was set to IX (Grand Master) on the core-fellowship pallet, corresponding to the establishment of the Technical Fellowship and setting the default member count to nine. However, with the introduction of new collectives, this maximum rank is expected to evolve. + +crates: + - name: pallet-core-fellowship diff --git a/prdoc/pr_3905.prdoc b/prdoc/pr_3905.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..d1c03650c9b2365d8f33345fbcef98b4f3885a51 --- /dev/null +++ b/prdoc/pr_3905.prdoc @@ -0,0 +1,25 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Allows Nomination Pool to use different staking strategies including a new DelegateStake strategy. + +doc: + - audience: Runtime Dev + description: | + This PR introduces a new staking strategy called `DelegateStake`. This strategy allows the nomination pool to + delegate its stake to a validator, that is, funds are locked in user account itself instead of being transferred + to the pool account. Includes migration of pools to this strategy for Westend. + +crates: + - name: pallet-nomination-pools + bump: major + - name: pallet-nomination-pools-benchmarking + bump: major + - name: sp-staking + bump: patch + - name: pallet-staking + bump: patch + - name: pallet-delegated-staking + bump: patch + - name: westend-runtime + bump: major diff --git a/prdoc/pr_3935.prdoc b/prdoc/pr_3935.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..93b0fba5d99b47fa918a1100e644ea32f5cc4aa8 --- /dev/null +++ b/prdoc/pr_3935.prdoc @@ -0,0 +1,30 @@ +title: "Introduce Polkadot-SDK umbrella crate" + +doc: + - audience: Runtime Dev + description: | + Introduces a new "umbrella" crate that re-exports all published crates of the Polkadot-SDK. + This helps developers to select a valid set of versions for all underlying dependencies. + + You can now use this create and remove lots of dependencies from your runtime and node crates. + The `staging-node-cli` and `kitchensink-runtime` both adopt this pattern as an example. + + Full docs in `docs/sdk/src/reference_docs/umbrella_crate.rs`. + +crates: + - name: cumulus-pallet-parachain-system + bump: patch + - name: sc-chain-spec-derive + bump: patch + - name: frame-election-provider-solution-type + bump: patch + - name: pallet-staking-reward-curve + bump: patch + - name: frame-support-procedural-tools + bump: patch + - name: sp-api-proc-macro + bump: patch + - name: polkadot-runtime-parachains + bump: patch + - name: polkadot-sdk + bump: major diff --git a/prdoc/pr_3952.prdoc b/prdoc/pr_3952.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..2401adbb76c13cbee7c467df1a0284fc9b4fcaa4 --- /dev/null +++ b/prdoc/pr_3952.prdoc @@ -0,0 +1,35 @@ +title: Storage bound the XCMP queue pallet + +doc: + - audience: Runtime Dev + description: | + Enforce upper limits for the number of active XCMP channels, the number of outgoing XCMP + messages per channel and the number of signals per channel. + + ## Integration + + If you see this error in your try-runtime-cli: + ```pre + Max message size for channel is too large. This means that the V5 migration can be front-run and an + attacker could place a large message just right before the migration to make other messages un-decodable. + Please either increase `MaxPageSize` or decrease the `max_message_size` for this channel. Channel max: + 102400, MaxPageSize: 65535 + ``` + + Then increase the `MaxPageSize` of the `cumulus_pallet_xcmp_queue` to something like this: + ```rust + type MaxPageSize = ConstU32<{ 103 * 1024 }>; + ``` + +migrations: + db: [] + + runtime: + - reference: cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5 + description: A No-OP migration is deployed to ensure that all `BoundedVec`s` still decode as expected. + +crates: + - name: cumulus-pallet-xcmp-queue + bump: major + +host_functions: [] diff --git a/prdoc/pr_4131.prdoc b/prdoc/pr_4131.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..b0619eabe13b575cc6aa10f7215e68a57698b159 --- /dev/null +++ b/prdoc/pr_4131.prdoc @@ -0,0 +1,26 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Deprecate XCMv2 + +doc: + - audience: Runtime Dev + description: | + XCMv2 has been deprecated. It will be removed when XCMv5 is released. + Use version 3 or 4 instead. + - audience: Runtime User + description: | + XCMv2 has been deprecated. It will be removed when XCMv5 is released. + Use version 3 or 4 instead. + +crates: +- name: staging-xcm + bump: minor +- name: xcm-procedural + bump: minor +- name: staging-xcm-builder + bump: minor +- name: pallet-xcm + bump: minor +- name: cumulus-pallet-xcmp-queue + bump: minor diff --git a/prdoc/pr_4198.prdoc b/prdoc/pr_4198.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..cff956812606fc18a500a9cf0de0cc7252955283 --- /dev/null +++ b/prdoc/pr_4198.prdoc @@ -0,0 +1,31 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Replace `Multiaddr` & related types with substrate-specific types + +doc: + - audience: Node Dev + description: | + Introduce custom types / substrate wrappers for `Multiaddr`, `multiaddr::Protocol`, + `Multihash`, `ed25519::*` and supplementary types like errors and iterators. + + Common code in substrate uses these custom types, while `libp2p` & `litep2p` network + backends use their corresponding libraries types. + + This is needed to independently upgrade `libp2p` & `litep2p` dependencies. + +crates: + - name: sc-network-types + bump: minor + - name: sc-network + bump: minor + - name: sc-network-sync + bump: minor + - name: sc-authority-discovery + bump: minor + - name: sc-cli + bump: patch + - name: sc-mixnet + bump: patch + - name: sc-telemetry + bump: patch diff --git a/prdoc/pr_4233.prdoc b/prdoc/pr_4233.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..c593fec68a66a133b2ee7db8a08eea38a9a05883 --- /dev/null +++ b/prdoc/pr_4233.prdoc @@ -0,0 +1,14 @@ +title: "[pallet_contracts] Update Host fn benchnmarks" + +doc: + - audience: Runtime Dev + description: | + Update how the host functions are benchmarked. + Instead of benchnarking a contract that calls the host functions, we now benchmark the host functions directly. + +crates: + - name: pallet-contracts + bump: minor + - name: pallet-contracts-proc-macro + bump: minor + diff --git a/prdoc/pr_4249.prdoc b/prdoc/pr_4249.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..1a267e263924b7f5d0df62d1e1af6800e3ad255f --- /dev/null +++ b/prdoc/pr_4249.prdoc @@ -0,0 +1,17 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Moves runtime macro out of experimental flag + +doc: + - audience: Runtime Dev + description: | + Now that the runtime macro (Construct Runtime V2) has been successfully deployed on Westend, + this PR moves it out of the experimental feature flag and makes it generally available for + runtime devs. + +crates: + - name: frame-support + bump: minor + - name: frame-support-procedural + bump: minor diff --git a/prdoc/pr_4274.prdoc b/prdoc/pr_4274.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..77f5d1387cf7bfc19cd548dbed1c7d7031e39c73 --- /dev/null +++ b/prdoc/pr_4274.prdoc @@ -0,0 +1,39 @@ +title: Introduce `CheckMetadataHash` signed extension + +doc: + - audience: Runtime Dev + description: | + Introduces the new `CheckMetadataHash` signed extension. This extension can be added to a + runtime to support verifying the metadata hash as described in + [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html). + This removes the requirement for having a metadata portal and in general a centralized + authentication of the metadata. With this signed extension the runtime is able to verify + that the metadata used by the wallet was correct. This is mainly useful for offline wallets + which users need to trust any way, not that useful for online wallets. + + There is a guide `generate_metadata_hash` for how to integrate this into a runtime that + should make it quite easy to integrate the signed extension. + - audience: Runtime User + description: | + This brings support for the new Ledger app and similar hardware wallets. These hardware + wallets will be able to decode the transaction using the metadata. The runtime will + ensure that the metadata used for this decoding process is correct and that the online + wallet did not tried to trick you. + +crates: + - name: substrate-wasm-builder + bump: minor + - name: sc-executor-wasmtime + bump: patch + - name: frame-metadata-hash-extension + bump: major + - name: polkadot-service + bump: none + - name: rococo-runtime + bump: major + - name: westend-runtime + bump: major + - name: asset-hub-rococo-runtime + bump: major + - name: asset-hub-westend-runtime + bump: major diff --git a/prdoc/pr_4339.prdoc b/prdoc/pr_4339.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..634ccfa1a339df615db5957729c7833c972047ac --- /dev/null +++ b/prdoc/pr_4339.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Improving on_demand_assigner emitted events + +doc: + - audience: Runtime User + description: | + Registering OnDemandOrderPlaced event that is useful for indexers to save data related to on demand orders. Adds SpotPriceSet as a new event to monitor on-demand spot prices. It updates whenever the price changes due to traffic. + +crates: + - name: polkadot-runtime-parachains + bump: minor \ No newline at end of file diff --git a/prdoc/pr_4380.prdoc b/prdoc/pr_4380.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..1420409656b320c390ab05eecb15df0eca9e3432 --- /dev/null +++ b/prdoc/pr_4380.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove `parametrized-consensus-hook` feature + +doc: + - audience: Runtime Dev + description: | + `parametrized-consensus-hook` feature is obsolete and is removed by this PR. The + long-deprecated `CheckInherents` trait is set to be removed by September 2024. + +crates: + - name: cumulus-pallet-parachain-system + bump: major + diff --git a/prdoc/pr_4392.prdoc b/prdoc/pr_4392.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..898ce9be069e20a09ccbe1ee4a85bcec36893f02 --- /dev/null +++ b/prdoc/pr_4392.prdoc @@ -0,0 +1,16 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove `pallet::getter` usage from both bounties and child bounties pallet + +doc: + - audience: Runtime Dev + description: | + This PR removes `pallet::getter`s from `pallet-bounties` and `pallet-child-bounties`. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-bounties + bump: major + - name: pallet-child-bounties + bump: major diff --git a/prdoc/pr_4410.prdoc b/prdoc/pr_4410.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..1dc1d4c1f87a728ef0edb60d7334ba97a59f539d --- /dev/null +++ b/prdoc/pr_4410.prdoc @@ -0,0 +1,37 @@ +title: "[sc-chain-spec] Remove deprecated code" + +doc: + - audience: Node Dev + description: | + The RuntimeGenesisConfig generic type parameter was removed from GenericChainSpec struct. + ChainSpec::from_genesis method was removed. + Removed related deprecated code from `sc-chain-spec`. + This change simplifies the codebase and ensures the use of up-to-date definitions. + +crates: + - name: sc-service + bump: minor + - name: minimal-template-node + bump: minor + - name: sc-cli + bump: patch + - name: polkadot-test-service + bump: major + - name: sc-service-test + bump: major + - name: staging-node-cli + bump: major + - name: parachain-template-node + bump: minor + - name: solochain-template-node + bump: minor + - name: polkadot-parachain-bin + bump: major + - name: polkadot-service + bump: major + - name: sc-consensus-grandpa + bump: patch + - name: cumulus-test-service + bump: minor + - name: sc-chain-spec + bump: major diff --git a/prdoc/pr_4465.prdoc b/prdoc/pr_4465.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..cbeff09f871f00d5ce3e646fa4adfb11148971a2 --- /dev/null +++ b/prdoc/pr_4465.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Bridge: added force_set_pallet_state call to pallet-bridge-grandpa" + +doc: + - audience: Runtime Dev + description: | + Added `force_set_pallet_state` to the `pallet-bridge-grandpa`. It is only callable by the + root (governance or sudo) and may be used to update current authorities set and the best + finalized header without any additional checks. + +crates: + - name: pallet-bridge-grandpa + bump: major + - name: bridge-hub-rococo-runtime + bump: minor + - name: bridge-hub-westend-runtime + bump: minor diff --git a/prdoc/pr_4471.prdoc b/prdoc/pr_4471.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..6d589be81fd96904f0c5c76abccb1c9b5acd920d --- /dev/null +++ b/prdoc/pr_4471.prdoc @@ -0,0 +1,16 @@ +title: "Remove prospective-parachains subsystem from collator nodes" + +doc: + - audience: Node Dev + description: | + Removes the prospective-parachains subsystem from collators. The GetMinimumRelayParents of the implicit view + is replaced by direct ChainAPI and runtime calls. The subsystem was causing performance problems when collating + connected to an RPC node, due to the high number of runtime API calls, which were unneccessary for a collator. + +crates: + - name: polkadot-collator-protocol + bump: minor + - name: polkadot-service + bump: minor + - name: polkadot-node-subsystem-util + bump: minor diff --git a/prdoc/pr_4472.prdoc b/prdoc/pr_4472.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..cd7527d73d6ba3689d9623c09a591ed61ab5da42 --- /dev/null +++ b/prdoc/pr_4472.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove `pallet::getter` usage from pallet-democracy + +doc: + - audience: Runtime Dev + description: | + This PR removes the `pallet::getter`s from `pallet-democracy`. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-democracy + bump: major diff --git a/prdoc/pr_4475.prdoc b/prdoc/pr_4475.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..30093dcd32b89d8f34c00154ee73fc60ced0b00a --- /dev/null +++ b/prdoc/pr_4475.prdoc @@ -0,0 +1,10 @@ +title: "Deprecate dmp-queue pallet" + +doc: + - audience: Runtime Dev + description: | + Schedule the DMP queue pallet for deletion. It is not needed anymore sine https://github.com/paritytech/polkadot-sdk/pull/1246. + +crates: + - name: cumulus-pallet-dmp-queue + bump: minor diff --git a/prdoc/pr_4478.prdoc b/prdoc/pr_4478.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..22e2e43db4caff9d405ca0ca8c4915416e7df1f5 --- /dev/null +++ b/prdoc/pr_4478.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Snowbridge - Ethereum Client - Reject finalized updates without a sync committee in next store period + +doc: + - audience: Runtime Dev + description: | + Bug fix in the Ethereum light client that stalls the light client when an update in the next sync committee period is received without receiving the next sync committee update in the next period. + +crates: + - name: snowbridge-pallet-ethereum-client + bump: patch diff --git a/prdoc/pr_4503.prdoc b/prdoc/pr_4503.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..d95a24cc7d6b6281761d81b4ab2ccdc8b14e4550 --- /dev/null +++ b/prdoc/pr_4503.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Patch pool to handle extra consumer ref when destroying. + +doc: + - audience: Runtime User + description: | + An erroneous consumer reference on the pool account is preventing pools from being destroyed. This patch removes the extra reference if it exists when the pool account is destroyed. + +crates: + - name: pallet-nomination-pools + bump: patch diff --git a/prdoc/pr_4510.prdoc b/prdoc/pr_4510.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..fbd9bf961fe902b9e38a1cba1a3393764b6f3ccf --- /dev/null +++ b/prdoc/pr_4510.prdoc @@ -0,0 +1,13 @@ +title: "[Contracts] Remove internal topic index" + +doc: + - audience: Runtime Dev + description: | + This PR removes topics from internal events emitted by pallet_contracts. It does not touch the `deposit_event` host function used by + smart contracts that can still include topics. + Event topics incurs significant Storage costs, and are only used by light clients to index events and avoid downloading the entire block. + They are not used by Dapp or Indexers that download the whole block anyway. + +crates: + - name: pallet-contracts + bump: patch diff --git a/prdoc/pr_4514.prdoc b/prdoc/pr_4514.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..dab6cab303476f32bf0c17836e2b770b5260c0f6 --- /dev/null +++ b/prdoc/pr_4514.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removed `pallet::getter` usage from pallet-fast-unstake + +doc: + - audience: Runtime Dev + description: | + This PR removed the `pallet::getter`s from `pallet-fast-unstake`. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-fast-unstake + bump: major diff --git a/prdoc/pr_4533.prdoc b/prdoc/pr_4533.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..a0835285fc012cb0018e499f87e380f7ac059999 --- /dev/null +++ b/prdoc/pr_4533.prdoc @@ -0,0 +1,10 @@ +title: "Fixed RPC subscriptions leak when subscription stream is finished" + +doc: + - audience: Node Operator + description: | + The node may leak RPC subscriptions in some cases, e.g. during + `author_submitAndWatchExtrinsic` calls. This PR fixes the issue. + +crates: + - name: sc-rpc diff --git a/prdoc/pr_4534.prdoc b/prdoc/pr_4534.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..417e4d3dace01e2e840a074bf9aac8615dbb5f1a --- /dev/null +++ b/prdoc/pr_4534.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Add Extra Check in Primary Username Setter + +doc: + - audience: Runtime User + description: | + Setting primary usernames requires an additional verification. + +crates: + - name: pallet-identity + bump: patch diff --git a/prdoc/pr_4541.prdoc b/prdoc/pr_4541.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..815ea2c800625f78e1f92d153a0f3da664508829 --- /dev/null +++ b/prdoc/pr_4541.prdoc @@ -0,0 +1,16 @@ +title: "Remove warning about `BadCertificate` Version 2" + +doc: + - audience: Node Operator + description: | + The node was printing the following warning from time to time: + ``` + Sending fatal alert BadCertificate + ``` + + This is not an user error and thus, the warning will now not be printed + anymore. + +crates: + - name: sc-tracing + bump: patch diff --git a/prdoc/pr_4555.prdoc b/prdoc/pr_4555.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..257115d236e76756007281a0b64d7a73fa2fdff9 --- /dev/null +++ b/prdoc/pr_4555.prdoc @@ -0,0 +1,11 @@ +title: Move `para_id` to `MockValidationDataInherentDataProvider` + +doc: + - audience: Node Dev + description: | + This moves the `para_id` from `MockXcmConfig` to `MockValidationDataInherentDataProvider` to make it more prominent. The `para_id` should + be set to the parachain id of the parachain that gets mocked to ensure that the relay chain storage proof is setup correctly etc. + +crates: + - name: cumulus-client-parachain-inherent + bump: major diff --git a/prdoc/pr_4571.prdoc b/prdoc/pr_4571.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..b03fee8a5cc8746f9ae569a6ffd4902f1da4a510 --- /dev/null +++ b/prdoc/pr_4571.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Ignore mandatory extrinsics in total PoV size check + +doc: + - audience: Runtime Dev + description: | + The `CheckWeight` extension is checking that extrinsic length and used storage proof + weight together do not exceed the PoV size limit. This lead to problems when + the PoV size was already reached before mandatory extrinsics were applied.The `CheckWeight` + extension will now allow extrinsics of `DispatchClass::Mandatory` to be applied even if + the limit is reached. + +crates: + - name: frame-system + bump: minor + - name: polkadot-sdk + bump: minor diff --git a/prdoc/schema_user.json b/prdoc/schema_user.json index 1fa4b8d1202c99c1fea077854b6f5efcf58f1ae5..e6c0468aaf8517956501324dc4ba087b444bb424 100644 --- a/prdoc/schema_user.json +++ b/prdoc/schema_user.json @@ -140,6 +140,9 @@ "bump": { "$ref": "#/$defs/semver_bump" }, + "validate": { + "$ref": "#/$defs/semver_validate" + }, "note": { "type": "string" } @@ -183,6 +186,11 @@ "description" ] }, + "semver_validate": { + "type": "boolean", + "description": "Whether or not to validate the specified semver bump.", + "default": true + }, "semver_bump": { "description": "The type of bump to apply to the crate version according to Cargo SemVer: https://doc.rust-lang.org/cargo/reference/semver.html. Please check docs/RELEASE.md for more information.", "oneOf": [ @@ -210,7 +218,7 @@ }, "doc": { "type": "object", - "description": "You have the the option to provide different description of your PR for different audiences.", + "description": "You have the option to provide different description of your PR for different audiences.", "additionalProperties": false, "properties": { "audience": { diff --git a/scripts/generate-umbrella.py b/scripts/generate-umbrella.py new file mode 100644 index 0000000000000000000000000000000000000000..0bdf160e63b176c6981ec18d8b72ee8782dd0e8b --- /dev/null +++ b/scripts/generate-umbrella.py @@ -0,0 +1,204 @@ +""" + +Creates the Polkadot-SDK umbrella crate that re-exports all other crates. + +This re-creates the `umbrella/` folder. Ensure that it does not contain any changes you want to keep. + +Usage: + python3 polkadot-sdk-umbrella-crate.py --sdk --version + +Example: + python3 polkadot-sdk-umbrella-crate.py --sdk ../polkadot-sdk --version 1.11.0 +""" + +import argparse +import os +import re +import toml +import shutil + +from cargo_workspace import Workspace + +""" +Crate names that should be excluded from the umbrella crate. +""" +def exclude(crate): + name = crate.name + if crate.metadata.get("polkadot-sdk.skip-umbrella", False): + return True + + # No fuzzers or examples: + if "example" in name or name.endswith("fuzzer"): + return True + # No runtime crates: + if name.endswith("-runtime"): + # Note: this is a bit hacky. We should use custom crate metadata instead. + return name != "sp-runtime" and name != "bp-runtime" and name != "frame-try-runtime" + + return False + +def main(path, version): + delete_umbrella(path) + workspace = Workspace.from_path(path) + print(f'Indexed {workspace}') + + std_crates = [] # name -> path. use list for sorting + nostd_crates = [] + for crate in workspace.crates: + if crate.name == 'polkadot-sdk': + continue + if not crate.publish: + print(f"Skipping {crate.name} as it is not published") + continue + + lib_path = os.path.dirname(crate.abs_path) + manifest_path = os.path.join(lib_path, "Cargo.toml") + lib_path = os.path.join(lib_path, "src", "lib.rs") + path = os.path.dirname(crate.rel_path) + + # Guess which crates support no_std. Proc-macro crates are always no_std: + with open(manifest_path, "r") as f: + manifest = toml.load(f) + if 'lib' in manifest and 'proc-macro' in manifest['lib']: + if manifest['lib']['proc-macro']: + nostd_crates.append((crate, path)) + continue + + # Crates without a lib.rs cannot be no_std + if not os.path.exists(lib_path): + print(f"Skipping {crate.name} as it does not have a 'src/lib.rs'") + continue + if exclude(crate): + print(f"Skipping {crate.name} as it is in the exclude list") + continue + + # No search for a no_std attribute: + with open(lib_path, "r") as f: + content = f.read() + if "#![no_std]" in content or '#![cfg_attr(not(feature = "std"), no_std)]' in content: + nostd_crates.append((crate, path)) + elif 'no_std' in content: + raise Exception(f"Found 'no_std' in {lib_path} without knowing how to handle it") + else: + std_crates.append((crate, path)) + + # Sort by name + std_crates.sort(key=lambda x: x[0].name) + nostd_crates.sort(key=lambda x: x[0].name) + all_crates = std_crates + nostd_crates + all_crates.sort(key=lambda x: x[0].name) + dependencies = {} + + for (crate, path) in nostd_crates: + dependencies[crate.name] = {"path": f"../{path}", "default-features": False, "optional": True} + + for (crate, path) in std_crates: + dependencies[crate.name] = {"path": f"../{path}", "default-features": False, "optional": True} + + # The empty features are filled by Zepter + features = { + "default": [ "std" ], + "std": [], + "runtime-benchmarks": [], + "try-runtime": [], + "serde": [], + "experimental": [], + "with-tracing": [], + "runtime": list([f"{d.name}" for d, _ in nostd_crates]), + "node": ["std"] + list([f"{d.name}" for d, _ in std_crates]), + "tuples-96": [], + } + + manifest = { + "package": { + "name": "polkadot-sdk", + "version": version, + "edition": { "workspace": True }, + "authors": { "workspace": True }, + "description": "Polkadot SDK umbrella crate.", + "license": "Apache-2.0", + "metadata": { "docs": { "rs": { + "features": ["runtime", "node"], + "targets": ["x86_64-unknown-linux-gnu"] + }}} + }, + "dependencies": dependencies, + "features": features, + } + + umbrella_dir = os.path.join(workspace.path, "umbrella") + manifest_path = os.path.join(umbrella_dir, "Cargo.toml") + lib_path = os.path.join(umbrella_dir, "src", "lib.rs") + # create all dir + os.makedirs(os.path.dirname(lib_path), exist_ok=True) + # Write the manifest + with open(manifest_path, "w") as f: + toml_manifest = toml.dumps(manifest) + f.write(toml_manifest) + print(f"Wrote {manifest_path}") + # and the lib.rs + with open(lib_path, "w") as f: + f.write('''// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +#![cfg_attr(not(feature = "std"), no_std)] + +//! Polkadot SDK umbrella crate re-exporting all other published crates. +//! +//! This helps to set a single version number for all your dependencies. Docs are in the +//! `polkadot-sdk-docs` crate. + +// This file is auto-generated and checked by the CI. You can edit it manually, but it must be +// exactly the way that the CI expects it. +''') + + for crate, _ in all_crates: + use = crate.name.replace("-", "_") + desc = crate.description if crate.description.endswith(".") else crate.description + "." + f.write(f'\n/// {desc}') + f.write(f'\n#[cfg(feature = "{crate.name}")]\n') + f.write(f"pub use {use};\n") + + print(f"Wrote {lib_path}") + + add_to_workspace(workspace.path) + +""" +Delete the umbrella folder and remove the umbrella crate from the workspace. +""" +def delete_umbrella(path): + umbrella_dir = os.path.join(path, "umbrella") + # remove the umbrella crate from the workspace + manifest = os.path.join(path, "Cargo.toml") + manifest = open(manifest, "r").read() + manifest = re.sub(r'\s+"umbrella",\n', "", manifest) + with open(os.path.join(path, "Cargo.toml"), "w") as f: + f.write(manifest) + if os.path.exists(umbrella_dir): + print(f"Deleting {umbrella_dir}") + shutil.rmtree(umbrella_dir) + +""" +Create the umbrella crate and add it to the workspace. +""" +def add_to_workspace(path): + manifest = os.path.join(path, "Cargo.toml") + manifest = open(manifest, "r").read() + manifest = re.sub(r'^members = \[', 'members = [\n "umbrella",', manifest, flags=re.M) + with open(os.path.join(path, "Cargo.toml"), "w") as f: + f.write(manifest) + + os.chdir(path) # hack + os.system("cargo metadata --format-version 1 > /dev/null") # update the lockfile + os.system(f"zepter") # enable the features + os.system(f"taplo format --config .config/taplo.toml Cargo.toml umbrella/Cargo.toml") + +def parse_args(): + parser = argparse.ArgumentParser(description="Create a polkadot-sdk crate") + parser.add_argument("--sdk", type=str, default="polkadot-sdk", help="Path to the polkadot-sdk crate") + parser.add_argument("--version", type=str, help="Version of the polkadot-sdk crate") + return parser.parse_args() + +if __name__ == "__main__": + args = parse_args() + main(args.sdk, args.version) diff --git a/scripts/release/build-changelogs.sh b/scripts/release/build-changelogs.sh index d9a1f11d01e92aa18c860cb87021caa066c7e96d..d73f06c8cd6bb3f8a0814fd797a19da951d51418 100755 --- a/scripts/release/build-changelogs.sh +++ b/scripts/release/build-changelogs.sh @@ -51,7 +51,7 @@ for tuple in "${aud_desc_array[@]}"; do echo "Processing audience: $audience ($audience_id)" export TARGET_AUDIENCE="$audience" - export AUDIENCE_DESC="**These changes are relevant to:** $description" + export AUDIENCE_DESC="**ℹ️ These changes are relevant to:** $description" tera -t "${TEMPLATE_AUDIENCE}" --env --env-key env "${CONTEXT_JSON}" > "$OUTPUT/relnote_${audience_id}.md" cat "$OUTPUT/relnote_${audience_id}.md" >> "$PROJECT_ROOT/scripts/release/templates/changelog.md" diff --git a/scripts/release/templates/_free_notes.md.tera b/scripts/release/templates/_free_notes.md.tera new file mode 100644 index 0000000000000000000000000000000000000000..c4a841a992515a0016f8aec99cc0038e7428cafb --- /dev/null +++ b/scripts/release/templates/_free_notes.md.tera @@ -0,0 +1,10 @@ + +{# This file uses the Markdown format with additional templating such as this comment. -#} +{# Such a comment will not show up in the rendered release notes. -#} +{# The content of this file (if any) will be inserted at the top of the release notes -#} +{# and generated for each new release candidate. -#} +{# Ensure you leave an empty line at both top and bottom of this file. -#} + + + + diff --git a/scripts/release/templates/docker_image.md.tera b/scripts/release/templates/docker_image.md.tera new file mode 100644 index 0000000000000000000000000000000000000000..273635670e17ae365576bcb9ea8b707c00804a24 --- /dev/null +++ b/scripts/release/templates/docker_image.md.tera @@ -0,0 +1,19 @@ + +## Docker images + +The docker images for the `polkadot` node binary and the `polkadot-parachain` binary can be found at Docker hub (will be available a few minutes after the release has been published): +- [Polkadot image](https://hub.docker.com/r/parity/polkadot/tags?page=1&ordering=last_updated) +- [Polkadot-Parachain image](https://hub.docker.com/r/parity/polkadot-parachain/tags?page=1&ordering=last_updated) + + +You may also pull it with: + +``` +docker pull parity/polkadot:latest +``` + +or + +``` +docker pull parity/polkadot-parachain:latest +``` diff --git a/scripts/release/templates/template.md.tera b/scripts/release/templates/template.md.tera index 39bc1c74402173a04021c20b340be1239e77bb64..0211cafb428b7cad37a0eee7f43b58f8b10b574b 100644 --- a/scripts/release/templates/template.md.tera +++ b/scripts/release/templates/template.md.tera @@ -2,8 +2,14 @@ This release contains the changes from `{{ env.REF1 | replace(from="refs/tags/", to="") }}` to `{{ env.REF2 | replace(from="refs/tags/", to="") }}`. +{# -- Manual free notes section -- #} +{% include "_free_notes.md.tera" -%} + +{# -- Automatic section -- #} {% include "changes.md.tera" -%} {% include "compiler.md.tera" -%} {% include "runtimes.md.tera" -%} + +{% include "docker_image.md.tera" -%} diff --git a/substrate/bin/node/bench/Cargo.toml b/substrate/bin/node/bench/Cargo.toml index 49485fe2a1b9b8017ec560adef2f0f2114b07b5d..b756f3504655bf44f0b5e51699026dcd82afaca3 100644 --- a/substrate/bin/node/bench/Cargo.toml +++ b/substrate/bin/node/bench/Cargo.toml @@ -15,7 +15,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } node-primitives = { path = "../primitives" } diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index e6f754fa40b1b6e7cc8faba9e149ee726be3b85b..929cd6a29e3889dbd93d6e31277406cf61176114 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -23,13 +23,10 @@ wasm-opt = false targets = ["x86_64-unknown-linux-gnu"] [badges] -travis-ci = { repository = "paritytech/substrate" } maintenance = { status = "actively-developed" } -is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } -is-it-maintained-open-issues = { repository = "paritytech/substrate" } +is-it-maintained-issue-resolution = { repository = "paritytech/polkadot-sdk" } +is-it-maintained-open-issues = { repository = "paritytech/polkadot-sdk" } -# The same node binary as the `substrate` (defined in the workspace `Cargo.toml`) binary, -# but just exposed by this crate here. [[bin]] name = "substrate-node" path = "bin/main.rs" @@ -42,192 +39,68 @@ crate-type = ["cdylib", "rlib"] # third-party dependencies array-bytes = "6.1" clap = { version = "4.5.3", features = ["derive"], optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } serde = { features = ["derive"], workspace = true, default-features = true } jsonrpsee = { version = "0.22", features = ["server"] } futures = "0.3.30" log = { workspace = true, default-features = true } rand = "0.8" +serde_json = { workspace = true, default-features = true } + +# The Polkadot-SDK: +polkadot-sdk = { path = "../../../../umbrella", features = ["node"] } -# primitives -sp-authority-discovery = { path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { path = "../../../primitives/consensus/babe" } -beefy-primitives = { package = "sp-consensus-beefy", path = "../../../primitives/consensus/beefy" } -grandpa-primitives = { package = "sp-consensus-grandpa", path = "../../../primitives/consensus/grandpa" } -sp-api = { path = "../../../primitives/api" } -sp-core = { path = "../../../primitives/core" } -sp-runtime = { path = "../../../primitives/runtime" } -sp-timestamp = { path = "../../../primitives/timestamp" } -sp-genesis-builder = { path = "../../../primitives/genesis-builder" } -sp-inherents = { path = "../../../primitives/inherents" } -sp-keyring = { path = "../../../primitives/keyring" } -sp-keystore = { path = "../../../primitives/keystore" } -sp-consensus = { path = "../../../primitives/consensus/common" } -sp-transaction-storage-proof = { path = "../../../primitives/transaction-storage-proof" } -sp-io = { path = "../../../primitives/io" } -sp-mixnet = { path = "../../../primitives/mixnet" } -sp-mmr-primitives = { path = "../../../primitives/merkle-mountain-range" } -sp-statement-store = { path = "../../../primitives/statement-store" } - -# client dependencies -sc-client-api = { path = "../../../client/api" } -sc-chain-spec = { path = "../../../client/chain-spec" } -sc-consensus = { path = "../../../client/consensus/common" } -sc-transaction-pool = { path = "../../../client/transaction-pool" } -sc-transaction-pool-api = { path = "../../../client/transaction-pool/api" } -sc-statement-store = { path = "../../../client/statement-store" } -sc-network = { path = "../../../client/network" } -sc-network-common = { path = "../../../client/network/common" } -sc-network-sync = { path = "../../../client/network/sync" } -sc-network-statement = { path = "../../../client/network/statement" } -sc-consensus-slots = { path = "../../../client/consensus/slots" } -sc-consensus-babe = { path = "../../../client/consensus/babe" } -beefy = { package = "sc-consensus-beefy", path = "../../../client/consensus/beefy" } -grandpa = { package = "sc-consensus-grandpa", path = "../../../client/consensus/grandpa" } -mmr-gadget = { path = "../../../client/merkle-mountain-range" } -sc-rpc = { path = "../../../client/rpc" } -sc-basic-authorship = { path = "../../../client/basic-authorship" } -sc-service = { path = "../../../client/service", default-features = false } -sc-telemetry = { path = "../../../client/telemetry" } -sc-executor = { path = "../../../client/executor" } -sc-authority-discovery = { path = "../../../client/authority-discovery" } -sc-mixnet = { path = "../../../client/mixnet" } -sc-sync-state-rpc = { path = "../../../client/sync-state-rpc" } -sc-sysinfo = { path = "../../../client/sysinfo" } -sc-storage-monitor = { path = "../../../client/storage-monitor" } -sc-offchain = { path = "../../../client/offchain" } - -# frame dependencies -frame-benchmarking = { path = "../../../frame/benchmarking" } -frame-system = { path = "../../../frame/system" } -frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api" } -pallet-assets = { path = "../../../frame/assets" } -pallet-asset-conversion-tx-payment = { path = "../../../frame/transaction-payment/asset-conversion-tx-payment" } -pallet-asset-tx-payment = { path = "../../../frame/transaction-payment/asset-tx-payment" } -pallet-im-online = { path = "../../../frame/im-online", default-features = false } -pallet-skip-feeless-payment = { path = "../../../frame/transaction-payment/skip-feeless-payment", default-features = false } - -# node-specific dependencies +# Shared code between the staging node and kitchensink runtime: kitchensink-runtime = { path = "../runtime" } node-rpc = { path = "../rpc" } node-primitives = { path = "../primitives" } - -# CLI-specific dependencies -sc-cli = { path = "../../../client/cli", optional = true } -frame-benchmarking-cli = { path = "../../../utils/frame/benchmarking-cli", optional = true } node-inspect = { package = "staging-node-inspect", path = "../inspect", optional = true } -serde_json = { workspace = true, default-features = true } [dev-dependencies] -sc-keystore = { path = "../../../client/keystore" } -sc-client-db = { path = "../../../client/db" } -sc-consensus = { path = "../../../client/consensus/common" } -sc-consensus-babe = { path = "../../../client/consensus/babe" } -sc-consensus-epochs = { path = "../../../client/consensus/epochs" } -sc-service-test = { path = "../../../client/service/test" } -sc-block-builder = { path = "../../../client/block-builder" } -sp-tracing = { path = "../../../primitives/tracing" } -sp-blockchain = { path = "../../../primitives/blockchain" } -sp-crypto-hashing = { path = "../../../primitives/crypto/hashing" } futures = "0.3.30" tempfile = "3.1.0" assert_cmd = "2.0.2" -nix = { version = "0.26.1", features = ["signal"] } +nix = { version = "0.28.0", features = ["signal"] } regex = "1.6.0" platforms = "3.0" soketto = "0.7.1" -criterion = { version = "0.4.0", features = ["async_tokio"] } +criterion = { version = "0.5.1", features = ["async_tokio"] } tokio = { version = "1.22.0", features = ["macros", "parking_lot", "time"] } tokio-util = { version = "0.7.4", features = ["compat"] } wait-timeout = "0.2" -substrate-rpc-client = { path = "../../../utils/frame/rpc/client" } -pallet-timestamp = { path = "../../../frame/timestamp" } -substrate-cli-test-utils = { path = "../../../test-utils/cli" } - wat = "1.0" -frame-support = { path = "../../../frame/support" } -node-testing = { path = "../testing" } -pallet-balances = { path = "../../../frame/balances" } -pallet-contracts = { path = "../../../frame/contracts" } -pallet-glutton = { path = "../../../frame/glutton" } -pallet-sudo = { path = "../../../frame/sudo" } -pallet-treasury = { path = "../../../frame/treasury" } -pallet-transaction-payment = { path = "../../../frame/transaction-payment" } -sp-application-crypto = { path = "../../../primitives/application-crypto" } -pallet-root-testing = { path = "../../../frame/root-testing" } -sp-consensus-babe = { path = "../../../primitives/consensus/babe" } -sp-externalities = { path = "../../../primitives/externalities" } -sp-keyring = { path = "../../../primitives/keyring" } -sp-runtime = { path = "../../../primitives/runtime" } serde_json = { workspace = true, default-features = true } scale-info = { version = "2.11.1", features = ["derive", "serde"] } -sp-trie = { path = "../../../primitives/trie" } -sp-state-machine = { path = "../../../primitives/state-machine" } + +# These testing-only dependencies are not exported by the Polkadot-SDK crate: +node-testing = { path = "../testing" } +substrate-cli-test-utils = { path = "../../../test-utils/cli" } +sc-service-test = { path = "../../../client/service/test" } [build-dependencies] clap = { version = "4.5.3", optional = true } clap_complete = { version = "4.0.2", optional = true } + node-inspect = { package = "staging-node-inspect", path = "../inspect", optional = true } -frame-benchmarking-cli = { path = "../../../utils/frame/benchmarking-cli", optional = true } -substrate-build-script-utils = { path = "../../../utils/build-script-utils", optional = true } -substrate-frame-cli = { path = "../../../utils/frame/frame-utilities-cli", optional = true } -sc-cli = { path = "../../../client/cli", optional = true } -pallet-balances = { path = "../../../frame/balances" } -sc-storage-monitor = { path = "../../../client/storage-monitor" } + +polkadot-sdk = { path = "../../../../umbrella", features = ["frame-benchmarking-cli", "sc-cli", "sc-storage-monitor", "substrate-build-script-utils"], optional = true } [features] default = ["cli"] cli = [ "clap", "clap_complete", - "frame-benchmarking-cli", "node-inspect", - "sc-cli", - "sc-service/rocksdb", - "substrate-build-script-utils", - "substrate-frame-cli", + "polkadot-sdk", ] runtime-benchmarks = [ - "frame-benchmarking-cli/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", "kitchensink-runtime/runtime-benchmarks", "node-inspect?/runtime-benchmarks", - "pallet-asset-tx-payment/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "pallet-glutton/runtime-benchmarks", - "pallet-im-online/runtime-benchmarks", - "pallet-skip-feeless-payment/runtime-benchmarks", - "pallet-sudo/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-treasury/runtime-benchmarks", - "sc-client-db/runtime-benchmarks", - "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", ] -# Enable features that allow the runtime to be tried and debugged. Name might be subject to change -# in the near future. try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", "kitchensink-runtime/try-runtime", - "pallet-asset-conversion-tx-payment/try-runtime", - "pallet-asset-tx-payment/try-runtime", - "pallet-assets/try-runtime", - "pallet-balances/try-runtime", - "pallet-contracts/try-runtime", - "pallet-glutton/try-runtime", - "pallet-im-online/try-runtime", - "pallet-root-testing/try-runtime", - "pallet-skip-feeless-payment/try-runtime", - "pallet-sudo/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-transaction-payment/try-runtime", - "pallet-treasury/try-runtime", - "sp-runtime/try-runtime", + "polkadot-sdk/try-runtime", "substrate-cli-test-utils/try-runtime", ] diff --git a/substrate/bin/node/cli/benches/block_production.rs b/substrate/bin/node/cli/benches/block_production.rs index f60610873d8c5a3832c77864a2c93fed023998ea..c16b25187e5f58a218fa22fc55cfdc58a214c6bf 100644 --- a/substrate/bin/node/cli/benches/block_production.rs +++ b/substrate/bin/node/cli/benches/block_production.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use polkadot_sdk::*; + use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput}; use kitchensink_runtime::{constants::currency::*, BalancesCall}; @@ -86,6 +88,8 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { rpc_message_buffer_capacity: Default::default(), rpc_batch_config: RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/substrate/bin/node/cli/benches/executor.rs b/substrate/bin/node/cli/benches/executor.rs index a326e1a79ea347f169e372581d07dc4f43848e24..fa4da5c13d4344208c6a51067fbf78e380923a82 100644 --- a/substrate/bin/node/cli/benches/executor.rs +++ b/substrate/bin/node/cli/benches/executor.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use polkadot_sdk::*; + use codec::{Decode, Encode}; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use frame_support::Hashable; @@ -55,7 +57,7 @@ const HEAP_PAGES: u64 = 20; type TestExternalities = CoreTestExternalities; fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH, None) } fn new_test_ext(genesis_config: &RuntimeGenesisConfig) -> TestExternalities { diff --git a/substrate/bin/node/cli/benches/transaction_pool.rs b/substrate/bin/node/cli/benches/transaction_pool.rs index 1906ae697e9007ece7539757dbd40d9f504007bd..6618f4b1132e031cd7e6c69451e3ff8997e86684 100644 --- a/substrate/bin/node/cli/benches/transaction_pool.rs +++ b/substrate/bin/node/cli/benches/transaction_pool.rs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use polkadot_sdk::*; use std::time::Duration; use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput}; @@ -82,6 +83,8 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { rpc_message_buffer_capacity: Default::default(), rpc_batch_config: RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/substrate/bin/node/cli/bin/main.rs b/substrate/bin/node/cli/bin/main.rs index ccc7d7b6b112558832549bf7e5435f68ac0fe944..b18d08880556093319cad2dfd3faa789fae819b1 100644 --- a/substrate/bin/node/cli/bin/main.rs +++ b/substrate/bin/node/cli/bin/main.rs @@ -20,6 +20,7 @@ #![warn(missing_docs)] +use polkadot_sdk::*; use staging_node_cli as node_cli; fn main() -> sc_cli::Result<()> { diff --git a/substrate/bin/node/cli/build.rs b/substrate/bin/node/cli/build.rs index 033f1e3349e6fae1f062f9a075dcb66295aab22d..c25d15de057425458230f48be270ca7ad09d895e 100644 --- a/substrate/bin/node/cli/build.rs +++ b/substrate/bin/node/cli/build.rs @@ -27,8 +27,10 @@ mod cli { use clap::{CommandFactory, ValueEnum}; use clap_complete::{generate_to, Shell}; + use polkadot_sdk::substrate_build_script_utils::{ + generate_cargo_keys, rerun_if_git_head_changed, + }; use std::{env, fs, path::Path}; - use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; pub fn main() { build_shell_completion(); diff --git a/substrate/bin/node/cli/src/benchmarking.rs b/substrate/bin/node/cli/src/benchmarking.rs index 333f855f2d7bb876d7768784b60dfa21e1d8d708..a2b28a0f317de4fcc74b963d3ccb1c026ddfa380 100644 --- a/substrate/bin/node/cli/src/benchmarking.rs +++ b/substrate/bin/node/cli/src/benchmarking.rs @@ -22,6 +22,8 @@ use crate::service::{create_extrinsic, FullClient}; +use polkadot_sdk::*; + use kitchensink_runtime::{BalancesCall, SystemCall}; use node_primitives::{AccountId, Balance}; use sc_cli::Result; diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs index d48d4a50f85f2672d5e65c639a6a0b200c06756c..bc7821bfcf304bc7c41d50d0bf1606e33ac114bc 100644 --- a/substrate/bin/node/cli/src/chain_spec.rs +++ b/substrate/bin/node/cli/src/chain_spec.rs @@ -18,8 +18,8 @@ //! Substrate chain configurations. -use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; -use grandpa_primitives::AuthorityId as GrandpaId; +use polkadot_sdk::*; + use kitchensink_runtime::{ constants::currency::*, wasm_binary_unwrap, Block, MaxNominations, SessionKeys, StakerStatus, }; @@ -30,6 +30,8 @@ use sc_telemetry::TelemetryEndpoints; use serde::{Deserialize, Serialize}; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; +use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{crypto::UncheckedInto, sr25519, Pair, Public}; use sp_mixnet::types::AuthorityId as MixnetId; use sp_runtime::{ @@ -62,7 +64,7 @@ pub struct Extensions { } /// Specialized `ChainSpec`. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; /// Flaming Fir testnet generator pub fn flaming_fir_config() -> Result { ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) diff --git a/substrate/bin/node/cli/src/cli.rs b/substrate/bin/node/cli/src/cli.rs index 1d1af6e03e9e6eb57055b416038ee97ba95f3e3a..c0dcacb2e4b451990ea08c0c29fd1f92f89b3eaa 100644 --- a/substrate/bin/node/cli/src/cli.rs +++ b/substrate/bin/node/cli/src/cli.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use polkadot_sdk::*; + /// An overarching CLI command definition. #[derive(Debug, clap::Parser)] pub struct Cli { diff --git a/substrate/bin/node/cli/src/command.rs b/substrate/bin/node/cli/src/command.rs index d869b77e9122859550232136d3907e2f33a4eda3..51fbf0904cf8c303a6af3bed0c24587952723cd0 100644 --- a/substrate/bin/node/cli/src/command.rs +++ b/substrate/bin/node/cli/src/command.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use polkadot_sdk::*; + use super::benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}; use crate::{ chain_spec, service, @@ -215,7 +217,7 @@ pub fn run() -> Result<()> { new_partial(&config, None)?; let aux_revert = Box::new(|client: Arc, backend, blocks| { sc_consensus_babe::revert(client.clone(), backend, blocks)?; - grandpa::revert(client, blocks)?; + sc_consensus_grandpa::revert(client, blocks)?; Ok(()) }); Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 5dc1193daf8d67f6f9067eb42a161dab9242efed..84903bd9b872322c75346a74195aa916d5cc4843 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -20,6 +20,8 @@ //! Service implementation. Specialized wrapper over substrate service. +use polkadot_sdk::{sc_consensus_beefy as beefy, sc_consensus_grandpa as grandpa, *}; + use crate::Cli; use codec::Encode; use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; @@ -126,6 +128,7 @@ pub fn create_extrinsic( kitchensink_runtime::Runtime, >::from(tip, None), ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), ); let raw_payload = kitchensink_runtime::SignedPayload::from_raw( @@ -140,6 +143,7 @@ pub fn create_extrinsic( (), (), (), + None, ), ); let signature = raw_payload.using_encoded(|e| sender.sign(e)); @@ -668,7 +672,7 @@ pub fn new_full_base::Hash>>( let beefy_params = beefy::BeefyParams { client: client.clone(), backend: backend.clone(), - payload_provider: beefy_primitives::mmr::MmrRootProvider::new(client.clone()), + payload_provider: sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone()), runtime: client.clone(), key_store: keystore.clone(), network_params, @@ -842,6 +846,7 @@ mod tests { Address, BalancesCall, RuntimeCall, UncheckedExtrinsic, }; use node_primitives::{Block, DigestItem, Signature}; + use polkadot_sdk::*; use sc_client_api::BlockBackend; use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy}; use sc_consensus_babe::{BabeIntermediate, CompatibleDigestItem, INTERMEDIATE_KEY}; @@ -1041,6 +1046,7 @@ mod tests { let tx_payment = pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(0, None), ); + let metadata_hash = frame_metadata_hash_extension::CheckMetadataHash::new(false); let extra = ( check_non_zero_sender, check_spec_version, @@ -1050,11 +1056,22 @@ mod tests { check_nonce, check_weight, tx_payment, + metadata_hash, ); let raw_payload = SignedPayload::from_raw( function, extra, - ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), (), ()), + ( + (), + spec_version, + transaction_version, + genesis_hash, + genesis_hash, + (), + (), + (), + None, + ), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); let (function, extra, _) = raw_payload.deconstruct(); diff --git a/substrate/bin/node/cli/tests/basic.rs b/substrate/bin/node/cli/tests/basic.rs index a9eea84d926000fafce766d3aa2889919ef5c376..b1f737ce399b32de652abd8c26bad1811727fcff 100644 --- a/substrate/bin/node/cli/tests/basic.rs +++ b/substrate/bin/node/cli/tests/basic.rs @@ -22,6 +22,7 @@ use frame_support::{ weights::Weight, }; use frame_system::{self, AccountInfo, EventRecord, Phase}; +use polkadot_sdk::*; use sp_core::{storage::well_known_keys, traits::Externalities}; use sp_runtime::{ traits::Hash as HashT, transaction_validity::InvalidTransaction, ApplyExtrinsicResult, diff --git a/substrate/bin/node/cli/tests/common.rs b/substrate/bin/node/cli/tests/common.rs index 2d74cdd5a0418aa7f93d7ebadfe3598036fb38ab..95583395f73403959f20162c543617a84d2741fa 100644 --- a/substrate/bin/node/cli/tests/common.rs +++ b/substrate/bin/node/cli/tests/common.rs @@ -18,6 +18,7 @@ use codec::{Decode, Encode}; use frame_support::Hashable; use frame_system::offchain::AppCrypto; +use polkadot_sdk::*; use sc_executor::error::Result; use sp_consensus_babe::{ digests::{PreDigest, SecondaryPlainPreDigest}, @@ -48,7 +49,7 @@ pub const TEST_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"test"); pub mod sr25519 { mod app_sr25519 { use super::super::TEST_KEY_TYPE_ID; - use sp_application_crypto::{app_crypto, sr25519}; + use polkadot_sdk::sp_application_crypto::{app_crypto, sr25519}; app_crypto!(sr25519, TEST_KEY_TYPE_ID); } @@ -83,7 +84,7 @@ pub const TRANSACTION_VERSION: u32 = kitchensink_runtime::VERSION.transaction_ve pub type TestExternalities = CoreTestExternalities; pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH, None) } pub fn default_transfer_call() -> pallet_balances::Call { diff --git a/substrate/bin/node/cli/tests/fees.rs b/substrate/bin/node/cli/tests/fees.rs index 69c96bf63a6d8d7b7c24746cdf5c3c48b526c12e..9f82338b4fb03bbe36d09894add142027e419f7e 100644 --- a/substrate/bin/node/cli/tests/fees.rs +++ b/substrate/bin/node/cli/tests/fees.rs @@ -28,6 +28,7 @@ use kitchensink_runtime::{ }; use node_primitives::Balance; use node_testing::keyring::*; +use polkadot_sdk::*; use sp_runtime::{traits::One, Perbill}; pub mod common; diff --git a/substrate/bin/node/cli/tests/submit_transaction.rs b/substrate/bin/node/cli/tests/submit_transaction.rs index 5cbb0103d471b96902bb341bcd796e6cf09eac76..18826e7e90a784e2b644b88024a8d83e3e15f3c1 100644 --- a/substrate/bin/node/cli/tests/submit_transaction.rs +++ b/substrate/bin/node/cli/tests/submit_transaction.rs @@ -18,6 +18,7 @@ use codec::Decode; use frame_system::offchain::{SendSignedTransaction, Signer, SubmitTransaction}; use kitchensink_runtime::{Executive, Indices, Runtime, UncheckedExtrinsic}; +use polkadot_sdk::*; use sp_application_crypto::AppCrypto; use sp_core::offchain::{testing::TestTransactionPoolExt, TransactionPoolExt}; use sp_keyring::sr25519::Keyring::Alice; diff --git a/substrate/bin/node/inspect/Cargo.toml b/substrate/bin/node/inspect/Cargo.toml index 8453aa3cdeb18715afede5d93fb52f3c6b39be7e..5e4488903bf45fa32dd1f219bf9cf5766522e5bd 100644 --- a/substrate/bin/node/inspect/Cargo.toml +++ b/substrate/bin/node/inspect/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] clap = { version = "4.5.3", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } thiserror = { workspace = true } sc-cli = { path = "../../../client/cli" } sc-client-api = { path = "../../../client/api" } diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index 00eab9b75f60dcc4f5b2c8bee15e61d14f306b3c..e8cc7b3482b66ef8e850871670430b23f2923396 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # third-party dependencies -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } @@ -31,408 +31,45 @@ serde_json = { features = ["alloc", "arbitrary_precision"], workspace = true } # pallet-asset-conversion: turn on "num-traits" feature primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "num-traits", "scale-info"] } -# primitives -sp-authority-discovery = { path = "../../../primitives/authority-discovery", default-features = false, features = ["serde"] } -sp-consensus-babe = { path = "../../../primitives/consensus/babe", default-features = false, features = ["serde"] } -sp-consensus-beefy = { path = "../../../primitives/consensus/beefy", default-features = false } -sp-consensus-grandpa = { path = "../../../primitives/consensus/grandpa", default-features = false, features = ["serde"] } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false } -sp-genesis-builder = { default-features = false, path = "../../../primitives/genesis-builder" } -sp-inherents = { path = "../../../primitives/inherents", default-features = false } +polkadot-sdk = { path = "../../../../umbrella", features = ["runtime", "tuples-96"], default-features = false } + +# shared code between runtime and node node-primitives = { path = "../primitives", default-features = false } -sp-mixnet = { path = "../../../primitives/mixnet", default-features = false } -sp-offchain = { path = "../../../primitives/offchain", default-features = false } -sp-core = { path = "../../../primitives/core", default-features = false, features = ["serde"] } -sp-std = { path = "../../../primitives/std", default-features = false } -sp-api = { path = "../../../primitives/api", default-features = false } -sp-runtime = { path = "../../../primitives/runtime", default-features = false, features = ["serde"] } -sp-staking = { path = "../../../primitives/staking", default-features = false, features = ["serde"] } -sp-storage = { path = "../../../primitives/storage", default-features = false } -sp-session = { path = "../../../primitives/session", default-features = false } -sp-transaction-pool = { path = "../../../primitives/transaction-pool", default-features = false } -sp-statement-store = { path = "../../../primitives/statement-store", default-features = false, features = ["serde"] } -sp-version = { path = "../../../primitives/version", default-features = false, features = ["serde"] } -sp-io = { path = "../../../primitives/io", default-features = false } -# frame dependencies -frame-executive = { path = "../../../frame/executive", default-features = false } -frame-benchmarking = { path = "../../../frame/benchmarking", default-features = false } -frame-benchmarking-pallet-pov = { path = "../../../frame/benchmarking/pov", default-features = false } -frame-support = { path = "../../../frame/support", default-features = false, features = ["experimental", "tuples-96"] } -frame-system = { path = "../../../frame/system", default-features = false } -frame-system-benchmarking = { path = "../../../frame/system/benchmarking", default-features = false, optional = true } -frame-election-provider-support = { path = "../../../frame/election-provider-support", default-features = false } -frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", default-features = false } -frame-try-runtime = { path = "../../../frame/try-runtime", default-features = false, optional = true } -pallet-alliance = { path = "../../../frame/alliance", default-features = false } -pallet-asset-conversion = { path = "../../../frame/asset-conversion", default-features = false } -pallet-asset-conversion-ops = { path = "../../../frame/asset-conversion/ops", default-features = false } -pallet-asset-rate = { path = "../../../frame/asset-rate", default-features = false } -pallet-assets = { path = "../../../frame/assets", default-features = false } -pallet-authority-discovery = { path = "../../../frame/authority-discovery", default-features = false } -pallet-authorship = { path = "../../../frame/authorship", default-features = false } -pallet-babe = { path = "../../../frame/babe", default-features = false } -pallet-bags-list = { path = "../../../frame/bags-list", default-features = false } -pallet-balances = { path = "../../../frame/balances", default-features = false } -pallet-beefy = { path = "../../../frame/beefy", default-features = false } -pallet-beefy-mmr = { path = "../../../frame/beefy-mmr", default-features = false } -pallet-bounties = { path = "../../../frame/bounties", default-features = false } -pallet-broker = { path = "../../../frame/broker", default-features = false } -pallet-child-bounties = { path = "../../../frame/child-bounties", default-features = false } -pallet-collective = { path = "../../../frame/collective", default-features = false } -pallet-contracts = { path = "../../../frame/contracts", default-features = false } -pallet-conviction-voting = { path = "../../../frame/conviction-voting", default-features = false } -pallet-core-fellowship = { path = "../../../frame/core-fellowship", default-features = false } -pallet-democracy = { path = "../../../frame/democracy", default-features = false } -pallet-election-provider-multi-phase = { path = "../../../frame/election-provider-multi-phase", default-features = false } -pallet-election-provider-support-benchmarking = { path = "../../../frame/election-provider-support/benchmarking", default-features = false, optional = true } -pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", default-features = false } -pallet-example-tasks = { path = "../../../frame/examples/tasks", default-features = false } -pallet-fast-unstake = { path = "../../../frame/fast-unstake", default-features = false } -pallet-migrations = { path = "../../../frame/migrations", default-features = false } +# Example pallets that are not published: pallet-example-mbm = { path = "../../../frame/examples/multi-block-migrations", default-features = false } -pallet-nis = { path = "../../../frame/nis", default-features = false } -pallet-grandpa = { path = "../../../frame/grandpa", default-features = false } -pallet-im-online = { path = "../../../frame/im-online", default-features = false } -pallet-indices = { path = "../../../frame/indices", default-features = false } -pallet-identity = { path = "../../../frame/identity", default-features = false } -pallet-lottery = { path = "../../../frame/lottery", default-features = false } -pallet-membership = { path = "../../../frame/membership", default-features = false } -pallet-message-queue = { path = "../../../frame/message-queue", default-features = false } -pallet-mixnet = { path = "../../../frame/mixnet", default-features = false } -pallet-mmr = { path = "../../../frame/merkle-mountain-range", default-features = false } -pallet-multisig = { path = "../../../frame/multisig", default-features = false } -pallet-nfts = { path = "../../../frame/nfts", default-features = false } -pallet-nfts-runtime-api = { path = "../../../frame/nfts/runtime-api", default-features = false } -pallet-nft-fractionalization = { path = "../../../frame/nft-fractionalization", default-features = false } -pallet-nomination-pools = { path = "../../../frame/nomination-pools", default-features = false } -pallet-nomination-pools-benchmarking = { path = "../../../frame/nomination-pools/benchmarking", default-features = false, optional = true } -pallet-nomination-pools-runtime-api = { path = "../../../frame/nomination-pools/runtime-api", default-features = false } -pallet-offences = { path = "../../../frame/offences", default-features = false } -pallet-offences-benchmarking = { path = "../../../frame/offences/benchmarking", default-features = false, optional = true } -pallet-glutton = { path = "../../../frame/glutton", default-features = false } -pallet-preimage = { path = "../../../frame/preimage", default-features = false } -pallet-proxy = { path = "../../../frame/proxy", default-features = false } -pallet-insecure-randomness-collective-flip = { path = "../../../frame/insecure-randomness-collective-flip", default-features = false } -pallet-ranked-collective = { path = "../../../frame/ranked-collective", default-features = false } -pallet-recovery = { path = "../../../frame/recovery", default-features = false } -pallet-referenda = { path = "../../../frame/referenda", default-features = false } -pallet-remark = { path = "../../../frame/remark", default-features = false } -pallet-root-testing = { path = "../../../frame/root-testing", default-features = false } -pallet-salary = { path = "../../../frame/salary", default-features = false } -pallet-session = { path = "../../../frame/session", default-features = false, features = ["historical"] } -pallet-session-benchmarking = { path = "../../../frame/session/benchmarking", default-features = false, optional = true } -pallet-staking = { path = "../../../frame/staking", default-features = false } -pallet-staking-reward-curve = { path = "../../../frame/staking/reward-curve", default-features = false } -pallet-staking-runtime-api = { path = "../../../frame/staking/runtime-api", default-features = false } -pallet-state-trie-migration = { path = "../../../frame/state-trie-migration", default-features = false } -pallet-statement = { path = "../../../frame/statement", default-features = false } -pallet-scheduler = { path = "../../../frame/scheduler", default-features = false } -pallet-society = { path = "../../../frame/society", default-features = false } -pallet-sudo = { path = "../../../frame/sudo", default-features = false } -pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } -pallet-tips = { path = "../../../frame/tips", default-features = false } -pallet-treasury = { path = "../../../frame/treasury", default-features = false } -pallet-utility = { path = "../../../frame/utility", default-features = false } -pallet-transaction-payment = { path = "../../../frame/transaction-payment", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { path = "../../../frame/transaction-payment/rpc/runtime-api", default-features = false } -pallet-asset-conversion-tx-payment = { path = "../../../frame/transaction-payment/asset-conversion-tx-payment", default-features = false } -pallet-asset-tx-payment = { path = "../../../frame/transaction-payment/asset-tx-payment", default-features = false } -pallet-skip-feeless-payment = { path = "../../../frame/transaction-payment/skip-feeless-payment", default-features = false } -pallet-transaction-storage = { path = "../../../frame/transaction-storage", default-features = false } -pallet-uniques = { path = "../../../frame/uniques", default-features = false } -pallet-vesting = { path = "../../../frame/vesting", default-features = false } -pallet-whitelist = { path = "../../../frame/whitelist", default-features = false } -pallet-tx-pause = { path = "../../../frame/tx-pause", default-features = false } -pallet-safe-mode = { path = "../../../frame/safe-mode", default-features = false } -pallet-parameters = { path = "../../../frame/parameters", default-features = false } +pallet-example-tasks = { path = "../../../frame/examples/tasks", default-features = false } [build-dependencies] substrate-wasm-builder = { path = "../../../utils/wasm-builder", optional = true } [features] default = ["std"] -with-tracing = ["frame-executive/with-tracing"] +with-tracing = ["polkadot-sdk/with-tracing"] std = [ "codec/std", - "frame-benchmarking-pallet-pov/std", - "frame-benchmarking/std", - "frame-election-provider-support/std", - "frame-executive/std", - "frame-support/std", - "frame-system-benchmarking?/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime?/std", "log/std", "node-primitives/std", - "pallet-alliance/std", - "pallet-asset-conversion-ops/std", - "pallet-asset-conversion-tx-payment/std", - "pallet-asset-conversion/std", - "pallet-asset-rate/std", - "pallet-asset-tx-payment/std", - "pallet-assets/std", - "pallet-authority-discovery/std", - "pallet-authorship/std", - "pallet-babe/std", - "pallet-bags-list/std", - "pallet-balances/std", - "pallet-beefy-mmr/std", - "pallet-beefy/std", - "pallet-bounties/std", - "pallet-broker/std", - "pallet-child-bounties/std", - "pallet-collective/std", - "pallet-contracts/std", - "pallet-conviction-voting/std", - "pallet-core-fellowship/std", - "pallet-democracy/std", - "pallet-election-provider-multi-phase/std", - "pallet-election-provider-support-benchmarking?/std", - "pallet-elections-phragmen/std", "pallet-example-mbm/std", "pallet-example-tasks/std", - "pallet-fast-unstake/std", - "pallet-glutton/std", - "pallet-grandpa/std", - "pallet-identity/std", - "pallet-im-online/std", - "pallet-indices/std", - "pallet-insecure-randomness-collective-flip/std", - "pallet-lottery/std", - "pallet-membership/std", - "pallet-message-queue/std", - "pallet-migrations/std", - "pallet-mixnet/std", - "pallet-mmr/std", - "pallet-multisig/std", - "pallet-nft-fractionalization/std", - "pallet-nfts-runtime-api/std", - "pallet-nfts/std", - "pallet-nis/std", - "pallet-nomination-pools-benchmarking?/std", - "pallet-nomination-pools-runtime-api/std", - "pallet-nomination-pools/std", - "pallet-offences-benchmarking?/std", - "pallet-offences/std", - "pallet-parameters/std", - "pallet-preimage/std", - "pallet-proxy/std", - "pallet-ranked-collective/std", - "pallet-recovery/std", - "pallet-referenda/std", - "pallet-remark/std", - "pallet-root-testing/std", - "pallet-safe-mode/std", - "pallet-salary/std", - "pallet-scheduler/std", - "pallet-session-benchmarking?/std", - "pallet-session/std", - "pallet-skip-feeless-payment/std", - "pallet-society/std", - "pallet-staking-runtime-api/std", - "pallet-staking/std", - "pallet-state-trie-migration/std", - "pallet-statement/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-tips/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-transaction-storage/std", - "pallet-treasury/std", - "pallet-tx-pause/std", - "pallet-uniques/std", - "pallet-utility/std", - "pallet-vesting/std", - "pallet-whitelist/std", + "polkadot-sdk/std", "primitive-types/std", "scale-info/std", "serde_json/std", - "sp-api/std", - "sp-authority-discovery/std", - "sp-block-builder/std", - "sp-consensus-babe/std", - "sp-consensus-beefy/std", - "sp-consensus-grandpa/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/std", - "sp-io/std", - "sp-mixnet/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-staking/std", - "sp-statement-store/std", - "sp-std/std", - "sp-storage/std", - "sp-transaction-pool/std", - "sp-version/std", "substrate-wasm-builder", ] runtime-benchmarks = [ - "frame-benchmarking-pallet-pov/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-election-provider-support/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-alliance/runtime-benchmarks", - "pallet-asset-conversion-ops/runtime-benchmarks", - "pallet-asset-conversion/runtime-benchmarks", - "pallet-asset-rate/runtime-benchmarks", - "pallet-asset-tx-payment/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-babe/runtime-benchmarks", - "pallet-bags-list/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-bounties/runtime-benchmarks", - "pallet-broker/runtime-benchmarks", - "pallet-child-bounties/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", - "pallet-contracts/runtime-benchmarks", - "pallet-conviction-voting/runtime-benchmarks", - "pallet-core-fellowship/runtime-benchmarks", - "pallet-democracy/runtime-benchmarks", - "pallet-election-provider-multi-phase/runtime-benchmarks", - "pallet-election-provider-support-benchmarking/runtime-benchmarks", - "pallet-elections-phragmen/runtime-benchmarks", "pallet-example-mbm/runtime-benchmarks", "pallet-example-tasks/runtime-benchmarks", - "pallet-fast-unstake/runtime-benchmarks", - "pallet-glutton/runtime-benchmarks", - "pallet-grandpa/runtime-benchmarks", - "pallet-identity/runtime-benchmarks", - "pallet-im-online/runtime-benchmarks", - "pallet-indices/runtime-benchmarks", - "pallet-lottery/runtime-benchmarks", - "pallet-membership/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-migrations/runtime-benchmarks", - "pallet-mixnet/runtime-benchmarks", - "pallet-mmr/runtime-benchmarks", - "pallet-multisig/runtime-benchmarks", - "pallet-nft-fractionalization/runtime-benchmarks", - "pallet-nfts/runtime-benchmarks", - "pallet-nis/runtime-benchmarks", - "pallet-nomination-pools-benchmarking/runtime-benchmarks", - "pallet-nomination-pools/runtime-benchmarks", - "pallet-offences-benchmarking/runtime-benchmarks", - "pallet-offences/runtime-benchmarks", - "pallet-parameters/runtime-benchmarks", - "pallet-preimage/runtime-benchmarks", - "pallet-proxy/runtime-benchmarks", - "pallet-ranked-collective/runtime-benchmarks", - "pallet-recovery/runtime-benchmarks", - "pallet-referenda/runtime-benchmarks", - "pallet-remark/runtime-benchmarks", - "pallet-safe-mode/runtime-benchmarks", - "pallet-salary/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", - "pallet-session-benchmarking/runtime-benchmarks", - "pallet-skip-feeless-payment/runtime-benchmarks", - "pallet-society/runtime-benchmarks", - "pallet-staking/runtime-benchmarks", - "pallet-state-trie-migration/runtime-benchmarks", - "pallet-sudo/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-tips/runtime-benchmarks", - "pallet-transaction-storage/runtime-benchmarks", - "pallet-treasury/runtime-benchmarks", - "pallet-tx-pause/runtime-benchmarks", - "pallet-uniques/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "pallet-vesting/runtime-benchmarks", - "pallet-whitelist/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", ] try-runtime = [ - "frame-benchmarking-pallet-pov/try-runtime", - "frame-election-provider-support/try-runtime", - "frame-executive/try-runtime", - "frame-support/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime/try-runtime", - "pallet-alliance/try-runtime", - "pallet-asset-conversion-ops/try-runtime", - "pallet-asset-conversion-tx-payment/try-runtime", - "pallet-asset-conversion/try-runtime", - "pallet-asset-rate/try-runtime", - "pallet-asset-tx-payment/try-runtime", - "pallet-assets/try-runtime", - "pallet-authority-discovery/try-runtime", - "pallet-authorship/try-runtime", - "pallet-babe/try-runtime", - "pallet-bags-list/try-runtime", - "pallet-balances/try-runtime", - "pallet-beefy-mmr/try-runtime", - "pallet-beefy/try-runtime", - "pallet-bounties/try-runtime", - "pallet-broker/try-runtime", - "pallet-child-bounties/try-runtime", - "pallet-collective/try-runtime", - "pallet-contracts/try-runtime", - "pallet-conviction-voting/try-runtime", - "pallet-core-fellowship/try-runtime", - "pallet-democracy/try-runtime", - "pallet-election-provider-multi-phase/try-runtime", - "pallet-elections-phragmen/try-runtime", "pallet-example-mbm/try-runtime", "pallet-example-tasks/try-runtime", - "pallet-fast-unstake/try-runtime", - "pallet-glutton/try-runtime", - "pallet-grandpa/try-runtime", - "pallet-identity/try-runtime", - "pallet-im-online/try-runtime", - "pallet-indices/try-runtime", - "pallet-insecure-randomness-collective-flip/try-runtime", - "pallet-lottery/try-runtime", - "pallet-membership/try-runtime", - "pallet-message-queue/try-runtime", - "pallet-migrations/try-runtime", - "pallet-mixnet/try-runtime", - "pallet-mmr/try-runtime", - "pallet-multisig/try-runtime", - "pallet-nft-fractionalization/try-runtime", - "pallet-nfts/try-runtime", - "pallet-nis/try-runtime", - "pallet-nomination-pools/try-runtime", - "pallet-offences/try-runtime", - "pallet-parameters/try-runtime", - "pallet-preimage/try-runtime", - "pallet-proxy/try-runtime", - "pallet-ranked-collective/try-runtime", - "pallet-recovery/try-runtime", - "pallet-referenda/try-runtime", - "pallet-remark/try-runtime", - "pallet-root-testing/try-runtime", - "pallet-safe-mode/try-runtime", - "pallet-salary/try-runtime", - "pallet-scheduler/try-runtime", - "pallet-session/try-runtime", - "pallet-skip-feeless-payment/try-runtime", - "pallet-society/try-runtime", - "pallet-staking/try-runtime", - "pallet-state-trie-migration/try-runtime", - "pallet-statement/try-runtime", - "pallet-sudo/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-tips/try-runtime", - "pallet-transaction-payment/try-runtime", - "pallet-transaction-storage/try-runtime", - "pallet-treasury/try-runtime", - "pallet-tx-pause/try-runtime", - "pallet-uniques/try-runtime", - "pallet-utility/try-runtime", - "pallet-vesting/try-runtime", - "pallet-whitelist/try-runtime", - "sp-runtime/try-runtime", + "polkadot-sdk/try-runtime", ] experimental = [ - "frame-support/experimental", - "frame-system/experimental", "pallet-example-tasks/experimental", ] + +metadata-hash = ["substrate-wasm-builder/metadata-hash"] diff --git a/substrate/bin/node/runtime/build.rs b/substrate/bin/node/runtime/build.rs index b7676a70dfe843e2cd47fc600ef599bbe7bff591..0e11c579f09ee04918c5d53d4f8779044b57ef30 100644 --- a/substrate/bin/node/runtime/build.rs +++ b/substrate/bin/node/runtime/build.rs @@ -15,13 +15,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] fn main() { - #[cfg(feature = "std")] - { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build(); - } + substrate_wasm_builder::WasmBuilder::build_using_defaults() } + +#[cfg(all(feature = "std", feature = "metadata-hash"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("Test", 14) + .build() +} + +#[cfg(not(feature = "std"))] +fn main() {} diff --git a/substrate/bin/node/runtime/src/assets_api.rs b/substrate/bin/node/runtime/src/assets_api.rs index 792ed7c6576bd85485eae9abe84ea17d5749cd13..38ec56507113f561721887689a5f4540121e2403 100644 --- a/substrate/bin/node/runtime/src/assets_api.rs +++ b/substrate/bin/node/runtime/src/assets_api.rs @@ -18,6 +18,8 @@ //! Runtime API definition for assets. +use polkadot_sdk::*; + use codec::Codec; use sp_std::vec::Vec; diff --git a/substrate/bin/node/runtime/src/constants.rs b/substrate/bin/node/runtime/src/constants.rs index e4fafbf0fa4790121787788cef8aa2547b226cf3..d13dca48d1f125acdc38217b677279f259a35aa5 100644 --- a/substrate/bin/node/runtime/src/constants.rs +++ b/substrate/bin/node/runtime/src/constants.rs @@ -50,7 +50,7 @@ pub mod time { /// always be assigned, in which case `MILLISECS_PER_BLOCK` and /// `SLOT_DURATION` should have the same value. /// - /// + /// pub const MILLISECS_PER_BLOCK: Moment = 3000; pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000; diff --git a/substrate/bin/node/runtime/src/impls.rs b/substrate/bin/node/runtime/src/impls.rs index 34f043b33a4edfe2d8cdbe154896e937826110ca..dbe562857c99fcdd4730edd0aa5d985ab2e6dd51 100644 --- a/substrate/bin/node/runtime/src/impls.rs +++ b/substrate/bin/node/runtime/src/impls.rs @@ -17,6 +17,8 @@ //! Some configurable implementations as associated type for the substrate runtime. +use polkadot_sdk::*; + use frame_support::{ pallet_prelude::*, traits::{ @@ -118,6 +120,7 @@ mod multiplier_tests { weights::{Weight, WeightToFee}, }; use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; + use polkadot_sdk::*; use sp_runtime::{ assert_eq_error_rate, traits::{Convert, One, Zero}, diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 18b0d0c31a4df97010149c12c1e12b3c2d4d5119..7d9128bb940a55bfc2b0497600c1f6f5ffa56119 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -22,6 +22,8 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limits. #![recursion_limit = "1024"] +use polkadot_sdk::*; + use codec::{Decode, Encode, MaxEncodedLen}; use frame_election_provider_support::{ bounds::{ElectionBounds, ElectionBoundsBuilder}, @@ -910,7 +912,7 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = Staking; + type StakeAdapter = pallet_nomination_pools::adapter::TransferStake; type PostUnbondingPoolsWindow = PostUnbondPoolsWindow; type MaxMetadataLen = ConstU32<256>; type MaxUnbonding = ConstU32<8>; @@ -1341,6 +1343,9 @@ impl pallet_tips::Config for Runtime { } parameter_types! { + pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerByte: Balance = deposit(0, 1); + pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); pub Schedule: pallet_contracts::Schedule = Default::default(); pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30); } @@ -1358,9 +1363,9 @@ impl pallet_contracts::Config for Runtime { /// change because that would break already deployed contracts. The `Call` structure itself /// is not allowed to change the indices of existing pallets, too. type CallFilter = Nothing; - type DepositPerItem = dynamic_params::contracts::DepositPerItem; - type DepositPerByte = dynamic_params::contracts::DepositPerByte; - type DefaultDepositLimit = dynamic_params::contracts::DefaultDepositLimit; + type DepositPerItem = DepositPerItem; + type DepositPerByte = DepositPerByte; + type DefaultDepositLimit = DefaultDepositLimit; type CallStack = [pallet_contracts::Frame; 5]; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; @@ -1434,6 +1439,7 @@ where tip, None, ), ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), ); let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { @@ -1869,6 +1875,7 @@ impl pallet_core_fellowship::Config for Runtime { type ApproveOrigin = EnsureRootWithSuccess>; type PromoteOrigin = EnsureRootWithSuccess>; type EvidenceSize = ConstU32<16_384>; + type MaxRank = ConstU32<9>; } parameter_types! { @@ -2181,19 +2188,6 @@ pub mod dynamic_params { #[codec(index = 1)] pub static ByteDeposit: Balance = 1 * CENTS; } - - #[dynamic_pallet_params] - #[codec(index = 1)] - pub mod contracts { - #[codec(index = 0)] - pub static DepositPerItem: Balance = deposit(1, 0); - - #[codec(index = 1)] - pub static DepositPerByte: Balance = deposit(0, 1); - - #[codec(index = 2)] - pub static DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); - } } #[cfg(feature = "runtime-benchmarks")] @@ -2219,10 +2213,6 @@ impl EnsureOriginWithArg for DynamicParamet frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; return Ok(()) }, - RuntimeParametersKey::Contracts(_) => { - frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; - return Ok(()) - }, } } @@ -2241,6 +2231,8 @@ impl pallet_parameters::Config for Runtime { #[frame_support::runtime] mod runtime { + use super::*; + #[runtime::runtime] #[runtime::derive( RuntimeCall, @@ -2527,6 +2519,7 @@ pub type SignedExtra = ( Runtime, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, >, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. @@ -2582,7 +2575,7 @@ impl pallet_beefy::Config for Runtime { /// MMR helper types. mod mmr { - use super::Runtime; + use super::*; pub use pallet_mmr::primitives::*; pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; @@ -2592,7 +2585,7 @@ mod mmr { #[cfg(feature = "runtime-benchmarks")] mod benches { - frame_benchmarking::define_benchmarks!( + polkadot_sdk::frame_benchmarking::define_benchmarks!( [frame_benchmarking, BaselineBench::] [frame_benchmarking_pallet_pov, Pov] [pallet_alliance, Alliance] @@ -3094,7 +3087,7 @@ impl_runtime_apis! { fn generate_proof( block_numbers: Vec, best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { + ) -> Result<(Vec, mmr::LeafProof), mmr::Error> { Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( @@ -3108,7 +3101,7 @@ impl_runtime_apis! { ) } - fn verify_proof(leaves: Vec, proof: mmr::Proof) + fn verify_proof(leaves: Vec, proof: mmr::LeafProof) -> Result<(), mmr::Error> { let leaves = leaves.into_iter().map(|leaf| @@ -3121,7 +3114,7 @@ impl_runtime_apis! { fn verify_proof_stateless( root: mmr::Hash, leaves: Vec, - proof: mmr::Proof + proof: mmr::LeafProof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); pallet_mmr::verify_leaves_proof::(root, nodes, proof) diff --git a/substrate/bin/node/testing/Cargo.toml b/substrate/bin/node/testing/Cargo.toml index fa3f90193ba5d11325bfb068fa69780495ec8c90..3ba3f07510e006458cf23b246e293af4e288c624 100644 --- a/substrate/bin/node/testing/Cargo.toml +++ b/substrate/bin/node/testing/Cargo.toml @@ -16,11 +16,12 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } fs_extra = "1" futures = "0.3.30" log = { workspace = true, default-features = true } tempfile = "3.1.0" +frame-metadata-hash-extension = { path = "../../../frame/metadata-hash-extension" } frame-system = { path = "../../../frame/system" } node-cli = { package = "staging-node-cli", path = "../cli" } node-primitives = { path = "../primitives" } diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs index e5c2563905e9ea59901db1564f2b0f34f6bd4aec..007d314684cf17faeda6adb4842513ea57030fdc 100644 --- a/substrate/bin/node/testing/src/bench.rs +++ b/substrate/bin/node/testing/src/bench.rs @@ -571,6 +571,8 @@ impl BenchKeyring { tx_version, genesis_hash, genesis_hash, + // metadata_hash + None::<()>, ); let key = self.accounts.get(&signed).expect("Account id not found in keyring"); let signature = payload.using_encoded(|b| { diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs index f712191bed695031275cfb11c5e22c8fa2a26f78..eab088d9100ef266f26b600a501e78881e557efe 100644 --- a/substrate/bin/node/testing/src/keyring.rs +++ b/substrate/bin/node/testing/src/keyring.rs @@ -82,6 +82,7 @@ pub fn signed_extra(nonce: Nonce, extra_fee: Balance) -> SignedExtra { pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(extra_fee, None), ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), ) } @@ -91,11 +92,19 @@ pub fn sign( spec_version: u32, tx_version: u32, genesis_hash: [u8; 32], + metadata_hash: Option<[u8; 32]>, ) -> UncheckedExtrinsic { match xt.signed { Some((signed, extra)) => { - let payload = - (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); + let payload = ( + xt.function, + extra.clone(), + spec_version, + tx_version, + genesis_hash, + genesis_hash, + metadata_hash, + ); let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload diff --git a/substrate/bin/utils/chain-spec-builder/Cargo.toml b/substrate/bin/utils/chain-spec-builder/Cargo.toml index 5c8a3ab4e89a55e5e61c371a41878ab8457ec12b..cc9aa402fd1a8b4ede854aaedc39db41923fcecc 100644 --- a/substrate/bin/utils/chain-spec-builder/Cargo.toml +++ b/substrate/bin/utils/chain-spec-builder/Cargo.toml @@ -1,13 +1,14 @@ [package] name = "staging-chain-spec-builder" -version = "3.0.0" +version = "1.6.0" authors.workspace = true edition.workspace = true build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository.workspace = true -publish = false +publish = true +description = "Utility for building chain-specification files for Substrate-based runtimes based on `sp-genesis-builder`" [lints] workspace = true diff --git a/substrate/bin/utils/chain-spec-builder/src/lib.rs b/substrate/bin/utils/chain-spec-builder/src/lib.rs index 7982da76227aeb70cc4683cc1887440cb2c0ecc0..167704d3633d07c83964b087e147b76447a9a5a1 100644 --- a/substrate/bin/utils/chain-spec-builder/src/lib.rs +++ b/substrate/bin/utils/chain-spec-builder/src/lib.rs @@ -206,9 +206,14 @@ struct NamedPresetCmd { /// /// The code field of the chain spec will be updated with the runtime provided in the /// command line. This operation supports both plain and raw formats. +/// +/// This command does not update chain-spec file in-place. The result of this command will be stored +/// in a file given as `-c/--chain-spec-path` command line argument. #[derive(Parser, Debug, Clone)] pub struct UpdateCodeCmd { /// Chain spec to be updated. + /// + /// Please note that the file will not be updated in-place. pub input_chain_spec: PathBuf, /// The path to new runtime wasm blob to be stored into chain-spec. pub runtime_wasm_path: PathBuf, diff --git a/substrate/bin/utils/subkey/README.md b/substrate/bin/utils/subkey/README.md index fc1053e232d70d746cf315d203a51dfd09e8447c..5c6dda37edf681b0425fa5e2c2072fd511200587 100644 --- a/substrate/bin/utils/subkey/README.md +++ b/substrate/bin/utils/subkey/README.md @@ -74,7 +74,7 @@ The output above shows a **secret phrase** (also called **mnemonic phrase**) and **Private Key**). Those 2 secrets are the pieces of information you MUST keep safe and secret. All the other information below can be derived from those secrets. -The output above also show the **public key** and the **Account ID**. Those are the independent from the network where +The output above also shows the **public key** and the **Account ID**. Those are the independent from the network where you will use the key. The **SS58 address** (or **Public Address**) of a new account is a representation of the public keys of an account for @@ -152,7 +152,7 @@ subkey inspect "soup lyrics media market way crouch elevator put moon useful que which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined **password** -(`extra_secret` in our example) is now required to fully recover the account. Let's inspect the the previous mnemonic, +(`extra_secret` in our example) is now required to fully recover the account. Let's inspect the previous mnemonic, this time passing also the required `password` as shown below: ```bash diff --git a/substrate/client/api/Cargo.toml b/substrate/client/api/Cargo.toml index fb650c5b532f2cbf841dc65e5f7f1a3c35dae733..147ea2bfbf5df83716c4a7f1f5fb2ade0c41d3f8 100644 --- a/substrate/client/api/Cargo.toml +++ b/substrate/client/api/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } fnv = "1.0.6" diff --git a/substrate/client/api/src/in_mem.rs b/substrate/client/api/src/in_mem.rs index b933ed1f17e01a8822b958ac6a064fe2f3503926..ba89aede9147ff0ebe16beb6fedf39389ee9c700 100644 --- a/substrate/client/api/src/in_mem.rs +++ b/substrate/client/api/src/in_mem.rs @@ -419,20 +419,6 @@ impl blockchain::Backend for Blockchain { Ok(self.storage.read().leaves.hashes()) } - fn displaced_leaves_after_finalizing( - &self, - block_number: NumberFor, - ) -> sp_blockchain::Result> { - Ok(self - .storage - .read() - .leaves - .displaced_by_finalize_height(block_number) - .leaves() - .cloned() - .collect::>()) - } - fn children(&self, _parent_hash: Block::Hash) -> sp_blockchain::Result> { unimplemented!() } diff --git a/substrate/client/api/src/leaves.rs b/substrate/client/api/src/leaves.rs index a8a988771e2fdf346dd0c50983d0e8b32c74bafc..e129de8bf3fad30a0bb76569957c93138c631db8 100644 --- a/substrate/client/api/src/leaves.rs +++ b/substrate/client/api/src/leaves.rs @@ -49,7 +49,7 @@ pub struct FinalizationOutcome { removed: BTreeMap, Vec>, } -impl FinalizationOutcome { +impl FinalizationOutcome { /// Merge with another. This should only be used for displaced items that /// are produced within one transaction of each other. pub fn merge(&mut self, mut other: Self) { @@ -63,6 +63,16 @@ impl FinalizationOutcome { pub fn leaves(&self) -> impl Iterator { self.removed.values().flatten() } + + /// Constructor + pub fn new(new_displaced: impl Iterator) -> Self { + let mut removed = BTreeMap::, Vec>::new(); + for (hash, number) in new_displaced { + removed.entry(Reverse(number)).or_default().push(hash); + } + + FinalizationOutcome { removed } + } } /// list of leaf hashes ordered by number (descending). @@ -151,39 +161,12 @@ where Some(RemoveOutcome { inserted, removed: LeafSetItem { hash, number } }) } - /// Note a block height finalized, displacing all leaves with number less than the finalized - /// block's. - /// - /// Although it would be more technically correct to also prune out leaves at the - /// same number as the finalized block, but with different hashes, the current behavior - /// is simpler and our assumptions about how finalization works means that those leaves - /// will be pruned soon afterwards anyway. - pub fn finalize_height(&mut self, number: N) -> FinalizationOutcome { - let boundary = if number == N::zero() { - return FinalizationOutcome { removed: BTreeMap::new() } - } else { - number - N::one() - }; - - let below_boundary = self.storage.split_off(&Reverse(boundary)); - FinalizationOutcome { removed: below_boundary } - } - - /// The same as [`Self::finalize_height`], but it only simulates the operation. - /// - /// This means that no changes are done. - /// - /// Returns the leaves that would be displaced by finalizing the given block. - pub fn displaced_by_finalize_height(&self, number: N) -> FinalizationOutcome { - let boundary = if number == N::zero() { - return FinalizationOutcome { removed: BTreeMap::new() } - } else { - number - N::one() - }; - - let below_boundary = self.storage.range(&Reverse(boundary)..); - FinalizationOutcome { - removed: below_boundary.map(|(k, v)| (k.clone(), v.clone())).collect(), + /// Remove all leaves displaced by the last block finalization. + pub fn remove_displaced_leaves(&mut self, displaced_leaves: &FinalizationOutcome) { + for (number, hashes) in &displaced_leaves.removed { + for hash in hashes.iter() { + self.remove_leaf(number, hash); + } } } @@ -420,32 +403,6 @@ mod tests { assert!(set.contains(11, 11_2)); } - #[test] - fn finalization_works() { - let mut set = LeafSet::new(); - set.import(9_1u32, 9u32, 0u32); - set.import(10_1, 10, 9_1); - set.import(10_2, 10, 9_1); - set.import(11_1, 11, 10_1); - set.import(11_2, 11, 10_1); - set.import(12_1, 12, 11_2); - - let outcome = set.finalize_height(11); - assert_eq!(set.count(), 2); - assert!(set.contains(11, 11_1)); - assert!(set.contains(12, 12_1)); - assert_eq!( - outcome.removed, - [(Reverse(10), vec![10_2])].into_iter().collect::>(), - ); - - set.undo().undo_finalization(outcome); - assert_eq!(set.count(), 3); - assert!(set.contains(11, 11_1)); - assert!(set.contains(12, 12_1)); - assert!(set.contains(10, 10_2)); - } - #[test] fn flush_to_disk() { const PREFIX: &[u8] = b"abcdefg"; @@ -479,35 +436,4 @@ mod tests { assert!(set.contains(10, 1_2)); assert!(!set.contains(10, 1_3)); } - - #[test] - fn finalization_consistent_with_disk() { - const PREFIX: &[u8] = b"prefix"; - let db = Arc::new(sp_database::MemDb::default()); - - let mut set = LeafSet::new(); - set.import(10_1u32, 10u32, 0u32); - set.import(11_1, 11, 10_2); - set.import(11_2, 11, 10_2); - set.import(12_1, 12, 11_123); - - assert!(set.contains(10, 10_1)); - - let mut tx = Transaction::new(); - set.prepare_transaction(&mut tx, 0, PREFIX); - db.commit(tx).unwrap(); - - let _ = set.finalize_height(11); - let mut tx = Transaction::new(); - set.prepare_transaction(&mut tx, 0, PREFIX); - db.commit(tx).unwrap(); - - assert!(set.contains(11, 11_1)); - assert!(set.contains(11, 11_2)); - assert!(set.contains(12, 12_1)); - assert!(!set.contains(10, 10_1)); - - let set2 = LeafSet::read_from_db(&*db, 0, PREFIX).unwrap(); - assert_eq!(set, set2); - } } diff --git a/substrate/client/authority-discovery/Cargo.toml b/substrate/client/authority-discovery/Cargo.toml index 0cf90ada8ac61bda63a12c5f3072017ccd067270..435ca88a80079c9da9510b0f505d21677afb52cf 100644 --- a/substrate/client/authority-discovery/Cargo.toml +++ b/substrate/client/authority-discovery/Cargo.toml @@ -17,10 +17,10 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.11" +prost-build = "0.12.4" [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } futures = "0.3.30" futures-timer = "3.0.1" ip_network = "0.4.1" @@ -28,7 +28,7 @@ libp2p = { version = "0.51.4", features = ["ed25519", "kad"] } multihash = { version = "0.17.0", default-features = false, features = ["sha2", "std"] } linked_hash_set = "0.1.4" log = { workspace = true, default-features = true } -prost = "0.12" +prost = "0.12.4" rand = "0.8.5" thiserror = { workspace = true } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } diff --git a/substrate/client/authority-discovery/src/error.rs b/substrate/client/authority-discovery/src/error.rs index 6f791237c2f229c3f94996e2a91c0c0de8800d0d..d2c567d77afcfb17f9af1cfde55ba232205e8167 100644 --- a/substrate/client/authority-discovery/src/error.rs +++ b/substrate/client/authority-discovery/src/error.rs @@ -35,7 +35,7 @@ pub enum Error { VerifyingDhtPayload, #[error("Failed to hash the authority id to be used as a dht key.")] - HashingAuthorityId(#[from] sc_network::multiaddr::multihash::Error), + HashingAuthorityId(#[from] sc_network_types::multihash::Error), #[error("Failed calling into the Substrate runtime: {0}")] CallingRuntime(#[from] sp_blockchain::Error), @@ -53,7 +53,7 @@ pub enum Error { EncodingDecodingScale(#[from] codec::Error), #[error("Failed to parse a libp2p multi address.")] - ParsingMultiaddress(#[from] sc_network::multiaddr::Error), + ParsingMultiaddress(#[from] sc_network::multiaddr::ParseError), #[error("Failed to parse a libp2p key: {0}")] ParsingLibp2pIdentity(String), diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index 53418d2d38c4a0ce0ab2c2b938b288360d2fdbbc..d89083100aa3c51c16e523a6f71ba6559cd04b62 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -35,7 +35,6 @@ use addr_cache::AddrCache; use codec::{Decode, Encode}; use ip_network::IpNetwork; use linked_hash_set::LinkedHashSet; -use multihash::{Code, Multihash, MultihashDigest}; use log::{debug, error, log_enabled}; use prometheus_endpoint::{register, Counter, CounterVec, Gauge, Opts, U64}; @@ -46,7 +45,10 @@ use sc_network::{ event::DhtEvent, multiaddr, KademliaKey, Multiaddr, NetworkDHTProvider, NetworkSigner, NetworkStateInfo, }; -use sc_network_types::PeerId; +use sc_network_types::{ + multihash::{Code, Multihash}, + PeerId, +}; use sp_api::{ApiError, ProvideRuntimeApi}; use sp_authority_discovery::{ AuthorityDiscoveryApi, AuthorityId, AuthorityPair, AuthoritySignature, diff --git a/substrate/client/authority-discovery/src/worker/addr_cache.rs b/substrate/client/authority-discovery/src/worker/addr_cache.rs index 6e3b3c8af20190f3711aac72fbd5e7cf3eb493c7..77cdfbd4f1502574cd5a1aa2434d3c0fd392fd51 100644 --- a/substrate/client/authority-discovery/src/worker/addr_cache.rs +++ b/substrate/client/authority-discovery/src/worker/addr_cache.rs @@ -176,8 +176,8 @@ fn addresses_to_peer_ids(addresses: &HashSet) -> HashSet { mod tests { use super::*; - use multihash::{self, Multihash}; use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; + use sc_network_types::multihash::Multihash; use sp_authority_discovery::{AuthorityId, AuthorityPair}; use sp_core::crypto::Pair; diff --git a/substrate/client/authority-discovery/src/worker/tests.rs b/substrate/client/authority-discovery/src/worker/tests.rs index caeac56c54073e53026ec3f8c52c8e7f88958f2b..70107c89a851d3de33d6bce65515661ec0675af1 100644 --- a/substrate/client/authority-discovery/src/worker/tests.rs +++ b/substrate/client/authority-discovery/src/worker/tests.rs @@ -29,11 +29,15 @@ use futures::{ sink::SinkExt, task::LocalSpawn, }; -use libp2p::{core::multiaddr, identity::SigningError, kad::record::Key as KademliaKey, PeerId}; +use libp2p::{identity::SigningError, kad::record::Key as KademliaKey}; use prometheus_endpoint::prometheus::default_registry; use sc_client_api::HeaderBackend; use sc_network::{service::signature::Keypair, Signature}; +use sc_network_types::{ + multiaddr::{Multiaddr, Protocol}, + PeerId, +}; use sp_api::{ApiRef, ProvideRuntimeApi}; use sp_keystore::{testing::MemoryKeystore, Keystore}; use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; @@ -168,7 +172,7 @@ impl NetworkSigner for TestNetwork { let public_key = libp2p::identity::PublicKey::try_decode_protobuf(&public_key) .map_err(|error| error.to_string())?; let peer_id: PeerId = peer_id.into(); - let remote: libp2p::PeerId = public_key.to_peer_id(); + let remote: PeerId = public_key.to_peer_id().into(); Ok(peer_id == remote && public_key.verify(message, signature)) } @@ -435,7 +439,7 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() { let peer_id = PeerId::random(); let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap(); - address.with(multiaddr::Protocol::P2p(peer_id.into())) + address.with(Protocol::P2p(peer_id.into())) }; let remote_key_store = MemoryKeystore::new(); let remote_public_key: AuthorityId = remote_key_store diff --git a/substrate/client/basic-authorship/Cargo.toml b/substrate/client/basic-authorship/Cargo.toml index 4890b66c9b2f91ef13ea74fa9f66c797d0beb32c..b75cb463b1a874c48a7b8c4511929eade4245704 100644 --- a/substrate/client/basic-authorship/Cargo.toml +++ b/substrate/client/basic-authorship/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" futures-timer = "3.0.1" log = { workspace = true, default-features = true } diff --git a/substrate/client/block-builder/Cargo.toml b/substrate/client/block-builder/Cargo.toml index e74d587d9b40fc57e0575b0fae7ecb0c5a177c15..62efe977e989c13bfc6e3fe0fb11d13ac3aca298 100644 --- a/substrate/client/block-builder/Cargo.toml +++ b/substrate/client/block-builder/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", features = [ "derive", ] } sp-api = { path = "../../primitives/api" } diff --git a/substrate/client/chain-spec/Cargo.toml b/substrate/client/chain-spec/Cargo.toml index 84320f17d7cb92c8319d437d49f70f2967e8fda1..9028a2c49eeac68929589e920544a174fd6abfd4 100644 --- a/substrate/client/chain-spec/Cargo.toml +++ b/substrate/client/chain-spec/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } memmap2 = "0.9.3" serde = { features = ["derive"], workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } @@ -34,7 +34,7 @@ sp-runtime = { path = "../../primitives/runtime" } sp-state-machine = { path = "../../primitives/state-machine" } log = { workspace = true } sp-tracing = { path = "../../primitives/tracing" } -array-bytes = { version = "6.1" } +array-bytes = "6.2.2" docify = "0.2.8" [dev-dependencies] @@ -42,3 +42,4 @@ substrate-test-runtime = { path = "../../test-utils/runtime" } sp-keyring = { path = "../../primitives/keyring" } sp-application-crypto = { default-features = false, path = "../../primitives/application-crypto", features = ["serde"] } sp-consensus-babe = { default-features = false, path = "../../primitives/consensus/babe", features = ["serde"] } +regex = "1.6.0" diff --git a/substrate/client/chain-spec/derive/src/impls.rs b/substrate/client/chain-spec/derive/src/impls.rs index c0624897c133e6ebd3ecda6556d628dccee3c53b..d8b20c5c2a8cca93bd2a6bc8da051ea3746c1e4e 100644 --- a/substrate/client/chain-spec/derive/src/impls.rs +++ b/substrate/client/chain-spec/derive/src/impls.rs @@ -19,7 +19,7 @@ use proc_macro2::{Span, TokenStream}; use proc_macro_crate::{crate_name, FoundCrate}; use quote::quote; -use syn::{DeriveInput, Error, Ident}; +use syn::{DeriveInput, Error, Ident, Path}; const CRATE_NAME: &str = "sc-chain-spec"; const ATTRIBUTE_NAME: &str = "forks"; @@ -143,7 +143,7 @@ pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { pub fn derive( ast: &DeriveInput, derive: impl Fn( - &Ident, + &Path, &Ident, &syn::Generics, Vec<&Ident>, @@ -171,25 +171,28 @@ pub fn derive( }; let name = &ast.ident; - let crate_name = match crate_name(CRATE_NAME) { + let crate_path = match crate_name(CRATE_NAME) { Ok(FoundCrate::Itself) => CRATE_NAME.replace("-", "_"), Ok(FoundCrate::Name(chain_spec_name)) => chain_spec_name, - Err(e) => { - let err = Error::new(Span::call_site(), &e).to_compile_error(); - return quote!( #err ).into() + Err(e) => match crate_name("polkadot-sdk") { + Ok(FoundCrate::Name(sdk)) => format!("{sdk}::{CRATE_NAME}").replace("-", "_"), + _ => { + return Error::new(Span::call_site(), &e).to_compile_error().into(); + }, }, }; - let crate_name = Ident::new(&crate_name, Span::call_site()); + let crate_path = + syn::parse_str::(&crate_path).expect("crate_name returns valid path; qed"); 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() + derive(&crate_path, 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); +fn generate_fork_fields(crate_path: &Path, names: &[&Ident], types: &[&syn::Type]) -> TokenStream { + let crate_path = std::iter::repeat(crate_path); quote! { - #( pub #names: Option<<#types as #crate_name::Group>::Fork>, )* + #( pub #names: Option<<#types as #crate_path::Group>::Fork>, )* } } diff --git a/substrate/client/chain-spec/res/chain_spec_as_json_fails_with_invalid_config.err b/substrate/client/chain-spec/res/chain_spec_as_json_fails_with_invalid_config.err deleted file mode 100644 index c545b53b2bafea88af090236f825bbafe2baf8f8..0000000000000000000000000000000000000000 --- a/substrate/client/chain-spec/res/chain_spec_as_json_fails_with_invalid_config.err +++ /dev/null @@ -1,114 +0,0 @@ -Invalid JSON blob: unknown field `babex`, expected one of `system`, `babe`, `substrateTest`, `balances` at line 3 column 9 for blob: -{ - "system": {}, - "babex": { - "authorities": [ - [ - "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", - 1 - ], - [ - "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", - 1 - ], - [ - "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", - 1 - ] - ], - "epochConfig": { - "c": [ - 3, - 10 - ], - "allowed_slots": "PrimaryAndSecondaryPlainSlots" - } - }, - "substrateTest": { - "authorities": [ - "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", - "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", - "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" - ] - }, - "balances": { - "balances": [ - [ - "5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH", - 100000000000000000 - ], - [ - "5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o", - 100000000000000000 - ], - [ - "5Dfis6XL8J2P6JHUnUtArnFWndn62SydeP8ee8sG2ky9nfm9", - 100000000000000000 - ], - [ - "5F4H97f7nQovyrbiq4ZetaaviNwThSVcFobcA5aGab6167dK", - 100000000000000000 - ], - [ - "5DiDShBWa1fQx6gLzpf3SFBhMinCoyvHM1BWjPNsmXS8hkrW", - 100000000000000000 - ], - [ - "5EFb84yH9tpcFuiKUcsmdoF7xeeY3ajG1ZLQimxQoFt9HMKR", - 100000000000000000 - ], - [ - "5DZLHESsfGrJ5YzT3HuRPXsSNb589xQ4Unubh1mYLodzKdVY", - 100000000000000000 - ], - [ - "5GHJzqvG6tXnngCpG7B12qjUvbo5e4e9z8Xjidk3CQZHxTPZ", - 100000000000000000 - ], - [ - "5CUnSsgAyLND3bxxnfNhgWXSe9Wn676JzLpGLgyJv858qhoX", - 100000000000000000 - ], - [ - "5CVKn7HAZW1Ky4r7Vkgsr7VEW88C2sHgUNDiwHY9Ct2hjU8q", - 100000000000000000 - ], - [ - "5H673aukQ4PeDe1U2nuv1bi32xDEziimh3PZz7hDdYUB7TNz", - 100000000000000000 - ], - [ - "5HTe9L15LJryjUAt1jZXZCBPnzbbGnpvFwbjE3NwCWaAqovf", - 100000000000000000 - ], - [ - "5D7LFzGpMwHPyDBavkRbWSKWTtJhCaPPZ379wWLT23bJwXJz", - 100000000000000000 - ], - [ - "5CLepMARnEgtVR1EkUuJVUvKh97gzergpSxUU3yKGx1v6EwC", - 100000000000000000 - ], - [ - "5Chb2UhfvZpmjjEziHbFbotM4quX32ZscRV6QJBt1rUKzz51", - 100000000000000000 - ], - [ - "5HmRp3i3ZZk7xsAvbi8hyXVP6whSMnBJGebVC4FsiZVhx52e", - 100000000000000000 - ], - [ - "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", - 100000000000000000 - ], - [ - "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", - 100000000000000000 - ], - [ - "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", - 100000000000000000 - ] - ] - } -} \ No newline at end of file diff --git a/substrate/client/chain-spec/src/chain_spec.rs b/substrate/client/chain-spec/src/chain_spec.rs index a9cdce4bf95580f6c00cbf27b0330779e4f39a28..883cd19adfd1c7543ee919a6e436df1838c6efe2 100644 --- a/substrate/client/chain-spec/src/chain_spec.rs +++ b/substrate/client/chain-spec/src/chain_spec.rs @@ -20,7 +20,7 @@ #![warn(missing_docs)] use crate::{ extension::GetExtension, genesis_config_builder::HostFunctions, ChainType, - GenesisConfigBuilderRuntimeCaller as RuntimeCaller, Properties, RuntimeGenesis, + GenesisConfigBuilderRuntimeCaller as RuntimeCaller, Properties, }; use sc_network::config::MultiaddrWithPeerId; use sc_telemetry::TelemetryEndpoints; @@ -37,7 +37,6 @@ use std::{ fs::File, marker::PhantomData, path::PathBuf, - sync::Arc, }; #[derive(Serialize, Deserialize)] @@ -58,37 +57,33 @@ impl Clone for GenesisBuildAction { } } -#[allow(deprecated)] -enum GenesisSource { +enum GenesisSource { File(PathBuf), Binary(Cow<'static, [u8]>), /// factory function + code - //Factory and G type parameter shall be removed together with `ChainSpec::from_genesis` - Factory(Arc G + Send + Sync>, Vec), Storage(Storage), /// build action + code GenesisBuilderApi(GenesisBuildAction, Vec), } -impl Clone for GenesisSource { +impl Clone for GenesisSource { fn clone(&self) -> Self { match *self { Self::File(ref path) => Self::File(path.clone()), Self::Binary(ref d) => Self::Binary(d.clone()), - Self::Factory(ref f, ref c) => Self::Factory(f.clone(), c.clone()), Self::Storage(ref s) => Self::Storage(s.clone()), Self::GenesisBuilderApi(ref s, ref c) => Self::GenesisBuilderApi(s.clone(), c.clone()), } } } -impl GenesisSource { - fn resolve(&self) -> Result, String> { +impl GenesisSource { + fn resolve(&self) -> Result { /// helper container for deserializing genesis from the JSON file (ChainSpec JSON file is /// also supported here) #[derive(Serialize, Deserialize)] - struct GenesisContainer { - genesis: Genesis, + struct GenesisContainer { + genesis: Genesis, } match self { @@ -105,19 +100,15 @@ impl GenesisSource { })? }; - let genesis: GenesisContainer = json::from_slice(&bytes) + let genesis: GenesisContainer = json::from_slice(&bytes) .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(genesis.genesis) }, Self::Binary(buf) => { - let genesis: GenesisContainer = json::from_reader(buf.as_ref()) + let genesis: GenesisContainer = json::from_reader(buf.as_ref()) .map_err(|e| format!("Error parsing embedded file: {}", e))?; Ok(genesis.genesis) }, - Self::Factory(f, code) => Ok(Genesis::RuntimeAndCode(RuntimeInnerWrapper { - runtime: f(), - code: code.clone(), - })), Self::Storage(storage) => Ok(Genesis::Raw(RawGenesis::from(storage.clone()))), Self::GenesisBuilderApi(GenesisBuildAction::Full(config), code) => Ok(Genesis::RuntimeGenesis(RuntimeGenesisInner { @@ -140,24 +131,12 @@ impl GenesisSource { } } -impl BuildStorage for ChainSpec +impl BuildStorage for ChainSpec where EHF: HostFunctions, { fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { match self.genesis.resolve()? { - #[allow(deprecated)] - Genesis::Runtime(runtime_genesis_config) => { - runtime_genesis_config.assimilate_storage(storage)?; - }, - #[allow(deprecated)] - Genesis::RuntimeAndCode(RuntimeInnerWrapper { - runtime: runtime_genesis_config, - code, - }) => { - runtime_genesis_config.assimilate_storage(storage)?; - storage.top.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code); - }, Genesis::Raw(RawGenesis { top: map, children_default: children_map }) => { storage.top.extend(map.into_iter().map(|(k, v)| (k.0, v.0))); children_map.into_iter().for_each(|(k, v)| { @@ -236,7 +215,7 @@ impl From for RawGenesis { } } -/// Inner representation of [`Genesis::RuntimeGenesis`] format +/// Inner representation of [`Genesis::RuntimeGenesis`] format #[derive(Serialize, Deserialize, Debug)] struct RuntimeGenesisInner { /// Runtime wasm code, expected to be hex-encoded in JSON. @@ -249,7 +228,7 @@ struct RuntimeGenesisInner { } /// Represents two possible variants of the contained JSON blob for the -/// [`Genesis::RuntimeGenesis`] format. +/// [`Genesis::RuntimeGenesis`] format. #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] enum RuntimeGenesisConfigJson { @@ -265,31 +244,11 @@ enum RuntimeGenesisConfigJson { Patch(json::Value), } -/// Inner variant wrapper for deprecated runtime. -#[derive(Serialize, Deserialize, Debug)] -struct RuntimeInnerWrapper { - /// The native `RuntimeGenesisConfig` struct. - runtime: G, - /// Runtime code. - #[serde(with = "sp_core::bytes")] - code: Vec, -} - /// Represents the different formats of the genesis state within chain spec JSON blob. #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] -enum Genesis { - /// (Deprecated) Contains the JSON representation of G (the native type representing the - /// runtime's `RuntimeGenesisConfig` struct) (will be removed with `ChainSpec::from_genesis`) - /// without the runtime code. It is required to deserialize the legacy chainspecs generated - /// with `ChainsSpec::from_genesis` method. - Runtime(G), - /// (Deprecated) Contains the JSON representation of G (the native type representing the - /// runtime's `RuntimeGenesisConfig` struct) (will be removed with `ChainSpec::from_genesis`) - /// and the runtime code. It is required to create and deserialize JSON chainspecs created with - /// deprecated `ChainSpec::from_genesis` method. - RuntimeAndCode(RuntimeInnerWrapper), +enum Genesis { /// The genesis storage as raw data. Typically raw key-value entries in state. Raw(RawGenesis), /// State root hash of the genesis storage. @@ -343,7 +302,7 @@ struct ClientSpec { pub type NoExtension = Option<()>; /// Builder for creating [`ChainSpec`] instances. -pub struct ChainSpecBuilder { +pub struct ChainSpecBuilder { code: Vec, extensions: E, name: String, @@ -355,10 +314,9 @@ pub struct ChainSpecBuilder { protocol_id: Option, fork_id: Option, properties: Option, - _genesis: PhantomData, } -impl ChainSpecBuilder { +impl ChainSpecBuilder { /// Creates a new builder instance with no defaults. pub fn new(code: &[u8], extensions: E) -> Self { Self { @@ -373,7 +331,6 @@ impl ChainSpecBuilder { protocol_id: None, fork_id: None, properties: None, - _genesis: Default::default(), } } @@ -457,7 +414,7 @@ impl ChainSpecBuilder { } /// Builds a [`ChainSpec`] instance using the provided settings. - pub fn build(self) -> ChainSpec { + pub fn build(self) -> ChainSpec { let client_spec = ClientSpec { name: self.name, id: self.id, @@ -486,13 +443,13 @@ impl ChainSpecBuilder { /// The chain spec is generic over the native `RuntimeGenesisConfig` struct (`G`). It is also /// possible to parametrize chain spec over the extended host functions (EHF). It should be use if /// runtime is using the non-standard host function during genesis state creation. -pub struct ChainSpec { +pub struct ChainSpec { client_spec: ClientSpec, - genesis: GenesisSource, + genesis: GenesisSource, _host_functions: PhantomData, } -impl Clone for ChainSpec { +impl Clone for ChainSpec { fn clone(&self) -> Self { ChainSpec { client_spec: self.client_spec.clone(), @@ -502,7 +459,7 @@ impl Clone for ChainSpec { } } -impl ChainSpec { +impl ChainSpec { /// A list of bootnode addresses. pub fn boot_nodes(&self) -> &[MultiaddrWithPeerId] { &self.client_spec.boot_nodes @@ -555,58 +512,18 @@ impl ChainSpec { &mut self.client_spec.extensions } - /// Create hardcoded spec. - #[deprecated( - note = "`from_genesis` is planned to be removed in May 2024. Use `builder()` instead." - )] - // deprecated note: Genesis::Runtime + GenesisSource::Factory shall also be removed - pub fn from_genesis G + 'static + Send + Sync>( - name: &str, - id: &str, - chain_type: ChainType, - constructor: F, - boot_nodes: Vec, - telemetry_endpoints: Option, - protocol_id: Option<&str>, - fork_id: Option<&str>, - properties: Option, - extensions: E, - code: &[u8], - ) -> Self { - let client_spec = ClientSpec { - name: name.to_owned(), - id: id.to_owned(), - chain_type, - boot_nodes, - telemetry_endpoints, - protocol_id: protocol_id.map(str::to_owned), - fork_id: fork_id.map(str::to_owned), - properties, - extensions, - consensus_engine: (), - genesis: Default::default(), - code_substitutes: BTreeMap::new(), - }; - - ChainSpec { - client_spec, - genesis: GenesisSource::Factory(Arc::new(constructor), code.into()), - _host_functions: Default::default(), - } - } - /// Type of the chain. fn chain_type(&self) -> ChainType { self.client_spec.chain_type.clone() } /// Provides a `ChainSpec` builder. - pub fn builder(code: &[u8], extensions: E) -> ChainSpecBuilder { + pub fn builder(code: &[u8], extensions: E) -> ChainSpecBuilder { ChainSpecBuilder::new(code, extensions) } } -impl ChainSpec { +impl ChainSpec { /// Parse json content into a `ChainSpec` pub fn from_json_bytes(json: impl Into>) -> Result { let json = json.into(); @@ -649,17 +566,17 @@ impl ChainS #[derive(Serialize, Deserialize)] // we cannot #[serde(deny_unknown_fields)]. Otherwise chain-spec-builder will fail on any // non-standard spec. -struct ChainSpecJsonContainer { +struct ChainSpecJsonContainer { #[serde(flatten)] client_spec: ClientSpec, - genesis: Genesis, + genesis: Genesis, } -impl ChainSpec +impl ChainSpec where EHF: HostFunctions, { - fn json_container(&self, raw: bool) -> Result, String> { + fn json_container(&self, raw: bool) -> Result, String> { let raw_genesis = match (raw, self.genesis.resolve()?) { ( true, @@ -685,20 +602,7 @@ where storage.top.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code); RawGenesis::from(storage) }, - - #[allow(deprecated)] - (true, Genesis::RuntimeAndCode(RuntimeInnerWrapper { runtime: g, code })) => { - let mut storage = g.build_storage()?; - storage.top.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code); - RawGenesis::from(storage) - }, - #[allow(deprecated)] - (true, Genesis::Runtime(g)) => { - let storage = g.build_storage()?; - RawGenesis::from(storage) - }, (true, Genesis::Raw(raw)) => raw, - (_, genesis) => return Ok(ChainSpecJsonContainer { client_spec: self.client_spec.clone(), genesis }), }; @@ -716,9 +620,8 @@ where } } -impl crate::ChainSpec for ChainSpec +impl crate::ChainSpec for ChainSpec where - G: RuntimeGenesis + 'static, E: GetExtension + serde::Serialize + Clone + Send + Sync + 'static, EHF: HostFunctions, { @@ -831,8 +734,8 @@ fn json_contains_path(doc: &json::Value, path: &mut VecDeque<&str>) -> bool { /// This function updates the code in given chain spec. /// -/// Function support updating the runtime code in provided JSON chain spec blob. `Genesis::Raw` -/// and `Genesis::RuntimeGenesis` formats are supported. +/// Function support updating the runtime code in provided JSON chain spec blob. `Genesis::Raw` +/// and `Genesis::RuntimeGenesis` formats are supported. /// /// If update was successful `true` is returned, otherwise `false`. Chain spec JSON is modified in /// place. @@ -871,19 +774,7 @@ mod tests { use sp_core::storage::well_known_keys; use sp_keyring::AccountKeyring; - #[derive(Debug, Serialize, Deserialize)] - struct Genesis(BTreeMap); - - 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; + type TestSpec = ChainSpec; #[test] fn should_deserialize_example_chain_spec() { @@ -919,7 +810,7 @@ mod tests { } } - type TestSpec2 = ChainSpec; + type TestSpec2 = ChainSpec; #[test] fn should_deserialize_chain_spec_with_extensions() { @@ -1137,10 +1028,10 @@ mod tests { #[test] fn chain_spec_as_json_fails_with_invalid_config() { - let expected_error_message = - include_str!("../res/chain_spec_as_json_fails_with_invalid_config.err"); - let j = - include_str!("../../../test-utils/runtime/res/default_genesis_config_invalid_2.json"); + let invalid_genesis_config = from_str::(include_str!( + "../../../test-utils/runtime/res/default_genesis_config_invalid_2.json" + )) + .unwrap(); let output = ChainSpec::<()>::builder( substrate_test_runtime::wasm_binary_unwrap().into(), Default::default(), @@ -1148,12 +1039,25 @@ mod tests { .with_name("TestName") .with_id("test_id") .with_chain_type(ChainType::Local) - .with_genesis_config(from_str(j).unwrap()) + .with_genesis_config(invalid_genesis_config.clone()) .build(); - let result = output.as_json(true); + let result = output.as_json(true).unwrap_err(); + let mut result = result.lines(); - assert_eq!(result.err().unwrap(), expected_error_message); + let result_header = result.next().unwrap(); + let result_body = result.collect::>().join("\n"); + let result_body: Value = serde_json::from_str(&result_body).unwrap(); + + let re = regex::Regex::new(concat!( + r"^Invalid JSON blob: unknown field `babex`, expected one of `system`, `babe`, ", + r"`substrateTest`, `balances` at line \d+ column \d+ for blob:$" + )) + .unwrap(); + + assert_eq!(json!({"a":1,"b":2}), json!({"b":2,"a":1})); + assert!(re.is_match(result_header)); + assert_eq!(invalid_genesis_config, result_body); } #[test] @@ -1278,35 +1182,4 @@ mod tests { &|v| { *v == "0x000102040506" } )); } - - #[test] - fn generate_from_genesis_is_still_supported() { - #[allow(deprecated)] - let chain_spec: ChainSpec = ChainSpec::from_genesis( - "TestName", - "test", - ChainType::Local, - || Default::default(), - Vec::new(), - None, - None, - None, - None, - Default::default(), - &vec![0, 1, 2, 4, 5, 6], - ); - - let chain_spec_json = from_str::(&chain_spec.as_json(false).unwrap()).unwrap(); - assert!(json_eval_value_at_key( - &chain_spec_json, - &mut json_path!["genesis", "runtimeAndCode", "code"], - &|v| { *v == "0x000102040506" } - )); - let chain_spec_json = from_str::(&chain_spec.as_json(true).unwrap()).unwrap(); - assert!(json_eval_value_at_key( - &chain_spec_json, - &mut json_path!["genesis", "raw", "top", "0x3a636f6465"], - &|v| { *v == "0x000102040506" } - )); - } } diff --git a/substrate/client/chain-spec/src/lib.rs b/substrate/client/chain-spec/src/lib.rs index abe01dafd92483fbede02eb6d95205b29bddacb5..066a0ab9e2afeb5b601a276b705cdff7f4699f9d 100644 --- a/substrate/client/chain-spec/src/lib.rs +++ b/substrate/client/chain-spec/src/lib.rs @@ -257,7 +257,7 @@ //! pub known_blocks: HashMap, //! } //! -//! pub type MyChainSpec = GenericChainSpec; +//! pub type MyChainSpec = GenericChainSpec; //! ``` //! Some parameters may require different values depending on the current blockchain height (a.k.a. //! forks). You can use the [`ChainSpecGroup`](macro@ChainSpecGroup) macro and the provided [`Forks`] @@ -286,10 +286,10 @@ //! pub type BlockNumber = u64; //! //! /// A chain spec supporting forkable `ClientParams`. -//! pub type MyChainSpec1 = GenericChainSpec>; +//! pub type MyChainSpec1 = GenericChainSpec>; //! //! /// A chain spec supporting forkable `Extension`. -//! pub type MyChainSpec2 = GenericChainSpec>; +//! pub type MyChainSpec2 = GenericChainSpec>; //! ``` //! It's also possible to have a set of parameters that are allowed to change with block numbers //! (i.e., they are forkable), and another set that is not subject to changes. This can also be @@ -316,7 +316,7 @@ //! pub pool: Forks, //! } //! -//! pub type MyChainSpec = GenericChainSpec; +//! pub type MyChainSpec = GenericChainSpec; //! ``` //! The chain spec can be extended with other fields that are opaque to the default chain spec. //! Specific node implementations will need to be able to deserialize these extensions. @@ -344,7 +344,6 @@ pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; use sc_network::config::MultiaddrWithPeerId; use sc_telemetry::TelemetryEndpoints; -use serde::{de::DeserializeOwned, Serialize}; use sp_core::storage::Storage; use sp_runtime::BuildStorage; @@ -373,10 +372,6 @@ impl Default for ChainType { /// Arbitrary properties defined in chain spec as a JSON object pub type Properties = serde_json::map::Map; -/// A set of traits for the runtime genesis config. -pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} -impl RuntimeGenesis for T {} - /// Common interface of a chain specification. pub trait ChainSpec: BuildStorage + Send + Sync { /// Spec name. diff --git a/substrate/client/cli/Cargo.toml b/substrate/client/cli/Cargo.toml index 805d3ee117f4ac19b636550bea6a0845978defee..1f3bce799b2c436565cf948f54d2017338344732 100644 --- a/substrate/client/cli/Cargo.toml +++ b/substrate/client/cli/Cargo.toml @@ -16,16 +16,16 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" chrono = "0.4.31" clap = { version = "4.5.3", features = ["derive", "string", "wrap_help"] } fdlimit = "0.3.0" futures = "0.3.30" -itertools = "0.10.3" +itertools = "0.11" libp2p-identity = { version = "0.1.3", features = ["ed25519", "peerid"] } log = { workspace = true, default-features = true } names = { version = "0.14.0", default-features = false } -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" rand = "0.8.5" regex = "1.6.0" rpassword = "7.0.0" diff --git a/substrate/client/cli/src/commands/insert_key.rs b/substrate/client/cli/src/commands/insert_key.rs index 3d89610b28b1bd0a031ffad6e94fef7fd604e20d..66dbec794865c00bed9e508a44e760299b2bc3ea 100644 --- a/substrate/client/cli/src/commands/insert_key.rs +++ b/substrate/client/cli/src/commands/insert_key.rs @@ -126,8 +126,10 @@ mod tests { } fn load_spec(&self, _: &str) -> std::result::Result, String> { + let builder = + GenericChainSpec::::builder(Default::default(), NoExtension::None); Ok(Box::new( - GenericChainSpec::<()>::builder(Default::default(), NoExtension::None) + builder .with_name("test") .with_id("test_id") .with_chain_type(ChainType::Development) diff --git a/substrate/client/cli/src/commands/run_cmd.rs b/substrate/client/cli/src/commands/run_cmd.rs index 221c32affd5a91d680f23ed11eb5f7a9a4051da2..c1288b502c95a4045215b66d57e18d7ade0e38ab 100644 --- a/substrate/client/cli/src/commands/run_cmd.rs +++ b/substrate/client/cli/src/commands/run_cmd.rs @@ -30,7 +30,9 @@ use crate::{ use clap::Parser; use regex::Regex; use sc_service::{ - config::{BasePath, PrometheusConfig, RpcBatchRequestConfig, TransactionPoolOptions}, + config::{ + BasePath, IpNetwork, PrometheusConfig, RpcBatchRequestConfig, TransactionPoolOptions, + }, ChainSpec, Role, }; use sc_telemetry::TelemetryEndpoints; @@ -94,6 +96,22 @@ pub struct RunCmd { #[arg(long)] pub rpc_rate_limit: Option, + /// Disable RPC rate limiting for certain ip addresses. + /// + /// Each IP address must be in CIDR notation such as `1.2.3.4/24`. + #[arg(long, num_args = 1..)] + pub rpc_rate_limit_whitelisted_ips: Vec, + + /// Trust proxy headers for disable rate limiting. + /// + /// By default the rpc server will not trust headers such `X-Real-IP`, `X-Forwarded-For` and + /// `Forwarded` and this option will make the rpc server to trust these headers. + /// + /// For instance this may be secure if the rpc server is behind a reverse proxy and that the + /// proxy always sets these headers. + #[arg(long)] + pub rpc_rate_limit_trust_proxy_headers: bool, + /// Set the maximum RPC request payload size for both HTTP and WS in megabytes. #[arg(long, default_value_t = RPC_DEFAULT_MAX_REQUEST_SIZE_MB)] pub rpc_max_request_size: u32, @@ -439,6 +457,14 @@ impl CliConfiguration for RunCmd { Ok(self.rpc_rate_limit) } + fn rpc_rate_limit_whitelisted_ips(&self) -> Result> { + Ok(self.rpc_rate_limit_whitelisted_ips.clone()) + } + + fn rpc_rate_limit_trust_proxy_headers(&self) -> Result { + Ok(self.rpc_rate_limit_trust_proxy_headers) + } + fn transaction_pool(&self, is_dev: bool) -> Result { Ok(self.pool_config.transaction_pool(is_dev)) } diff --git a/substrate/client/cli/src/config.rs b/substrate/client/cli/src/config.rs index 70a4885e5eef79780bdbec5b2cb7550b28ad866a..783c9313121fef1a199705e8a6508688e51b67ca 100644 --- a/substrate/client/cli/src/config.rs +++ b/substrate/client/cli/src/config.rs @@ -26,7 +26,7 @@ use log::warn; use names::{Generator, Name}; use sc_service::{ config::{ - BasePath, Configuration, DatabaseSource, KeystoreConfig, NetworkConfiguration, + BasePath, Configuration, DatabaseSource, IpNetwork, KeystoreConfig, NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, OutputFormat, PrometheusConfig, PruningMode, Role, RpcBatchRequestConfig, RpcMethods, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, @@ -349,6 +349,16 @@ pub trait CliConfiguration: Sized { Ok(None) } + /// RPC rate limit whitelisted ip addresses. + fn rpc_rate_limit_whitelisted_ips(&self) -> Result> { + Ok(vec![]) + } + + /// RPC rate limit trust proxy headers. + fn rpc_rate_limit_trust_proxy_headers(&self) -> Result { + Ok(false) + } + /// Get the prometheus configuration (`None` if disabled) /// /// By default this is `None`. @@ -523,6 +533,8 @@ pub trait CliConfiguration: Sized { rpc_message_buffer_capacity: self.rpc_buffer_capacity_per_connection()?, rpc_batch_config: self.rpc_batch_config()?, rpc_rate_limit: self.rpc_rate_limit()?, + rpc_rate_limit_whitelisted_ips: self.rpc_rate_limit_whitelisted_ips()?, + rpc_rate_limit_trust_proxy_headers: self.rpc_rate_limit_trust_proxy_headers()?, prometheus_config: self .prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?, telemetry_endpoints, diff --git a/substrate/client/cli/src/params/node_key_params.rs b/substrate/client/cli/src/params/node_key_params.rs index 7058af19f1d4a5edc31a8e93d062f7f93c065f1e..0e12c7a2a2d3742ef3d9aa3681f900036e67a467 100644 --- a/substrate/client/cli/src/params/node_key_params.rs +++ b/substrate/client/cli/src/params/node_key_params.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use clap::Args; -use sc_network::config::{identity::ed25519, NodeKeyConfig}; +use sc_network::config::{ed25519, NodeKeyConfig}; use sc_service::Role; use sp_core::H256; use std::{path::PathBuf, str::FromStr}; @@ -148,7 +148,7 @@ fn parse_ed25519_secret(hex: &str) -> error::Result::builder(Default::default(), NoExtension::None) - .with_name("test") - .with_id("test_id") - .with_chain_type(ChainType::Development) - .with_genesis_config_patch(Default::default()) - .build(), + GenericChainSpec::::builder( + Default::default(), + NoExtension::None, + ) + .with_name("test") + .with_id("test_id") + .with_chain_type(ChainType::Development) + .with_genesis_config_patch(Default::default()) + .build(), ), wasm_method: Default::default(), wasm_runtime_overrides: None, @@ -273,6 +276,8 @@ mod tests { rpc_port: 9944, rpc_batch_config: sc_service::config::RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/substrate/client/consensus/aura/Cargo.toml b/substrate/client/consensus/aura/Cargo.toml index 64e2d16cd913aaea5d2688087e90088e5ff46ab8..d1460c45356d7ec86204b52c42c08ee28e9c5faf 100644 --- a/substrate/client/consensus/aura/Cargo.toml +++ b/substrate/client/consensus/aura/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" log = { workspace = true, default-features = true } thiserror = { workspace = true } diff --git a/substrate/client/consensus/babe/Cargo.toml b/substrate/client/consensus/babe/Cargo.toml index b001e3d117aa94c86e76484336b434f840ec3e69..c51082a018b5cfd558efe0b76985d6add890057d 100644 --- a/substrate/client/consensus/babe/Cargo.toml +++ b/substrate/client/consensus/babe/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" log = { workspace = true, default-features = true } num-bigint = "0.4.3" diff --git a/substrate/client/consensus/babe/README.md b/substrate/client/consensus/babe/README.md index a3cf944b513b80eb96493342b821147bfc905592..47b5820ff71aab8a4a6c92640ebd8981c396fa09 100644 --- a/substrate/client/consensus/babe/README.md +++ b/substrate/client/consensus/babe/README.md @@ -43,6 +43,6 @@ 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: - + License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/consensus/babe/rpc/Cargo.toml b/substrate/client/consensus/babe/rpc/Cargo.toml index b2661bbde27e4a9d72d0140e241c1da1bcc0f2b2..4c755df541d70315dea241092145e17c2bd28800 100644 --- a/substrate/client/consensus/babe/rpc/Cargo.toml +++ b/substrate/client/consensus/babe/rpc/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } futures = "0.3.30" serde = { features = ["derive"], workspace = true, default-features = true } thiserror = { workspace = true } diff --git a/substrate/client/consensus/babe/src/lib.rs b/substrate/client/consensus/babe/src/lib.rs index d10bdd8c7e4c4d108b78ef3286f475ba85e16a8a..0c85de24004031fce96be35bc413506069093eb1 100644 --- a/substrate/client/consensus/babe/src/lib.rs +++ b/substrate/client/consensus/babe/src/lib.rs @@ -61,7 +61,7 @@ //! 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)] @@ -562,9 +562,10 @@ fn aux_storage_cleanup + HeaderBackend, Block: B // Cleans data for stale forks. let stale_forks = match client.expand_forks(¬ification.stale_heads) { Ok(stale_forks) => stale_forks, - Err((stale_forks, e)) => { + Err(e) => { warn!(target: LOG_TARGET, "{:?}", e); - stale_forks + + Default::default() }, }; hashes.extend(stale_forks.iter()); diff --git a/substrate/client/consensus/babe/src/tests.rs b/substrate/client/consensus/babe/src/tests.rs index 38c9e1ff6ac25cc26151c668902838ec65ab6189..716067ae4000661beab6aeb90772087720d0a5ae 100644 --- a/substrate/client/consensus/babe/src/tests.rs +++ b/substrate/client/consensus/babe/src/tests.rs @@ -1094,8 +1094,8 @@ async fn obsolete_blocks_aux_data_cleanup() { assert!(aux_data_check(&fork1_hashes[2..3], false)); // Present: A4 assert!(aux_data_check(&fork1_hashes[3..], true)); - // Present C4, C5 - assert!(aux_data_check(&fork3_hashes, true)); + // Wiped C4, C5 + assert!(aux_data_check(&fork3_hashes, false)); } #[tokio::test] diff --git a/substrate/client/consensus/beefy/Cargo.toml b/substrate/client/consensus/beefy/Cargo.toml index 435604a9473b299bbf59caba7a3a3c9716b5bffc..193acbe52a1e8b3bc7752b984296bb9c1456d483 100644 --- a/substrate/client/consensus/beefy/Cargo.toml +++ b/substrate/client/consensus/beefy/Cargo.toml @@ -12,10 +12,10 @@ homepage = "https://substrate.io" workspace = true [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" async-channel = "1.8.0" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } fnv = "1.0.6" futures = "0.3.30" log = { workspace = true, default-features = true } diff --git a/substrate/client/consensus/beefy/rpc/Cargo.toml b/substrate/client/consensus/beefy/rpc/Cargo.toml index e46fc4f4410a461f73f5e5fe791bd9b08fd98a99..07e46dbda156a79a77a60e8340e46a323e133fd2 100644 --- a/substrate/client/consensus/beefy/rpc/Cargo.toml +++ b/substrate/client/consensus/beefy/rpc/Cargo.toml @@ -12,9 +12,9 @@ homepage = "https://substrate.io" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } log = { workspace = true, default-features = true } parking_lot = "0.12.1" serde = { features = ["derive"], workspace = true, default-features = true } diff --git a/substrate/client/consensus/epochs/Cargo.toml b/substrate/client/consensus/epochs/Cargo.toml index ff6bf86a6a441d49a8950c38d2333bd0e067724d..e409e171e477c2452903a09ee78916808a210011 100644 --- a/substrate/client/consensus/epochs/Cargo.toml +++ b/substrate/client/consensus/epochs/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } fork-tree = { path = "../../../utils/fork-tree" } sc-client-api = { path = "../../api" } sc-consensus = { path = "../common" } diff --git a/substrate/client/consensus/grandpa/Cargo.toml b/substrate/client/consensus/grandpa/Cargo.toml index e59c17b0680374d7195e823514d02f807f6f3cbf..9099761fbceb4a30624eef4f636982f3e3b9921b 100644 --- a/substrate/client/consensus/grandpa/Cargo.toml +++ b/substrate/client/consensus/grandpa/Cargo.toml @@ -18,14 +18,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ahash = "0.8.2" -array-bytes = "6.1" +array-bytes = "6.2.2" async-trait = "0.1.79" dyn-clone = "1.0" finality-grandpa = { version = "0.16.2", features = ["derive-codec"] } futures = "0.3.30" futures-timer = "3.0.1" log = { workspace = true, default-features = true } -parity-scale-codec = { version = "3.6.1", features = ["derive"] } +parity-scale-codec = { version = "3.6.12", features = ["derive"] } parking_lot = "0.12.1" rand = "0.8.5" serde_json = { workspace = true, default-features = true } diff --git a/substrate/client/consensus/grandpa/rpc/Cargo.toml b/substrate/client/consensus/grandpa/rpc/Cargo.toml index 0789a429ac416de70201e30e909d4f3dec7e4a66..d4e72baef3e7df47baf948cba59e35b2687c76e1 100644 --- a/substrate/client/consensus/grandpa/rpc/Cargo.toml +++ b/substrate/client/consensus/grandpa/rpc/Cargo.toml @@ -15,9 +15,9 @@ workspace = true [dependencies] finality-grandpa = { version = "0.16.2", features = ["derive-codec"] } futures = "0.3.30" -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } log = { workspace = true, default-features = true } -parity-scale-codec = { version = "3.6.1", features = ["derive"] } +parity-scale-codec = { version = "3.6.12", features = ["derive"] } serde = { features = ["derive"], workspace = true, default-features = true } thiserror = { workspace = true } sc-client-api = { path = "../../../api" } diff --git a/substrate/client/consensus/grandpa/src/communication/tests.rs b/substrate/client/consensus/grandpa/src/communication/tests.rs index bc3023fc0281d150864cb3bb21214c3648a73c42..d7153a79ce0b991887b302265508d35de418f0a6 100644 --- a/substrate/client/consensus/grandpa/src/communication/tests.rs +++ b/substrate/client/consensus/grandpa/src/communication/tests.rs @@ -706,25 +706,12 @@ fn peer_with_higher_view_leads_to_catch_up_request() { } fn local_chain_spec() -> Box { - use sc_chain_spec::{ChainSpec, GenericChainSpec}; - use serde::{Deserialize, Serialize}; - use sp_runtime::{BuildStorage, Storage}; - - #[derive(Debug, Serialize, Deserialize)] - struct Genesis(std::collections::BTreeMap); - 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(()) - } - } - let chain_spec = GenericChainSpec::::from_json_bytes( - &include_bytes!("../../../../chain-spec/res/chain_spec.json")[..], - ) - .unwrap(); - chain_spec.cloned_box() + let chain_spec = + sc_chain_spec::GenericChainSpec::::from_json_bytes( + &include_bytes!("../../../../chain-spec/res/chain_spec.json")[..], + ) + .unwrap(); + sc_chain_spec::ChainSpec::cloned_box(&chain_spec) } #[test] diff --git a/substrate/client/consensus/manual-seal/Cargo.toml b/substrate/client/consensus/manual-seal/Cargo.toml index 1422d46105b22bd093de3260e3e13219aa2731a9..33f5bf1f8c1501e0e366edab6c3606716aeb47ab 100644 --- a/substrate/client/consensus/manual-seal/Cargo.toml +++ b/substrate/client/consensus/manual-seal/Cargo.toml @@ -16,10 +16,10 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } assert_matches = "1.3.0" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" futures-timer = "3.0.1" log = { workspace = true, default-features = true } diff --git a/substrate/client/consensus/pow/Cargo.toml b/substrate/client/consensus/pow/Cargo.toml index ecfa29aa194d424d35eba858a0b829fb58a610e3..51a2be1b6cf5d4be2d5a5c3af6b0e6ea2bc25406 100644 --- a/substrate/client/consensus/pow/Cargo.toml +++ b/substrate/client/consensus/pow/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" futures-timer = "3.0.1" log = { workspace = true, default-features = true } diff --git a/substrate/client/consensus/slots/Cargo.toml b/substrate/client/consensus/slots/Cargo.toml index 4ac6ce90713798d2cce4172f3544c6a116736a84..8e88ee68d7d739a888f3b0e32b7a8fee3ac1e41c 100644 --- a/substrate/client/consensus/slots/Cargo.toml +++ b/substrate/client/consensus/slots/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" futures-timer = "3.0.1" log = { workspace = true, default-features = true } diff --git a/substrate/client/db/Cargo.toml b/substrate/client/db/Cargo.toml index 57ee1a8ad3315036f44e5b560fb55fa3f31c97e5..b10c42d50f0bcbf9aed764a2df85cffe7c6baf66 100644 --- a/substrate/client/db/Cargo.toml +++ b/substrate/client/db/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", features = [ "derive", ] } hash-db = "0.16.0" @@ -39,7 +39,7 @@ sp-state-machine = { path = "../../primitives/state-machine" } sp-trie = { path = "../../primitives/trie" } [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" kvdb-rocksdb = "0.19.0" rand = "0.8.5" tempfile = "3.1.0" @@ -47,7 +47,7 @@ quickcheck = { version = "1.0.3", default-features = false } kitchensink-runtime = { path = "../../bin/node/runtime" } sp-tracing = { path = "../../primitives/tracing" } substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } -array-bytes = "6.1" +array-bytes = "6.2.2" [features] default = [] diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index 0faa90dfc4f925db8776c6914fcf864813b790a5..36f9aea817c9c7031ae69a588a9385e88e786b0c 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -68,8 +68,8 @@ use sc_client_api::{ use sc_state_db::{IsPruned, LastCanonicalized, StateDb}; use sp_arithmetic::traits::Saturating; use sp_blockchain::{ - Backend as _, CachedHeaderMetadata, Error as ClientError, HeaderBackend, HeaderMetadata, - HeaderMetadataCache, Result as ClientResult, + Backend as _, CachedHeaderMetadata, DisplacedLeavesAfterFinalization, Error as ClientError, + HeaderBackend, HeaderMetadata, HeaderMetadataCache, Result as ClientResult, }; use sp_core::{ offchain::OffchainOverlayedChange, @@ -747,19 +747,6 @@ impl sc_client_api::blockchain::Backend for BlockchainDb, - ) -> ClientResult> { - Ok(self - .leaves - .read() - .displaced_by_finalize_height(block_number) - .leaves() - .cloned() - .collect::>()) - } - fn children(&self, parent_hash: Block::Hash) -> ClientResult> { children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash) } @@ -1813,14 +1800,13 @@ impl Backend { apply_state_commit(transaction, commit); } - let new_displaced = self.blockchain.leaves.write().finalize_height(f_num); - self.prune_blocks( - transaction, - f_num, - f_hash, - &new_displaced, - current_transaction_justifications, - )?; + let new_displaced = self.blockchain.displaced_leaves_after_finalizing(f_hash, f_num)?; + let finalization_outcome = + FinalizationOutcome::new(new_displaced.displaced_leaves.clone().into_iter()); + + self.blockchain.leaves.write().remove_displaced_leaves(&finalization_outcome); + + self.prune_blocks(transaction, f_num, &new_displaced, current_transaction_justifications)?; Ok(()) } @@ -1829,8 +1815,7 @@ impl Backend { &self, transaction: &mut Transaction, finalized_number: NumberFor, - finalized_hash: Block::Hash, - displaced: &FinalizationOutcome>, + displaced: &DisplacedLeavesAfterFinalization, current_transaction_justifications: &mut HashMap, ) -> ClientResult<()> { match self.blocks_pruning { @@ -1858,10 +1843,10 @@ impl Backend { self.prune_block(transaction, BlockId::::number(number))?; } - self.prune_displaced_branches(transaction, finalized_hash, displaced)?; + self.prune_displaced_branches(transaction, displaced)?; }, BlocksPruning::KeepFinalized => { - self.prune_displaced_branches(transaction, finalized_hash, displaced)?; + self.prune_displaced_branches(transaction, displaced)?; }, } Ok(()) @@ -1870,21 +1855,13 @@ impl Backend { fn prune_displaced_branches( &self, transaction: &mut Transaction, - finalized: Block::Hash, - displaced: &FinalizationOutcome>, + displaced: &DisplacedLeavesAfterFinalization, ) -> ClientResult<()> { // Discard all blocks from displaced branches - for h in displaced.leaves() { - match sp_blockchain::tree_route(&self.blockchain, *h, finalized) { - Ok(tree_route) => - for r in tree_route.retracted() { - self.blockchain.insert_persisted_body_if_pinned(r.hash)?; - self.prune_block(transaction, BlockId::::hash(r.hash))?; - }, - Err(sp_blockchain::Error::UnknownBlock(_)) => { - // Sometimes routes can't be calculated. E.g. after warp sync. - }, - Err(e) => Err(e)?, + for (_, tree_route) in displaced.tree_routes.iter() { + for r in tree_route.retracted() { + self.blockchain.insert_persisted_body_if_pinned(r.hash)?; + self.prune_block(transaction, BlockId::::hash(r.hash))?; } } Ok(()) @@ -3190,6 +3167,9 @@ pub(crate) mod tests { #[test] fn test_leaves_pruned_on_finality() { + // / 1b - 2b - 3b + // 0 - 1a - 2a + // \ 1c let backend: Backend = Backend::new_test(10, 10); let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); @@ -3201,18 +3181,16 @@ pub(crate) mod tests { let block2_a = insert_header(&backend, 2, block1_a, None, Default::default()); let block2_b = insert_header(&backend, 2, block1_b, None, Default::default()); - let block2_c = insert_header(&backend, 2, block1_b, None, [1; 32].into()); - assert_eq!( - backend.blockchain().leaves().unwrap(), - vec![block2_a, block2_b, block2_c, block1_c] - ); + let block3_b = insert_header(&backend, 3, block2_b, None, [3; 32].into()); + + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block3_b, block2_a, block1_c]); backend.finalize_block(block1_a, None).unwrap(); backend.finalize_block(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]); + // All leaves are pruned that are known to not belong to canonical branch + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block2_a]); } #[test] diff --git a/substrate/client/executor/Cargo.toml b/substrate/client/executor/Cargo.toml index efe8cc3069ca8be4d797196cbbf6256d248d76a0..1f54b82030ff226b179afe8f167e134417b859e9 100644 --- a/substrate/client/executor/Cargo.toml +++ b/substrate/client/executor/Cargo.toml @@ -21,7 +21,7 @@ parking_lot = "0.12.1" schnellru = "0.2.1" tracing = "0.1.29" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } sc-executor-common = { path = "common" } sc-executor-polkavm = { path = "polkavm" } sc-executor-wasmtime = { path = "wasmtime" } @@ -36,7 +36,7 @@ sp-version = { path = "../../primitives/version" } sp-wasm-interface = { path = "../../primitives/wasm-interface" } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" assert_matches = "1.3.0" wat = "1.0" sc-runtime-test = { path = "runtime-test" } @@ -50,7 +50,7 @@ sp-tracing = { path = "../../primitives/tracing" } tracing-subscriber = { workspace = true } paste = "1.0" regex = "1.6.0" -criterion = "0.4.0" +criterion = "0.5.1" env_logger = "0.11" num_cpus = "1.13.1" tempfile = "3.3.0" diff --git a/substrate/client/executor/src/executor.rs b/substrate/client/executor/src/executor.rs index d56a3b389ef42868d0543303c5fbd63ea8d2d884..913bcdfcfe591d9f7c8a0b78198102bd5441750e 100644 --- a/substrate/client/executor/src/executor.rs +++ b/substrate/client/executor/src/executor.rs @@ -83,7 +83,7 @@ fn unwrap_heap_pages(pages: Option) -> HeapAllocStrategy { } /// Builder for creating a [`WasmExecutor`] instance. -pub struct WasmExecutorBuilder { +pub struct WasmExecutorBuilder { _phantom: PhantomData, method: WasmExecutionMethod, onchain_heap_alloc_strategy: Option, @@ -218,7 +218,7 @@ impl WasmExecutorBuilder { /// An abstraction over Wasm code executor. Supports selecting execution backend and /// manages runtime cache. -pub struct WasmExecutor { +pub struct WasmExecutor { /// Method used to execute fallback Wasm code. method: WasmExecutionMethod, /// The heap allocation strategy for onchain Wasm calls. @@ -252,10 +252,13 @@ impl Clone for WasmExecutor { } } -impl WasmExecutor -where - H: HostFunctions, -{ +impl Default for WasmExecutor { + fn default() -> Self { + WasmExecutorBuilder::new().build() + } +} + +impl WasmExecutor { /// Create new instance. /// /// # Parameters @@ -312,7 +315,12 @@ where pub fn allow_missing_host_functions(&mut self, allow_missing_host_functions: bool) { self.allow_missing_host_functions = allow_missing_host_functions } +} +impl WasmExecutor +where + H: HostFunctions, +{ /// Execute the given closure `f` with the latest runtime (based on `runtime_code`). /// /// The closure `f` is expected to return `Err(_)` when there happened a `panic!` in native code @@ -558,6 +566,9 @@ where /// 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. +#[deprecated( + note = "Native execution will be deprecated, please replace with `WasmExecutor`. Will be removed at end of 2024." +)] pub struct NativeElseWasmExecutor { /// Native runtime version info. native_version: NativeVersion, @@ -568,6 +579,7 @@ pub struct NativeElseWasmExecutor { use_native: bool, } +#[allow(deprecated)] impl NativeElseWasmExecutor { /// /// Create new instance. @@ -628,6 +640,7 @@ impl NativeElseWasmExecutor { } } +#[allow(deprecated)] impl RuntimeVersionOf for NativeElseWasmExecutor { fn runtime_version( &self, @@ -638,12 +651,14 @@ impl RuntimeVersionOf for NativeElseWasmExecutor } } +#[allow(deprecated)] impl GetNativeVersion for NativeElseWasmExecutor { fn native_version(&self) -> &NativeVersion { &self.native_version } } +#[allow(deprecated)] impl CodeExecutor for NativeElseWasmExecutor { type Error = Error; @@ -718,6 +733,7 @@ impl CodeExecutor for NativeElseWasmExecut } } +#[allow(deprecated)] impl Clone for NativeElseWasmExecutor { fn clone(&self) -> Self { NativeElseWasmExecutor { @@ -728,6 +744,7 @@ impl Clone for NativeElseWasmExecutor { } } +#[allow(deprecated)] impl sp_core::traits::ReadRuntimeVersion for NativeElseWasmExecutor { fn read_runtime_version( &self, @@ -765,6 +782,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn native_executor_registers_custom_interface() { let executor = NativeElseWasmExecutor::::new_with_wasm_executor( WasmExecutor::builder().build(), diff --git a/substrate/client/executor/src/lib.rs b/substrate/client/executor/src/lib.rs index 6b99f0a6ee03b303d2d97ce05040828e3248312b..204f1ff22d74dc96bedb52711308010d59351a27 100644 --- a/substrate/client/executor/src/lib.rs +++ b/substrate/client/executor/src/lib.rs @@ -36,18 +36,17 @@ mod executor; mod integration_tests; mod wasm_runtime; -pub use self::{ - executor::{ - with_externalities_safe, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, - }, - wasm_runtime::{read_embedded_version, WasmExecutionMethod}, -}; pub use codec::Codec; +#[allow(deprecated)] +pub use executor::NativeElseWasmExecutor; +pub use executor::{with_externalities_safe, NativeExecutionDispatch, WasmExecutor}; #[doc(hidden)] pub use sp_core::traits::Externalities; pub use sp_version::{NativeVersion, RuntimeVersion}; #[doc(hidden)] pub use sp_wasm_interface; +pub use sp_wasm_interface::HostFunctions; +pub use wasm_runtime::{read_embedded_version, WasmExecutionMethod}; pub use sc_executor_common::{ error, diff --git a/substrate/client/executor/wasmtime/Cargo.toml b/substrate/client/executor/wasmtime/Cargo.toml index f3fef4046914128dff2ad0904d445e89cba11c6a..d3d670650db789b2b9b854a5fda8724a506833ee 100644 --- a/substrate/client/executor/wasmtime/Cargo.toml +++ b/substrate/client/executor/wasmtime/Cargo.toml @@ -50,5 +50,5 @@ sc-runtime-test = { path = "../runtime-test" } sp-io = { path = "../../../primitives/io" } tempfile = "3.3.0" paste = "1.0" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } cargo_metadata = "0.15.4" diff --git a/substrate/client/executor/wasmtime/src/lib.rs b/substrate/client/executor/wasmtime/src/lib.rs index 82e62b4a5dd3cd6d7b009e019f0c24c28551743a..8e8e92017df91260d7d79f8f237200c1ef9936c0 100644 --- a/substrate/client/executor/wasmtime/src/lib.rs +++ b/substrate/client/executor/wasmtime/src/lib.rs @@ -41,3 +41,7 @@ pub use runtime::{ prepare_runtime_artifact, Config, DeterministicStackLimit, InstantiationStrategy, Semantics, WasmtimeRuntime, }; +pub use sc_executor_common::{ + runtime_blob::RuntimeBlob, + wasm_runtime::{HeapAllocStrategy, WasmModule}, +}; diff --git a/substrate/client/keystore/Cargo.toml b/substrate/client/keystore/Cargo.toml index 908e0aa8f38ced48facaf99d05c0d7771f03fa26..443ce3507542c155119f2d424d18e9268b4d391b 100644 --- a/substrate/client/keystore/Cargo.toml +++ b/substrate/client/keystore/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" parking_lot = "0.12.1" serde_json = { workspace = true, default-features = true } thiserror = { workspace = true } diff --git a/substrate/client/merkle-mountain-range/Cargo.toml b/substrate/client/merkle-mountain-range/Cargo.toml index 46b7a1011c465f1aced062ba6978580a5f85c43c..3cf3cdd15dad9bb30fe2a9a70b6adc9f4541e56e 100644 --- a/substrate/client/merkle-mountain-range/Cargo.toml +++ b/substrate/client/merkle-mountain-range/Cargo.toml @@ -14,7 +14,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" log = { workspace = true, default-features = true } sp-api = { path = "../../primitives/api" } diff --git a/substrate/client/merkle-mountain-range/rpc/Cargo.toml b/substrate/client/merkle-mountain-range/rpc/Cargo.toml index 9b391b76ea00b5e48700b7213afb691c149167ab..25e6e316a8be0ab6ec0ff70f38a05f603ebf8404 100644 --- a/substrate/client/merkle-mountain-range/rpc/Cargo.toml +++ b/substrate/client/merkle-mountain-range/rpc/Cargo.toml @@ -15,8 +15,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +codec = { package = "parity-scale-codec", version = "3.6.12" } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } serde = { features = ["derive"], workspace = true, default-features = true } sp-api = { path = "../../../primitives/api" } sp-blockchain = { path = "../../../primitives/blockchain" } diff --git a/substrate/client/merkle-mountain-range/rpc/src/lib.rs b/substrate/client/merkle-mountain-range/rpc/src/lib.rs index b4da9848de54cbc10ee549c3bd8cf1b033559722..41e73a5b8d75d6940c669786533e423fcc81b5ac 100644 --- a/substrate/client/merkle-mountain-range/rpc/src/lib.rs +++ b/substrate/client/merkle-mountain-range/rpc/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::{ offchain::{storage::OffchainDb, OffchainDbExt, OffchainStorage}, Bytes, }; -use sp_mmr_primitives::{Error as MmrError, Proof}; +use sp_mmr_primitives::{Error as MmrError, LeafProof}; use sp_runtime::traits::{Block as BlockT, NumberFor}; pub use sp_mmr_primitives::MmrApi as MmrRuntimeApi; @@ -52,17 +52,17 @@ pub struct LeavesProof { pub block_hash: BlockHash, /// SCALE-encoded vector of `LeafData`. pub leaves: Bytes, - /// SCALE-encoded proof data. See [sp_mmr_primitives::Proof]. + /// SCALE-encoded proof data. See [sp_mmr_primitives::LeafProof]. pub proof: Bytes, } impl LeavesProof { /// Create new `LeavesProof` from a given vector of `Leaf` and a - /// [sp_mmr_primitives::Proof]. + /// [sp_mmr_primitives::LeafProof]. pub fn new( block_hash: BlockHash, leaves: Vec, - proof: Proof, + proof: LeafProof, ) -> Self where Leaf: Encode, @@ -258,7 +258,7 @@ mod tests { fn should_serialize_leaf_proof() { // given let leaf = vec![1_u8, 2, 3, 4]; - let proof = Proof { + let proof = LeafProof { leaf_indices: vec![1], leaf_count: 9, items: vec![H256::repeat_byte(1), H256::repeat_byte(2)], @@ -281,7 +281,7 @@ mod tests { // given let leaf_a = vec![1_u8, 2, 3, 4]; let leaf_b = vec![2_u8, 2, 3, 4]; - let proof = Proof { + let proof = LeafProof { leaf_indices: vec![1, 2], leaf_count: 9, items: vec![H256::repeat_byte(1), H256::repeat_byte(2)], @@ -306,7 +306,7 @@ mod tests { block_hash: H256::repeat_byte(0), leaves: Bytes(vec![vec![1_u8, 2, 3, 4]].encode()), proof: Bytes( - Proof { + LeafProof { leaf_indices: vec![1], leaf_count: 9, items: vec![H256::repeat_byte(1), H256::repeat_byte(2)], @@ -333,7 +333,7 @@ mod tests { block_hash: H256::repeat_byte(0), leaves: Bytes(vec![vec![1_u8, 2, 3, 4], vec![2_u8, 2, 3, 4]].encode()), proof: Bytes( - Proof { + LeafProof { leaf_indices: vec![1, 2], leaf_count: 9, items: vec![H256::repeat_byte(1), H256::repeat_byte(2)], diff --git a/substrate/client/merkle-mountain-range/src/offchain_mmr.rs b/substrate/client/merkle-mountain-range/src/offchain_mmr.rs index 3c3f0beb6c6a9196bfb8bf6d1108b737869d346c..94593f9c2c7ba265fe2ec1b0b50a6e1b962788a7 100644 --- a/substrate/client/merkle-mountain-range/src/offchain_mmr.rs +++ b/substrate/client/merkle-mountain-range/src/offchain_mmr.rs @@ -33,7 +33,7 @@ use sp_runtime::{ traits::{Block, Header, NumberFor, One}, Saturating, }; -use std::{collections::VecDeque, sync::Arc}; +use std::{collections::VecDeque, default::Default, sync::Arc}; /// `OffchainMMR` exposes MMR offchain canonicalization and pruning logic. pub struct OffchainMmr, C> { @@ -273,12 +273,11 @@ where self.write_gadget_state_or_log(); // Remove offchain MMR nodes for stale forks. - let stale_forks = self.client.expand_forks(¬ification.stale_heads).unwrap_or_else( - |(stale_forks, e)| { - warn!(target: LOG_TARGET, "{:?}", e); - stale_forks - }, - ); + let stale_forks = self.client.expand_forks(¬ification.stale_heads).unwrap_or_else(|e| { + warn!(target: LOG_TARGET, "{:?}", e); + + Default::default() + }); for hash in stale_forks.iter() { self.prune_branch(hash); } diff --git a/substrate/client/merkle-mountain-range/src/test_utils.rs b/substrate/client/merkle-mountain-range/src/test_utils.rs index 5775b4cfe67cd49878508521ec72ba9af413a187..fcf9fa25b593c86eb780d8b563e6ecc55ecb50a7 100644 --- a/substrate/client/merkle-mountain-range/src/test_utils.rs +++ b/substrate/client/merkle-mountain-range/src/test_utils.rs @@ -309,11 +309,11 @@ sp_api::mock_impl_runtime_apis! { &self, _block_numbers: Vec, _best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { + ) -> Result<(Vec, mmr::LeafProof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_proof(_leaves: Vec, _proof: mmr::Proof) + fn verify_proof(_leaves: Vec, _proof: mmr::LeafProof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) @@ -322,7 +322,7 @@ sp_api::mock_impl_runtime_apis! { fn verify_proof_stateless( _root: MmrHash, _leaves: Vec, - _proof: mmr::Proof + _proof: mmr::LeafProof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } diff --git a/substrate/client/mixnet/Cargo.toml b/substrate/client/mixnet/Cargo.toml index e605a06c9d9c7e886a9bb388bd9ab70254d193f5..1626305639498855148b515e666e1e91a603643f 100644 --- a/substrate/client/mixnet/Cargo.toml +++ b/substrate/client/mixnet/Cargo.toml @@ -16,11 +16,11 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "4.1" +array-bytes = "6.2.2" arrayvec = "0.7.2" blake2 = "0.10.4" bytes = "1" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } futures = "0.3.30" futures-timer = "3.0.2" log = { workspace = true, default-features = true } diff --git a/substrate/client/mixnet/src/sync_with_runtime.rs b/substrate/client/mixnet/src/sync_with_runtime.rs index 46c2334ceb46d8ef7966b666e480e83075a51703..0071ce13b33a3ff015569ce66530215f1d9ac5b6 100644 --- a/substrate/client/mixnet/src/sync_with_runtime.rs +++ b/substrate/client/mixnet/src/sync_with_runtime.rs @@ -25,8 +25,10 @@ use mixnet::core::{ Mixnet, Mixnode as CoreMixnode, MixnodesErr as CoreMixnodesErr, RelSessionIndex, SessionPhase as CoreSessionPhase, SessionStatus as CoreSessionStatus, }; -use multiaddr::{multiaddr, Multiaddr, Protocol}; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{multiaddr, Multiaddr, Protocol}, + PeerId, +}; use sp_api::{ApiError, ApiRef}; use sp_mixnet::{ runtime_api::MixnetApi, @@ -196,7 +198,6 @@ where #[cfg(test)] mod tests { use super::*; - use multiaddr::multiaddr; #[test] fn fixup_empty_external_addresses() { diff --git a/substrate/client/network-gossip/Cargo.toml b/substrate/client/network-gossip/Cargo.toml index ad81381edea1800035a96b608681c5f3691d2d05..3eeea6651186162ed2f28bdf12ec08ad184df906 100644 --- a/substrate/client/network-gossip/Cargo.toml +++ b/substrate/client/network-gossip/Cargo.toml @@ -34,6 +34,6 @@ sp-runtime = { path = "../../primitives/runtime" } [dev-dependencies] tokio = "1.37" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } quickcheck = { version = "1.0.3", default-features = false } substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } diff --git a/substrate/client/network/Cargo.toml b/substrate/client/network/Cargo.toml index 0879481a419930fae590e3ac68cde17f1ceb2207..29b14a4511cac655096b3e3dded5013462ae7e9e 100644 --- a/substrate/client/network/Cargo.toml +++ b/substrate/client/network/Cargo.toml @@ -17,16 +17,16 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.11" +prost-build = "0.12.4" [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" async-channel = "1.8.0" async-trait = "0.1.79" asynchronous-codec = "0.6" bytes = "1" cid = "0.9.0" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } either = "1.5.3" fnv = "1.0.6" futures = "0.3.30" @@ -49,7 +49,7 @@ tokio-stream = "0.1.7" unsigned-varint = { version = "0.7.2", features = ["asynchronous_codec", "futures"] } zeroize = "1.4.3" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } -prost = "0.11" +prost = "0.12.4" sc-client-api = { path = "../api" } sc-network-common = { path = "common" } sc-network-types = { path = "types" } @@ -59,7 +59,7 @@ sp-blockchain = { path = "../../primitives/blockchain" } sp-core = { path = "../../primitives/core" } sp-runtime = { path = "../../primitives/runtime" } wasm-timer = "0.2" -litep2p = { git = "https://github.com/paritytech/litep2p", branch = "master" } +litep2p = "0.5.0" once_cell = "1.18.0" void = "1.0.2" schnellru = "0.2.1" diff --git a/substrate/client/network/common/Cargo.toml b/substrate/client/network/common/Cargo.toml index 4478693456f7e32bcab4cf6ce8a94a48a5e7c727..9a1bf5b88ea1a97cf6bdfe358a44338561500b50 100644 --- a/substrate/client/network/common/Cargo.toml +++ b/substrate/client/network/common/Cargo.toml @@ -16,12 +16,12 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.11" +prost-build = "0.12.4" [dependencies] async-trait = "0.1.79" bitflags = "1.3.2" -codec = { package = "parity-scale-codec", version = "3.6.1", features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", features = [ "derive", ] } futures = "0.3.30" diff --git a/substrate/client/network/light/Cargo.toml b/substrate/client/network/light/Cargo.toml index d75a2a908da54ceb7c27a3ba79e4ac6c0d2ba071..baaed578b884172bdcfba5eb2a66e48ac32c56a5 100644 --- a/substrate/client/network/light/Cargo.toml +++ b/substrate/client/network/light/Cargo.toml @@ -16,17 +16,17 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.11" +prost-build = "0.12.4" [dependencies] async-channel = "1.8.0" -array-bytes = "6.1" -codec = { package = "parity-scale-codec", version = "3.6.1", features = [ +array-bytes = "6.2.2" +codec = { package = "parity-scale-codec", version = "3.6.12", features = [ "derive", ] } futures = "0.3.30" log = { workspace = true, default-features = true } -prost = "0.12" +prost = "0.12.4" sp-blockchain = { path = "../../../primitives/blockchain" } sc-client-api = { path = "../../api" } sc-network-types = { path = "../types" } diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index e6cc9de56942700940da2644b2c5b57c0abd144d..100a1e9dfb38ea23d4bb7d846aed0295f1cdaaea 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -35,12 +35,11 @@ pub use crate::{ types::ProtocolName, }; -pub use libp2p::{ - build_multiaddr, - identity::{self, ed25519, Keypair}, - multiaddr, Multiaddr, +pub use sc_network_types::{build_multiaddr, ed25519}; +use sc_network_types::{ + multiaddr::{self, Multiaddr}, + PeerId, }; -use sc_network_types::PeerId; use crate::service::{ensure_addresses_consistent_with_transport, traits::NetworkBackend}; use codec::Encode; @@ -100,7 +99,7 @@ impl fmt::Debug for ProtocolId { /// # Example /// /// ``` -/// # use libp2p::{Multiaddr, PeerId}; +/// # use sc_network_types::{multiaddr::Multiaddr, PeerId}; /// use sc_network::config::parse_str_addr; /// let (peer_id, addr) = parse_str_addr( /// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV" @@ -131,7 +130,7 @@ pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> /// # Example /// /// ``` -/// # use libp2p::{Multiaddr, PeerId}; +/// # use sc_network_types::{multiaddr::Multiaddr, PeerId}; /// use sc_network::config::MultiaddrWithPeerId; /// let addr: MultiaddrWithPeerId = /// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".parse().unwrap(); @@ -187,7 +186,7 @@ impl TryFrom for MultiaddrWithPeerId { #[derive(Debug)] pub enum ParseErr { /// Error while parsing the multiaddress. - MultiaddrParse(multiaddr::Error), + MultiaddrParse(multiaddr::ParseError), /// Multihash of the peer ID is invalid. InvalidPeerId, /// The peer ID is missing from the address. @@ -214,8 +213,8 @@ impl std::error::Error for ParseErr { } } -impl From for ParseErr { - fn from(err: multiaddr::Error) -> ParseErr { +impl From for ParseErr { + fn from(err: multiaddr::ParseError) -> ParseErr { Self::MultiaddrParse(err) } } @@ -343,10 +342,10 @@ impl NodeKeyConfig { /// /// * If the secret is configured to be new, it is generated and the corresponding keypair is /// returned. - pub fn into_keypair(self) -> io::Result { + pub fn into_keypair(self) -> io::Result { use NodeKeyConfig::*; match self { - Ed25519(Secret::New) => Ok(Keypair::generate_ed25519()), + Ed25519(Secret::New) => Ok(ed25519::Keypair::generate()), Ed25519(Secret::Input(k)) => Ok(ed25519::Keypair::from(k).into()), @@ -365,8 +364,7 @@ impl NodeKeyConfig { ed25519::SecretKey::generate, |b| b.as_ref().to_vec(), ) - .map(ed25519::Keypair::from) - .map(Keypair::from), + .map(ed25519::Keypair::from), } } } @@ -887,7 +885,7 @@ impl> FullNetworkConfig .find(|o| o.peer_id != bootnode.peer_id) { Err(crate::error::Error::DuplicateBootnode { - address: bootnode.multiaddr.clone(), + address: bootnode.multiaddr.clone().into(), first_id: bootnode.peer_id.into(), second_id: other.peer_id.into(), }) @@ -947,14 +945,8 @@ mod tests { tempfile::Builder::new().prefix(prefix).tempdir().unwrap() } - fn secret_bytes(kp: Keypair) -> Vec { - kp.try_into_ed25519() - .expect("ed25519 keypair") - .secret() - .as_ref() - .iter() - .cloned() - .collect() + fn secret_bytes(kp: ed25519::Keypair) -> Vec { + kp.secret().to_bytes().into() } #[test] diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs index 4e2121c5540d6c7c6d895e2756b266f6b5a945e8..7d4481b0d06f947619b66ab60a5ab60b8fe15a99 100644 --- a/substrate/client/network/src/discovery.rs +++ b/substrate/client/network/src/discovery.rs @@ -105,7 +105,8 @@ pub struct DiscoveryConfig { discovery_only_if_under_num: u64, enable_mdns: bool, kademlia_disjoint_query_paths: bool, - kademlia_protocols: Vec>, + kademlia_protocol: Vec, + kademlia_legacy_protocol: Vec, kademlia_replication_factor: NonZeroUsize, } @@ -121,7 +122,8 @@ impl DiscoveryConfig { discovery_only_if_under_num: std::u64::MAX, enable_mdns: false, kademlia_disjoint_query_paths: false, - kademlia_protocols: Vec::new(), + kademlia_protocol: Vec::new(), + kademlia_legacy_protocol: Vec::new(), kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR) .expect("value is a constant; constant is non-zero; qed."), } @@ -177,9 +179,8 @@ impl DiscoveryConfig { fork_id: Option<&str>, protocol_id: &ProtocolId, ) -> &mut Self { - self.kademlia_protocols = Vec::new(); - self.kademlia_protocols.push(kademlia_protocol_name(genesis_hash, fork_id)); - self.kademlia_protocols.push(legacy_kademlia_protocol_name(protocol_id)); + self.kademlia_protocol = kademlia_protocol_name(genesis_hash, fork_id); + self.kademlia_legacy_protocol = legacy_kademlia_protocol_name(protocol_id); self } @@ -207,14 +208,19 @@ impl DiscoveryConfig { discovery_only_if_under_num, enable_mdns, kademlia_disjoint_query_paths, - kademlia_protocols, + kademlia_protocol, + kademlia_legacy_protocol, kademlia_replication_factor, } = self; - let kademlia = if !kademlia_protocols.is_empty() { + let kademlia = if !kademlia_protocol.is_empty() { let mut config = KademliaConfig::default(); config.set_replication_factor(kademlia_replication_factor); + // Populate kad with both the legacy and the new protocol names. + // Remove the legacy protocol: + // https://github.com/paritytech/polkadot-sdk/issues/504 + let kademlia_protocols = [kademlia_protocol.clone(), kademlia_legacy_protocol]; config.set_protocol_names(kademlia_protocols.into_iter().map(Into::into).collect()); // By default Kademlia attempts to insert all peers into its routing table once a // dialing attempt succeeds. In order to control which peer is added, disable the @@ -266,6 +272,7 @@ impl DiscoveryConfig { .expect("value is a constant; constant is non-zero; qed."), ), records_to_publish: Default::default(), + kademlia_protocol, } } } @@ -309,6 +316,11 @@ pub struct DiscoveryBehaviour { /// did not return the record(in `FinishedWithNoAdditionalRecord`). We will then put the record /// to these peers. records_to_publish: HashMap, + /// The chain based kademlia protocol name (including genesis hash and fork id). + /// + /// Remove when all nodes are upgraded to genesis hash and fork ID-based Kademlia: + /// . + kademlia_protocol: Vec, } impl DiscoveryBehaviour { @@ -366,23 +378,29 @@ impl DiscoveryBehaviour { return } - if let Some(matching_protocol) = supported_protocols + // The supported protocols must include the chain-based Kademlia protocol. + // + // Extract the chain-based Kademlia protocol from `kademlia.protocol_name()` + // when all nodes are upgraded to genesis hash and fork ID-based Kademlia: + // https://github.com/paritytech/polkadot-sdk/issues/504. + if !supported_protocols .iter() - .find(|p| kademlia.protocol_names().iter().any(|k| k.as_ref() == p.as_ref())) + .any(|p| p.as_ref() == self.kademlia_protocol.as_slice()) { - trace!( - target: "sub-libp2p", - "Adding self-reported address {} from {} to Kademlia DHT {}.", - addr, peer_id, String::from_utf8_lossy(matching_protocol.as_ref()), - ); - kademlia.add_address(peer_id, addr.clone()); - } else { trace!( target: "sub-libp2p", "Ignoring self-reported address {} from {} as remote node is not part of the \ Kademlia DHT supported by the local node.", addr, peer_id, ); + return } + + trace!( + target: "sub-libp2p", + "Adding self-reported address {} from {} to Kademlia DHT.", + addr, peer_id + ); + kademlia.add_address(peer_id, addr.clone()); } } @@ -1075,17 +1093,20 @@ mod tests { .unwrap(); // Test both genesis hash-based and legacy // protocol names. - let protocol_name = if swarm_n % 2 == 0 { - kademlia_protocol_name(genesis_hash, fork_id) + let protocol_names = if swarm_n % 2 == 0 { + vec![kademlia_protocol_name(genesis_hash, fork_id)] } else { - legacy_kademlia_protocol_name(&protocol_id) + vec![ + legacy_kademlia_protocol_name(&protocol_id), + kademlia_protocol_name(genesis_hash, fork_id), + ] }; swarms[swarm_n] .0 .behaviour_mut() .add_self_reported_address( &other, - &[protocol_name], + protocol_names.as_slice(), addr, ); @@ -1181,9 +1202,56 @@ mod tests { &[kademlia_protocol_name(supported_genesis_hash, None)], remote_addr.clone(), ); + { + let kademlia = discovery.kademlia.as_mut().unwrap(); + assert!( + !kademlia + .kbucket(remote_peer_id) + .expect("Remote peer id not to be equal to local peer id.") + .is_empty(), + "Expect peer with supported protocol to be added." + ); + } + + let unsupported_peer_id = predictable_peer_id(b"00000000000000000000000000000002"); + let unsupported_peer_addr: Multiaddr = "/memory/2".parse().unwrap(); + + // Check the unsupported peer is not present before and after the call. + { + let kademlia = discovery.kademlia.as_mut().unwrap(); + assert!( + kademlia + .kbucket(unsupported_peer_id) + .expect("Remote peer id not to be equal to local peer id.") + .is_empty(), + "Expect unsupported peer not to be added." + ); + } + // Note: legacy protocol is not supported without genesis hash and fork ID, + // if the legacy is the only protocol supported, then the peer will not be added. + discovery.add_self_reported_address( + &unsupported_peer_id, + &[legacy_kademlia_protocol_name(&supported_protocol_id)], + unsupported_peer_addr.clone(), + ); + { + let kademlia = discovery.kademlia.as_mut().unwrap(); + assert!( + kademlia + .kbucket(unsupported_peer_id) + .expect("Remote peer id not to be equal to local peer id.") + .is_empty(), + "Expect unsupported peer not to be added." + ); + } + + // Supported legacy and genesis based protocols are allowed to be added. discovery.add_self_reported_address( &another_peer_id, - &[legacy_kademlia_protocol_name(&supported_protocol_id)], + &[ + legacy_kademlia_protocol_name(&supported_protocol_id), + kademlia_protocol_name(supported_genesis_hash, None), + ], another_addr.clone(), ); @@ -1194,6 +1262,13 @@ mod tests { kademlia.kbuckets().fold(0, |acc, bucket| acc + bucket.num_entries()), "Expect peers with supported protocol to be added." ); + assert!( + !kademlia + .kbucket(another_peer_id) + .expect("Remote peer id not to be equal to local peer id.") + .is_empty(), + "Expect peer with supported protocol to be added." + ); } } } diff --git a/substrate/client/network/src/error.rs b/substrate/client/network/src/error.rs index b776e3e1ad9de8f84118f293f28ad00c88969ba0..376b8461be4e57a72ad45c7f29763bba19e40ac9 100644 --- a/substrate/client/network/src/error.rs +++ b/substrate/client/network/src/error.rs @@ -20,7 +20,7 @@ use crate::{config::TransportConfig, types::ProtocolName}; -use libp2p::{Multiaddr, PeerId}; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use std::fmt; diff --git a/substrate/client/network/src/lib.rs b/substrate/client/network/src/lib.rs index 8f479825c8d77c7684333981d1763099b8a537c9..99a972f914e261e60ef8692fc3fab7a53051d3df 100644 --- a/substrate/client/network/src/lib.rs +++ b/substrate/client/network/src/lib.rs @@ -272,6 +272,10 @@ pub use sc_network_common::{ role::{ObservedRole, Roles}, types::ReputationChange, }; +pub use sc_network_types::{ + multiaddr::{self, Multiaddr}, + PeerId, +}; pub use service::{ metrics::NotificationMetrics, signature::Signature, @@ -285,7 +289,7 @@ pub use service::{ DecodingError, Keypair, NetworkService, NetworkWorker, NotificationSender, OutboundFailure, PublicKey, }; -pub use types::{multiaddr, Multiaddr, PeerId, ProtocolName}; +pub use types::ProtocolName; /// The maximum allowed number of established connections per peer. /// diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 27f4d5473722186e986deef29bb8a9b3eb0aeaec..ff5f492df246a6e4165700132d080c183b91b79a 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -20,9 +20,7 @@ use crate::{ config::{NetworkConfiguration, ProtocolId}, - multiaddr::Protocol, peer_store::PeerStoreProvider, - Multiaddr, }; use array_bytes::bytes2hex; @@ -36,12 +34,13 @@ use litep2p::{ identify::{Config as IdentifyConfig, IdentifyEvent}, kademlia::{ Config as KademliaConfig, ConfigBuilder as KademliaConfigBuilder, KademliaEvent, - KademliaHandle, QueryId, Quorum, Record, RecordKey, + KademliaHandle, QueryId, Quorum, Record, RecordKey, RecordsType, }, ping::{Config as PingConfig, PingEvent}, }, mdns::{Config as MdnsConfig, MdnsEvent}, }, + types::multiaddr::{Multiaddr, Protocol}, PeerId, ProtocolName, }; use parking_lot::RwLock; @@ -124,8 +123,8 @@ pub enum DiscoveryEvent { /// Query ID. query_id: QueryId, - /// Record. - record: Record, + /// Records. + records: RecordsType, }, /// Record was successfully stored on the DHT. @@ -227,7 +226,7 @@ impl Discovery { let (identify_config, identify_event_stream) = IdentifyConfig::new( "/substrate/1.0".to_string(), Some(user_agent), - config.public_addresses.clone(), + config.public_addresses.clone().into_iter().map(Into::into).collect(), ); let (mdns_config, mdns_event_stream) = match config.transport { @@ -266,12 +265,12 @@ impl Discovery { duration_to_next_find_query: Duration::from_secs(1), address_confirmations: LruMap::new(ByLength::new(8)), allow_non_global_addresses: config.allow_non_globals_in_dht, - public_addresses: config.public_addresses.iter().cloned().collect(), + public_addresses: config.public_addresses.iter().cloned().map(Into::into).collect(), next_kad_query: Some(Delay::new(KADEMLIA_QUERY_INTERVAL)), - local_protocols: HashSet::from_iter([ - kademlia_protocol_name(genesis_hash, fork_id), - legacy_kademlia_protocol_name(protocol_id), - ]), + local_protocols: HashSet::from_iter([kademlia_protocol_name( + genesis_hash, + fork_id, + )]), }, ping_config, identify_config, @@ -295,6 +294,11 @@ impl Discovery { addresses: Vec, ) { if self.local_protocols.is_disjoint(&supported_protocols) { + log::trace!( + target: "sub-libp2p", + "Ignoring self-reported address of peer {peer} as remote node is not part of the \ + Kademlia DHT supported by the local node.", + ); return } @@ -456,13 +460,13 @@ impl Stream for Discovery { peers: peers.into_iter().collect(), })) }, - Poll::Ready(Some(KademliaEvent::GetRecordSuccess { query_id, record })) => { + Poll::Ready(Some(KademliaEvent::GetRecordSuccess { query_id, records })) => { log::trace!( target: LOG_TARGET, - "`GET_RECORD` succeeded for {query_id:?}: {record:?}", + "`GET_RECORD` succeeded for {query_id:?}: {records:?}", ); - return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { query_id, record })); + return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { query_id, records })); }, Poll::Ready(Some(KademliaEvent::PutRecordSucess { query_id, key: _ })) => return Poll::Ready(Some(DiscoveryEvent::PutRecordSuccess { query_id })), diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 1137c73b56db8292fdee437ee3a656f38e789f51..ae287052b2d44934a8b4827e53c77cae0d707be9 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -38,7 +38,6 @@ use crate::{ request_response::{RequestResponseConfig, RequestResponseProtocol}, }, }, - multiaddr::{Multiaddr, Protocol}, peer_store::PeerStoreProvider, protocol, service::{ @@ -54,17 +53,23 @@ use futures::StreamExt; use libp2p::kad::RecordKey; use litep2p::{ config::ConfigBuilder, - crypto::ed25519::{Keypair, SecretKey}, + crypto::ed25519::Keypair, executor::Executor, protocol::{ - libp2p::{bitswap::Config as BitswapConfig, kademlia::QueryId}, + libp2p::{ + bitswap::Config as BitswapConfig, + kademlia::{QueryId, RecordsType}, + }, request_response::ConfigBuilder as RequestResponseConfigBuilder, }, transport::{ tcp::config::Config as TcpTransportConfig, websocket::config::Config as WebSocketTransportConfig, Endpoint, }, - types::ConnectionId, + types::{ + multiaddr::{Multiaddr, Protocol}, + ConnectionId, + }, Error as Litep2pError, Litep2p, Litep2pEvent, ProtocolName as Litep2pProtocolName, }; use parking_lot::RwLock; @@ -81,7 +86,7 @@ use std::{ collections::{hash_map::Entry, HashMap, HashSet}, fs, future::Future, - io, iter, + iter, pin::Pin, sync::{ atomic::{AtomicUsize, Ordering}, @@ -200,12 +205,12 @@ impl Litep2pNetworkBackend { Protocol::Ip4(_), ) => match address.iter().find(|protocol| std::matches!(protocol, Protocol::P2p(_))) { - Some(Protocol::P2p(multihash)) => PeerId::from_multihash(multihash) + Some(Protocol::P2p(multihash)) => PeerId::from_multihash(multihash.into()) .map_or(None, |peer| Some((peer, Some(address)))), _ => None, }, Some(Protocol::P2p(multihash)) => - PeerId::from_multihash(multihash).map_or(None, |peer| Some((peer, None))), + PeerId::from_multihash(multihash.into()).map_or(None, |peer| Some((peer, None))), _ => None, }) .fold(HashMap::new(), |mut acc, (peer, maybe_address)| { @@ -244,16 +249,9 @@ impl Litep2pNetworkBackend { impl Litep2pNetworkBackend { /// Get `litep2p` keypair from `NodeKeyConfig`. fn get_keypair(node_key: &NodeKeyConfig) -> Result<(Keypair, litep2p::PeerId), Error> { - let secret = libp2p::identity::Keypair::try_into_ed25519(node_key.clone().into_keypair()?) - .map_err(|error| { - log::error!(target: LOG_TARGET, "failed to convert to ed25519: {error:?}"); - Error::Io(io::ErrorKind::InvalidInput.into()) - })? - .secret(); - - let mut secret = secret.as_ref().iter().cloned().collect::>(); - let secret = SecretKey::from_bytes(&mut secret) - .map_err(|_| Error::Io(io::ErrorKind::InvalidInput.into()))?; + let secret: litep2p::crypto::ed25519::SecretKey = + node_key.clone().into_keypair()?.secret().into(); + let local_identity = Keypair::from(secret); let local_public = local_identity.public(); let local_peer_id = local_public.to_peer_id(); @@ -327,6 +325,8 @@ impl Litep2pNetworkBackend { .listen_addresses .iter() .filter_map(|address| { + use sc_network_types::multiaddr::Protocol; + let mut iter = address.iter(); match iter.next() { @@ -367,12 +367,12 @@ impl Litep2pNetworkBackend { config_builder .with_websocket(WebSocketTransportConfig { - listen_addresses: websocket.into_iter().flatten().collect(), + listen_addresses: websocket.into_iter().flatten().map(Into::into).collect(), yamux_config: yamux_config.clone(), ..Default::default() }) .with_tcp(TcpTransportConfig { - listen_addresses: tcp.into_iter().flatten().collect(), + listen_addresses: tcp.into_iter().flatten().map(Into::into).collect(), yamux_config, ..Default::default() }) @@ -522,6 +522,8 @@ impl NetworkBackend for Litep2pNetworkBac // collect known addresses let known_addresses: HashMap> = known_addresses.into_iter().fold(HashMap::new(), |mut acc, (peer, address)| { + use sc_network_types::multiaddr::Protocol; + let address = match address.iter().last() { Some(Protocol::Ws(_) | Protocol::Wss(_) | Protocol::Tcp(_)) => address.with(Protocol::P2p(peer.into())), @@ -529,7 +531,7 @@ impl NetworkBackend for Litep2pNetworkBac _ => return acc, }; - acc.entry(peer.into()).or_default().push(address); + acc.entry(peer.into()).or_default().push(address.into()); peer_store_handle.add_known_peer(peer); acc @@ -567,7 +569,7 @@ impl NetworkBackend for Litep2pNetworkBac Litep2p::new(config_builder.build()).map_err(|error| Error::Litep2p(error))?; let external_addresses: Arc>> = Arc::new(RwLock::new( - HashSet::from_iter(network_config.public_addresses.iter().cloned()), + HashSet::from_iter(network_config.public_addresses.iter().cloned().map(Into::into)), )); litep2p.listen_addresses().for_each(|address| { log::debug!(target: LOG_TARGET, "listening on: {address}"); @@ -713,7 +715,7 @@ impl NetworkBackend for Litep2pNetworkBac protocol, peers, } => { - let peers = self.add_addresses(peers.into_iter()); + let peers = self.add_addresses(peers.into_iter().map(Into::into)); match self.peerset_handles.get(&protocol) { Some(handle) => { @@ -722,9 +724,11 @@ impl NetworkBackend for Litep2pNetworkBac None => log::warn!(target: LOG_TARGET, "protocol {protocol} doens't exist"), }; } - NetworkServiceCommand::AddKnownAddress { peer, mut address } => { + NetworkServiceCommand::AddKnownAddress { peer, address } => { + let mut address: Multiaddr = address.into(); + if !address.iter().any(|protocol| std::matches!(protocol, Protocol::P2p(_))) { - address.push(Protocol::P2p(peer.into())); + address.push(Protocol::P2p(litep2p::PeerId::from(peer).into())); } if self.litep2p.add_known_address(peer.into(), iter::once(address.clone())) == 0usize { @@ -735,7 +739,7 @@ impl NetworkBackend for Litep2pNetworkBac } }, NetworkServiceCommand::SetReservedPeers { protocol, peers } => { - let peers = self.add_addresses(peers.into_iter()); + let peers = self.add_addresses(peers.into_iter().map(Into::into)); match self.peerset_handles.get(&protocol) { Some(handle) => { @@ -795,23 +799,30 @@ impl NetworkBackend for Litep2pNetworkBac self.peerstore_handle.add_known_peer(peer.into()); } } - Some(DiscoveryEvent::GetRecordSuccess { query_id, record }) => { + Some(DiscoveryEvent::GetRecordSuccess { query_id, records }) => { match self.pending_get_values.remove(&query_id) { None => log::warn!( target: LOG_TARGET, "`GET_VALUE` succeeded for a non-existent query", ), - Some((_key, started)) => { + Some((key, started)) => { log::trace!( target: LOG_TARGET, "`GET_VALUE` for {:?} ({query_id:?}) succeeded", - record.key, + key, ); - self.event_streams.send(Event::Dht( - DhtEvent::ValueFound(vec![ + let value_found = match records { + RecordsType::LocalStore(record) => vec![ (libp2p::kad::RecordKey::new(&record.key), record.value) - ]) + ], + RecordsType::Network(records) => records.into_iter().map(|peer_record| { + (libp2p::kad::RecordKey::new(&peer_record.record.key), peer_record.record.value) + }).collect(), + }; + + self.event_streams.send(Event::Dht( + DhtEvent::ValueFound(value_found) )); if let Some(ref metrics) = self.metrics { diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index 86f11aa6e142e2a1bdc161e7a92e34f5833cd1bb..09b869abdf5f5e38050f3b275b6a95da0a342745 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -24,7 +24,6 @@ use crate::{ notification::{config::ProtocolControlHandle, peerset::PeersetCommand}, request_response::OutboundRequest, }, - multiaddr::Protocol, network_state::NetworkState, peer_store::PeerStoreProvider, service::out_events, @@ -35,15 +34,18 @@ use crate::{ use codec::DecodeAll; use futures::{channel::oneshot, stream::BoxStream}; -use libp2p::{identity::SigningError, kad::record::Key as KademliaKey, Multiaddr}; -use litep2p::crypto::ed25519::Keypair; +use libp2p::{identity::SigningError, kad::record::Key as KademliaKey}; +use litep2p::{crypto::ed25519::Keypair, types::multiaddr::Multiaddr as LiteP2pMultiaddr}; use parking_lot::RwLock; use sc_network_common::{ role::{ObservedRole, Roles}, types::ReputationChange, }; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{Multiaddr, Protocol}, + PeerId, +}; use sc_utils::mpsc::TracingUnboundedSender; use std::{ @@ -165,10 +167,10 @@ pub struct Litep2pNetworkService { request_response_protocols: HashMap>, /// Listen addresses. - listen_addresses: Arc>>, + listen_addresses: Arc>>, /// External addresses. - external_addresses: Arc>>, + external_addresses: Arc>>, } impl Litep2pNetworkService { @@ -181,8 +183,8 @@ impl Litep2pNetworkService { peerset_handles: HashMap, block_announce_protocol: ProtocolName, request_response_protocols: HashMap>, - listen_addresses: Arc>>, - external_addresses: Arc>>, + listen_addresses: Arc>>, + external_addresses: Arc>>, ) -> Self { Self { local_peer_id, @@ -322,7 +324,7 @@ impl NetworkPeers for Litep2pNetworkService { fn add_reserved_peer(&self, peer: MultiaddrWithPeerId) -> Result<(), String> { let _ = self.cmd_tx.unbounded_send(NetworkServiceCommand::AddPeersToReservedSet { protocol: self.block_announce_protocol.clone(), - peers: HashSet::from_iter([peer.concat()]), + peers: HashSet::from_iter([peer.concat().into()]), }); Ok(()) @@ -415,11 +417,11 @@ impl NetworkEventStream for Litep2pNetworkService { impl NetworkStateInfo for Litep2pNetworkService { fn external_addresses(&self) -> Vec { - self.external_addresses.read().iter().cloned().collect() + self.external_addresses.read().iter().cloned().map(Into::into).collect() } fn listen_addresses(&self) -> Vec { - self.listen_addresses.read().iter().cloned().collect() + self.listen_addresses.read().iter().cloned().map(Into::into).collect() } fn local_peer_id(&self) -> PeerId { diff --git a/substrate/client/network/src/peer_store.rs b/substrate/client/network/src/peer_store.rs index a4c739f1448e685aad34819b627333e4c250d957..987405500dc9b22e8a19d667cc4e1fe26f18c16d 100644 --- a/substrate/client/network/src/peer_store.rs +++ b/substrate/client/network/src/peer_store.rs @@ -19,8 +19,9 @@ //! [`PeerStore`] manages peer reputations and provides connection candidates to //! [`crate::protocol_controller::ProtocolController`]. -use crate::{service::traits::PeerStore as PeerStoreT, PeerId}; +use crate::service::traits::PeerStore as PeerStoreT; +use libp2p::PeerId; use log::trace; use parking_lot::Mutex; use partial_sort::PartialSort; diff --git a/substrate/client/network/src/protocol/notifications/service/mod.rs b/substrate/client/network/src/protocol/notifications/service/mod.rs index 15d289d170ee83e52476d4b5a1c5a10bde3274c8..4f6d32ae3b356f8813bb38cab5b80050f600931d 100644 --- a/substrate/client/network/src/protocol/notifications/service/mod.rs +++ b/substrate/client/network/src/protocol/notifications/service/mod.rs @@ -28,13 +28,13 @@ use crate::{ }, }, types::ProtocolName, - PeerId, }; use futures::{ stream::{FuturesUnordered, Stream}, StreamExt, }; +use libp2p::PeerId; use parking_lot::Mutex; use tokio::sync::{mpsc, oneshot}; use tokio_stream::wrappers::ReceiverStream; diff --git a/substrate/client/network/src/protocol/notifications/service/tests.rs b/substrate/client/network/src/protocol/notifications/service/tests.rs index f0157f6d28dd10d7382427b7464e4f478d912c03..32ccb3348adfbce266561645c75fea466023ed72 100644 --- a/substrate/client/network/src/protocol/notifications/service/tests.rs +++ b/substrate/client/network/src/protocol/notifications/service/tests.rs @@ -200,7 +200,7 @@ async fn send_async_notification_to_non_existent_peer() { if let Err(error::Error::PeerDoesntExist(peer_id)) = notif.send_async_notification(&peer.into(), vec![1, 3, 3, 7]).await { - assert_eq!(peer, peer_id); + assert_eq!(peer, peer_id.into()); } else { panic!("invalid error received from `send_async_notification()`"); } diff --git a/substrate/client/network/src/protocol_controller.rs b/substrate/client/network/src/protocol_controller.rs index 2c3e6744e328f3900790e747a3a8d998f4e6964e..da51a7a4f9f43f4ac68632a7701d62983f08ec26 100644 --- a/substrate/client/network/src/protocol_controller.rs +++ b/substrate/client/network/src/protocol_controller.rs @@ -41,12 +41,10 @@ //! Even though this does not guarantee that `ProtocolController` and `Notifications` have the same //! view of the peers' states at any given moment, the eventual consistency is maintained. -use crate::{ - peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}, - PeerId, -}; +use crate::peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}; use futures::{channel::oneshot, future::Either, FutureExt, StreamExt}; +use libp2p::PeerId; use log::{debug, error, trace, warn}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_arithmetic::traits::SaturatedConversion; @@ -860,8 +858,9 @@ mod tests { use super::*; use crate::{ peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}, - PeerId, ReputationChange, + ReputationChange, }; + use libp2p::PeerId; use sc_network_common::role::ObservedRole; use sc_utils::mpsc::{tracing_unbounded, TryRecvError}; use std::collections::HashSet; diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index 807c5b5a80afa682ef07b9ba2326a528b5d1c8f5..27de12bc1ec9a50ca8c5773de8a6bdbda61d35ab 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -55,24 +55,26 @@ use crate::{ }, transport, types::ProtocolName, - Multiaddr, NotificationService, PeerId, ReputationChange, + NotificationService, ReputationChange, }; use codec::DecodeAll; use either::Either; use futures::{channel::oneshot, prelude::*}; +use libp2p::identity::ed25519; #[allow(deprecated)] use libp2p::{ connection_limits::Exceeded, core::{upgrade, ConnectedPoint, Endpoint}, identify::Info as IdentifyInfo, kad::record::Key as KademliaKey, - multiaddr, + multiaddr::{self, Multiaddr}, ping::Failure as PingFailure, swarm::{ AddressScore, ConnectionError, ConnectionId, ConnectionLimits, DialError, Executor, ListenError, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr, }, + PeerId, }; use log::{debug, error, info, trace, warn}; use metrics::{Histogram, MetricSources, Metrics}; @@ -269,6 +271,15 @@ where let local_public = local_identity.public(); let local_peer_id = local_public.to_peer_id(); + // Convert to libp2p types. + let local_identity: ed25519::Keypair = local_identity.into(); + let local_public: ed25519::PublicKey = local_public.into(); + let local_peer_id: PeerId = local_peer_id.into(); + let listen_addresses: Vec = + network_config.listen_addresses.iter().cloned().map(Into::into).collect(); + let public_addresses: Vec = + network_config.public_addresses.iter().cloned().map(Into::into).collect(); + network_config.boot_nodes = network_config .boot_nodes .into_iter() @@ -370,7 +381,7 @@ where }; transport::build_transport( - local_identity.clone(), + local_identity.clone().into(), config_mem, network_config.yamux_window_size, yamux_maximum_buffer_size, @@ -462,7 +473,7 @@ where .find(|o| o.peer_id != bootnode.peer_id) { Err(Error::DuplicateBootnode { - address: bootnode.multiaddr.clone(), + address: bootnode.multiaddr.clone().into(), first_id: bootnode.peer_id.into(), second_id: other.peer_id.into(), }) @@ -478,7 +489,7 @@ where boot_node_ids .entry(bootnode.peer_id.into()) .or_default() - .push(bootnode.multiaddr.clone()); + .push(bootnode.multiaddr.clone().into()); } let boot_node_ids = Arc::new(boot_node_ids); @@ -502,11 +513,11 @@ where format!("{} ({})", network_config.client_version, network_config.node_name); let discovery_config = { - let mut config = DiscoveryConfig::new(local_public.to_peer_id()); + let mut config = DiscoveryConfig::new(local_peer_id); config.with_permanent_addresses( known_addresses .iter() - .map(|(peer, address)| (peer.into(), address.clone())) + .map(|(peer, address)| (peer.into(), address.clone().into())) .collect::>(), ); config.discovery_limit(u64::from(network_config.default_peers_set.out_peers) + 15); @@ -544,7 +555,7 @@ where let result = Behaviour::new( protocol, user_agent, - local_public, + local_public.into(), discovery_config, request_response_protocols, Arc::clone(&peer_store_handle), @@ -581,7 +592,7 @@ where crate::MAX_CONNECTIONS_ESTABLISHED_INCOMING, )), ) - .substream_upgrade_protocol_override(upgrade::Version::V1Lazy) + .substream_upgrade_protocol_override(upgrade::Version::V1) .notify_handler_buffer_size(NonZeroUsize::new(32).expect("32 != 0; qed")) // NOTE: 24 is somewhat arbitrary and should be tuned in the future if necessary. // See @@ -604,14 +615,14 @@ where }; // Listen on multiaddresses. - for addr in &network_config.listen_addresses { + for addr in &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 &network_config.public_addresses { + for addr in &public_addresses { Swarm::>::add_external_address( &mut swarm, addr.clone(), @@ -619,15 +630,15 @@ where ); } - let listen_addresses = Arc::new(Mutex::new(HashSet::new())); + let listen_addresses_set = Arc::new(Mutex::new(HashSet::new())); let service = Arc::new(NetworkService { bandwidth, external_addresses, - listen_addresses: listen_addresses.clone(), + listen_addresses: listen_addresses_set.clone(), num_connected: num_connected.clone(), local_peer_id, - local_identity, + local_identity: local_identity.into(), to_worker, notification_protocol_ids, protocol_handles, @@ -638,7 +649,7 @@ where }); Ok(NetworkWorker { - listen_addresses, + listen_addresses: listen_addresses_set, num_connected, network_service: swarm, service, @@ -880,13 +891,13 @@ where H: ExHashT, { /// Returns the local external addresses. - fn external_addresses(&self) -> Vec { - self.external_addresses.lock().iter().cloned().collect() + fn external_addresses(&self) -> Vec { + self.external_addresses.lock().iter().cloned().map(Into::into).collect() } /// Returns the listener addresses (without trailing `/p2p/` with our `PeerId`). - fn listen_addresses(&self) -> Vec { - self.listen_addresses.lock().iter().cloned().collect() + fn listen_addresses(&self) -> Vec { + self.listen_addresses.lock().iter().cloned().map(Into::into).collect() } /// Returns the local Peer ID. @@ -998,10 +1009,14 @@ where self.sync_protocol_handle.set_reserved_only(reserved_only); } - fn add_known_address(&self, peer_id: sc_network_types::PeerId, addr: Multiaddr) { + fn add_known_address( + &self, + peer_id: sc_network_types::PeerId, + addr: sc_network_types::multiaddr::Multiaddr, + ) { let _ = self .to_worker - .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id.into(), addr)); + .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id.into(), addr.into())); } fn report_peer(&self, peer_id: sc_network_types::PeerId, cost_benefit: ReputationChange) { @@ -1034,7 +1049,7 @@ where let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::AddKnownAddress( peer.peer_id.into(), - peer.multiaddr, + peer.multiaddr.into(), )); self.sync_protocol_handle.add_reserved_peer(peer.peer_id.into()); @@ -1048,16 +1063,16 @@ where fn set_reserved_peers( &self, protocol: ProtocolName, - peers: HashSet, + peers: HashSet, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { return Err(format!("Cannot set reserved peers for unknown protocol: {}", protocol)) }; + let peers: HashSet = peers.into_iter().map(Into::into).collect(); let peers_addrs = self.split_multiaddr_and_peer_id(peers)?; - let mut peers: HashSet = - HashSet::with_capacity(peers_addrs.len()); + let mut peers: HashSet = HashSet::with_capacity(peers_addrs.len()); for (peer_id, addr) in peers_addrs.into_iter() { // Make sure the local peer ID is never added to the PSM. @@ -1074,8 +1089,7 @@ where } } - self.protocol_handles[usize::from(*set_id)] - .set_reserved_peers(peers.iter().map(|peer| (*peer).into()).collect()); + self.protocol_handles[usize::from(*set_id)].set_reserved_peers(peers); Ok(()) } @@ -1083,7 +1097,7 @@ where fn add_peers_to_reserved_set( &self, protocol: ProtocolName, - peers: HashSet, + peers: HashSet, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { return Err(format!( @@ -1092,6 +1106,7 @@ where )) }; + let peers: HashSet = peers.into_iter().map(Into::into).collect(); let peers = self.split_multiaddr_and_peer_id(peers)?; for (peer_id, addr) in peers.into_iter() { @@ -1723,8 +1738,8 @@ where { if let DialError::WrongPeerId { obtained, endpoint } = &error { if let ConnectedPoint::Dialer { address, role_override: _ } = endpoint { - let address_without_peer_id = parse_addr(address.clone()) - .map_or_else(|_| address.clone(), |r| r.1); + let address_without_peer_id = parse_addr(address.clone().into()) + .map_or_else(|_| address.clone(), |r| r.1.into()); // Only report for address of boot node that was added at startup of // the node and not for any address that the node learned of the @@ -1860,14 +1875,14 @@ where } pub(crate) fn ensure_addresses_consistent_with_transport<'a>( - addresses: impl Iterator, + addresses: impl Iterator, transport: &TransportConfig, ) -> Result<(), Error> { + use sc_network_types::multiaddr::Protocol; + if matches!(transport, TransportConfig::MemoryOnly) { let addresses: Vec<_> = addresses - .filter(|x| { - x.iter().any(|y| !matches!(y, libp2p::core::multiaddr::Protocol::Memory(_))) - }) + .filter(|x| x.iter().any(|y| !matches!(y, Protocol::Memory(_)))) .cloned() .collect(); @@ -1879,7 +1894,7 @@ pub(crate) fn ensure_addresses_consistent_with_transport<'a>( } } else { let addresses: Vec<_> = addresses - .filter(|x| x.iter().any(|y| matches!(y, libp2p::core::multiaddr::Protocol::Memory(_)))) + .filter(|x| x.iter().any(|y| matches!(y, Protocol::Memory(_)))) .cloned() .collect(); diff --git a/substrate/client/network/src/service/traits.rs b/substrate/client/network/src/service/traits.rs index 9bbaeb1026f9304d43d347893de5795fd0bb93b4..d1ea9a2ed568f7ee35416164e5e7f1a9d89d5c3b 100644 --- a/substrate/client/network/src/service/traits.rs +++ b/substrate/client/network/src/service/traits.rs @@ -28,7 +28,7 @@ use crate::{ request_responses::{IfDisconnected, RequestFailure}, service::{metrics::NotificationMetrics, signature::Signature, PeerStoreProvider}, types::ProtocolName, - Multiaddr, ReputationChange, + ReputationChange, }; use futures::{channel::oneshot, Stream}; @@ -36,7 +36,7 @@ use prometheus_endpoint::Registry; use sc_client_api::BlockBackend; use sc_network_common::{role::ObservedRole, ExHashT}; -use sc_network_types::PeerId; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use sp_runtime::traits::Block as BlockT; use std::{collections::HashSet, fmt::Debug, future::Future, pin::Pin, sync::Arc, time::Duration}; diff --git a/substrate/client/network/statement/Cargo.toml b/substrate/client/network/statement/Cargo.toml index 4ffe6d6e3aedf9154c073f63fa2ddbf4dda12c01..0dfaa491b65c93acb50f44bb002d655043317d99 100644 --- a/substrate/client/network/statement/Cargo.toml +++ b/substrate/client/network/statement/Cargo.toml @@ -16,9 +16,9 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" async-channel = "1.8.0" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" libp2p = "0.51.4" log = { workspace = true, default-features = true } diff --git a/substrate/client/network/sync/Cargo.toml b/substrate/client/network/sync/Cargo.toml index eb79973c2739a3bfd11477b4bbf0979249a741e6..964090444b22afdeca073ebc25d0be71817f1248 100644 --- a/substrate/client/network/sync/Cargo.toml +++ b/substrate/client/network/sync/Cargo.toml @@ -16,19 +16,19 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.11" +prost-build = "0.12.4" [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" async-channel = "1.8.0" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" futures-timer = "3.0.2" libp2p = "0.51.4" log = { workspace = true, default-features = true } mockall = "0.11.3" -prost = "0.12" +prost = "0.12.4" schnellru = "0.2.1" smallvec = "1.11.0" thiserror = { workspace = true } diff --git a/substrate/client/network/sync/src/block_announce_validator.rs b/substrate/client/network/sync/src/block_announce_validator.rs index 3c994dd69442a0a7b0f29820b8044f0308436c48..cb1d5ee6b22ee92104faa061fbc8958ce20d316d 100644 --- a/substrate/client/network/sync/src/block_announce_validator.rs +++ b/substrate/client/network/sync/src/block_announce_validator.rs @@ -156,7 +156,7 @@ impl BlockAnnounceValidator { return }, AllocateSlotForBlockAnnounceValidation::MaximumPeerSlotsReached => { - warn!( + debug!( target: LOG_TARGET, "💔 Ignored block (#{} -- {}) announcement from {} because all validation slots for this peer are occupied.", number, diff --git a/substrate/client/network/sync/src/service/mock.rs b/substrate/client/network/sync/src/service/mock.rs index 2e7e12af53d5373f4335361a108cd3980c7c3dcb..141edc7c884144455e43f5b7c5b2b62ae246bbab 100644 --- a/substrate/client/network/sync/src/service/mock.rs +++ b/substrate/client/network/sync/src/service/mock.rs @@ -23,10 +23,10 @@ use sc_network::{ config::MultiaddrWithPeerId, request_responses::{IfDisconnected, RequestFailure}, types::ProtocolName, - Multiaddr, NetworkPeers, NetworkRequest, NetworkSyncForkRequest, ReputationChange, + NetworkPeers, NetworkRequest, NetworkSyncForkRequest, ReputationChange, }; use sc_network_common::role::ObservedRole; -use sc_network_types::PeerId; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use sp_runtime::traits::{Block as BlockT, NumberFor}; use std::collections::HashSet; diff --git a/substrate/client/network/test/src/fuzz.rs b/substrate/client/network/test/src/fuzz.rs index 69d08d47d26a9ea4368ffdfea456711345d15d8b..b0cd6dcf999391a0fedd5a29a38b89d370e25771 100644 --- a/substrate/client/network/test/src/fuzz.rs +++ b/substrate/client/network/test/src/fuzz.rs @@ -20,6 +20,7 @@ //! and `PeerStore` to discover possible inconsistencies in peer management. use futures::prelude::*; +use libp2p::PeerId; use rand::{ distributions::{Distribution, Uniform, WeightedIndex}, seq::IteratorRandom, @@ -27,7 +28,7 @@ use rand::{ use sc_network::{ peer_store::{PeerStore, PeerStoreProvider}, protocol_controller::{IncomingIndex, Message, ProtoSetConfig, ProtocolController, SetId}, - PeerId, ReputationChange, + ReputationChange, }; use sc_utils::mpsc::tracing_unbounded; use std::{ diff --git a/substrate/client/network/test/src/lib.rs b/substrate/client/network/test/src/lib.rs index 48a4b3d6e6e16a4281c6e504d1c0d9511d2eb677..8a8f9608051af0bcb523b405585ad7c0b81b4ae2 100644 --- a/substrate/client/network/test/src/lib.rs +++ b/substrate/client/network/test/src/lib.rs @@ -35,7 +35,7 @@ use std::{ }; use futures::{channel::oneshot, future::BoxFuture, pin_mut, prelude::*}; -use libp2p::{build_multiaddr, PeerId}; +use libp2p::PeerId; use log::trace; use parking_lot::Mutex; use sc_block_builder::{BlockBuilder, BlockBuilderBuilder}; @@ -57,8 +57,8 @@ use sc_network::{ peer_store::PeerStore, request_responses::ProtocolConfig as RequestResponseConfig, types::ProtocolName, - Multiaddr, NetworkBlock, NetworkService, NetworkStateInfo, NetworkSyncForkRequest, - NetworkWorker, NotificationMetrics, NotificationService, + NetworkBlock, NetworkService, NetworkStateInfo, NetworkSyncForkRequest, NetworkWorker, + NotificationMetrics, NotificationService, }; use sc_network_common::role::Roles; use sc_network_light::light_client_requests::handler::LightClientRequestHandler; @@ -71,6 +71,7 @@ use sc_network_sync::{ }, warp_request_handler, }; +use sc_network_types::{build_multiaddr, multiaddr::Multiaddr}; use sc_service::client::Client; use sp_blockchain::{ Backend as BlockchainBackend, HeaderBackend, Info as BlockchainInfo, Result as ClientResult, @@ -985,7 +986,7 @@ pub trait TestNetFactory: Default + Sized + Send { for peer in peers.iter_mut() { peer.network.add_known_address( network.service().local_peer_id().into(), - listen_addr.clone(), + listen_addr.clone().into(), ); } diff --git a/substrate/client/network/transactions/Cargo.toml b/substrate/client/network/transactions/Cargo.toml index d74636d60a7da57edff1a14e003b623b252c94bc..d871b59b37bb120783aa2e27a23aa9ee814b3ddf 100644 --- a/substrate/client/network/transactions/Cargo.toml +++ b/substrate/client/network/transactions/Cargo.toml @@ -16,8 +16,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +array-bytes = "6.2.2" +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } futures = "0.3.30" libp2p = "0.51.4" log = { workspace = true, default-features = true } diff --git a/substrate/client/network/types/Cargo.toml b/substrate/client/network/types/Cargo.toml index d8f03939ab96c303bd4ae862cd76df2ff77e0c91..a9334aaa1705987a35322921616188113f011ed8 100644 --- a/substrate/client/network/types/Cargo.toml +++ b/substrate/client/network/types/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Substrate network types" name = "sc-network-types" -version = "0.10.0-dev" +version = "0.10.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors.workspace = true edition.workspace = true @@ -10,10 +10,15 @@ repository.workspace = true documentation = "https://docs.rs/sc-network-types" [dependencies] -bs58 = "0.4.0" +bs58 = "0.5.0" +ed25519-dalek = "2.1" libp2p-identity = { version = "0.1.3", features = ["ed25519", "peerid"] } -litep2p = { git = "https://github.com/paritytech/litep2p", branch = "master" } +litep2p = "0.5.0" multiaddr = "0.17.0" multihash = { version = "0.17.0", default-features = false, features = ["identity", "multihash-impl", "sha2", "std"] } rand = "0.8.5" thiserror = "1.0.48" +zeroize = { version = "1.7.0", default-features = false } + +[dev-dependencies] +quickcheck = "1.0.3" diff --git a/substrate/client/network/types/src/ed25519.rs b/substrate/client/network/types/src/ed25519.rs new file mode 100644 index 0000000000000000000000000000000000000000..e85f405b13066b8be1eed82f8ca783aa62c777d9 --- /dev/null +++ b/substrate/client/network/types/src/ed25519.rs @@ -0,0 +1,551 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Ed25519 keys. + +use crate::PeerId; +use core::{cmp, fmt, hash}; +use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _}; +use libp2p_identity::ed25519 as libp2p_ed25519; +use litep2p::crypto::ed25519 as litep2p_ed25519; +use zeroize::Zeroize; + +/// An Ed25519 keypair. +#[derive(Clone)] +pub struct Keypair(ed25519::SigningKey); + +impl Keypair { + /// Generate a new random Ed25519 keypair. + pub fn generate() -> Keypair { + Keypair::from(SecretKey::generate()) + } + + /// Convert the keypair into a byte array by concatenating the bytes + /// of the secret scalar and the compressed public point, + /// an informal standard for encoding Ed25519 keypairs. + pub fn to_bytes(&self) -> [u8; 64] { + self.0.to_keypair_bytes() + } + + /// Try to parse a keypair from the [binary format](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5) + /// produced by [`Keypair::to_bytes`], zeroing the input on success. + /// + /// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s. + pub fn try_from_bytes(kp: &mut [u8]) -> Result { + let bytes = <[u8; 64]>::try_from(&*kp) + .map_err(|e| DecodingError::KeypairParseError(Box::new(e)))?; + + ed25519::SigningKey::from_keypair_bytes(&bytes) + .map(|k| { + kp.zeroize(); + Keypair(k) + }) + .map_err(|e| DecodingError::KeypairParseError(Box::new(e))) + } + + /// Sign a message using the private key of this keypair. + pub fn sign(&self, msg: &[u8]) -> Vec { + self.0.sign(msg).to_bytes().to_vec() + } + + /// Get the public key of this keypair. + pub fn public(&self) -> PublicKey { + PublicKey(self.0.verifying_key()) + } + + /// Get the secret key of this keypair. + pub fn secret(&self) -> SecretKey { + SecretKey(self.0.to_bytes()) + } +} + +impl fmt::Debug for Keypair { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Keypair").field("public", &self.0.verifying_key()).finish() + } +} + +impl From for Keypair { + fn from(kp: litep2p_ed25519::Keypair) -> Self { + Self::try_from_bytes(&mut kp.encode()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for litep2p_ed25519::Keypair { + fn from(kp: Keypair) -> Self { + Self::decode(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for Keypair { + fn from(kp: libp2p_ed25519::Keypair) -> Self { + Self::try_from_bytes(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +impl From for libp2p_ed25519::Keypair { + fn from(kp: Keypair) -> Self { + Self::try_from_bytes(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +/// Demote an Ed25519 keypair to a secret key. +impl From for SecretKey { + fn from(kp: Keypair) -> SecretKey { + SecretKey(kp.0.to_bytes()) + } +} + +/// Promote an Ed25519 secret key into a keypair. +impl From for Keypair { + fn from(sk: SecretKey) -> Keypair { + let signing = ed25519::SigningKey::from_bytes(&sk.0); + Keypair(signing) + } +} + +/// An Ed25519 public key. +#[derive(Eq, Clone)] +pub struct PublicKey(ed25519::VerifyingKey); + +impl fmt::Debug for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("PublicKey(compressed): ")?; + for byte in self.0.as_bytes() { + write!(f, "{byte:x}")?; + } + Ok(()) + } +} + +impl cmp::PartialEq for PublicKey { + fn eq(&self, other: &Self) -> bool { + self.0.as_bytes().eq(other.0.as_bytes()) + } +} + +impl hash::Hash for PublicKey { + fn hash(&self, state: &mut H) { + self.0.as_bytes().hash(state); + } +} + +impl cmp::PartialOrd for PublicKey { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl cmp::Ord for PublicKey { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.0.as_bytes().cmp(other.0.as_bytes()) + } +} + +impl PublicKey { + /// Verify the Ed25519 signature on a message using the public key. + pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool { + ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok() + } + + /// Convert the public key to a byte array in compressed form, i.e. + /// where one coordinate is represented by a single bit. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() + } + + /// Try to parse a public key from a byte array containing the actual key as produced by + /// `to_bytes`. + pub fn try_from_bytes(k: &[u8]) -> Result { + let k = + <[u8; 32]>::try_from(k).map_err(|e| DecodingError::PublicKeyParseError(Box::new(e)))?; + ed25519::VerifyingKey::from_bytes(&k) + .map_err(|e| DecodingError::PublicKeyParseError(Box::new(e))) + .map(PublicKey) + } + + /// Convert public key to `PeerId`. + pub fn to_peer_id(&self) -> PeerId { + litep2p::PeerId::from(litep2p::crypto::PublicKey::Ed25519(self.clone().into())).into() + } +} + +impl From for PublicKey { + fn from(k: litep2p_ed25519::PublicKey) -> Self { + Self::try_from_bytes(&k.encode()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for litep2p_ed25519::PublicKey { + fn from(k: PublicKey) -> Self { + Self::decode(&k.to_bytes()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for PublicKey { + fn from(k: libp2p_ed25519::PublicKey) -> Self { + Self::try_from_bytes(&k.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +impl From for libp2p_ed25519::PublicKey { + fn from(k: PublicKey) -> Self { + Self::try_from_bytes(&k.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +/// An Ed25519 secret key. +#[derive(Clone)] +pub struct SecretKey(ed25519::SecretKey); + +/// View the bytes of the secret key. +impl AsRef<[u8]> for SecretKey { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl fmt::Debug for SecretKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "SecretKey") + } +} + +impl SecretKey { + /// Generate a new Ed25519 secret key. + pub fn generate() -> SecretKey { + let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng); + SecretKey(signing.to_bytes()) + } + + /// Try to parse an Ed25519 secret key from a byte slice + /// containing the actual key, zeroing the input on success. + /// If the bytes do not constitute a valid Ed25519 secret key, an error is + /// returned. + pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result { + let sk_bytes = sk_bytes.as_mut(); + let secret = <[u8; 32]>::try_from(&*sk_bytes) + .map_err(|e| DecodingError::SecretKeyParseError(Box::new(e)))?; + sk_bytes.zeroize(); + Ok(SecretKey(secret)) + } + + pub fn to_bytes(&self) -> [u8; 32] { + self.0 + } +} + +impl Drop for SecretKey { + fn drop(&mut self) { + self.0.zeroize(); + } +} + +impl From for SecretKey { + fn from(sk: litep2p_ed25519::SecretKey) -> Self { + Self::try_from_bytes(&mut sk.to_bytes()).expect("Ed25519 key to be 32 bytes length") + } +} + +impl From for litep2p_ed25519::SecretKey { + fn from(sk: SecretKey) -> Self { + Self::from_bytes(&mut sk.to_bytes()) + .expect("litep2p `SecretKey` to accept 32 bytes as Ed25519 key") + } +} + +impl From for SecretKey { + fn from(sk: libp2p_ed25519::SecretKey) -> Self { + Self::try_from_bytes(&mut sk.as_ref().to_owned()) + .expect("Ed25519 key to be 32 bytes length") + } +} + +impl From for libp2p_ed25519::SecretKey { + fn from(sk: SecretKey) -> Self { + Self::try_from_bytes(&mut sk.to_bytes()) + .expect("libp2p `SecretKey` to accept 32 bytes as Ed25519 key") + } +} + +/// Error when decoding `ed25519`-related types. +#[derive(Debug, thiserror::Error)] +pub enum DecodingError { + #[error("failed to parse Ed25519 keypair: {0}")] + KeypairParseError(Box), + #[error("failed to parse Ed25519 secret key: {0}")] + SecretKeyParseError(Box), + #[error("failed to parse Ed25519 public key: {0}")] + PublicKeyParseError(Box), +} + +#[cfg(test)] +mod tests { + use super::*; + use quickcheck::*; + + fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool { + kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes() + } + + #[test] + fn ed25519_keypair_encode_decode() { + fn prop() -> bool { + let kp1 = Keypair::generate(); + let mut kp1_enc = kp1.to_bytes(); + let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap(); + eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0) + } + QuickCheck::new().tests(10).quickcheck(prop as fn() -> _); + } + + #[test] + fn ed25519_keypair_from_secret() { + fn prop() -> bool { + let kp1 = Keypair::generate(); + let mut sk = kp1.0.to_bytes(); + let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap()); + eq_keypairs(&kp1, &kp2) && sk == [0u8; 32] + } + QuickCheck::new().tests(10).quickcheck(prop as fn() -> _); + } + + #[test] + fn ed25519_signature() { + let kp = Keypair::generate(); + let pk = kp.public(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + assert!(pk.verify(msg, &sig)); + + let mut invalid_sig = sig.clone(); + invalid_sig[3..6].copy_from_slice(&[10, 23, 42]); + assert!(!pk.verify(msg, &invalid_sig)); + + let invalid_msg = "h3ll0 w0rld".as_bytes(); + assert!(!pk.verify(invalid_msg, &sig)); + } + + #[test] + fn substrate_kp_to_libs() { + let kp = Keypair::generate(); + let kp_bytes = kp.to_bytes(); + let kp1: libp2p_ed25519::Keypair = kp.clone().into(); + let kp2: litep2p_ed25519::Keypair = kp.clone().into(); + let kp3 = libp2p_ed25519::Keypair::try_from_bytes(&mut kp_bytes.clone()).unwrap(); + let kp4 = litep2p_ed25519::Keypair::decode(&mut kp_bytes.clone()).unwrap(); + + assert_eq!(kp_bytes, kp1.to_bytes()); + assert_eq!(kp_bytes, kp2.encode()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + let sig3 = kp3.sign(msg); + let sig4 = kp4.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + assert_eq!(sig, sig3); + assert_eq!(sig, sig4); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + let pk3 = kp3.public(); + let pk4 = kp4.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + assert!(pk3.verify(msg, &sig)); + assert!(pk4.verify(msg, &sig)); + } + + #[test] + fn litep2p_kp_to_substrate_kp() { + let kp = litep2p_ed25519::Keypair::generate(); + let kp1: Keypair = kp.clone().into(); + let kp2 = Keypair::try_from_bytes(&mut kp.encode()).unwrap(); + + assert_eq!(kp.encode(), kp1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn libp2p_kp_to_substrate_kp() { + let kp = libp2p_ed25519::Keypair::generate(); + let kp1: Keypair = kp.clone().into(); + let kp2 = Keypair::try_from_bytes(&mut kp.to_bytes()).unwrap(); + + assert_eq!(kp.to_bytes(), kp1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn substrate_pk_to_libs() { + let kp = Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.to_bytes(); + let pk1: libp2p_ed25519::PublicKey = pk.clone().into(); + let pk2: litep2p_ed25519::PublicKey = pk.clone().into(); + let pk3 = libp2p_ed25519::PublicKey::try_from_bytes(&pk_bytes).unwrap(); + let pk4 = litep2p_ed25519::PublicKey::decode(&pk_bytes).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + assert_eq!(pk_bytes, pk2.encode()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + assert!(pk3.verify(msg, &sig)); + assert!(pk4.verify(msg, &sig)); + } + + #[test] + fn litep2p_pk_to_substrate_pk() { + let kp = litep2p_ed25519::Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.clone().encode(); + let pk1: PublicKey = pk.clone().into(); + let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn libp2p_pk_to_substrate_pk() { + let kp = libp2p_ed25519::Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.clone().to_bytes(); + let pk1: PublicKey = pk.clone().into(); + let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn substrate_sk_to_libs() { + let sk = SecretKey::generate(); + let sk_bytes = sk.to_bytes(); + let sk1: libp2p_ed25519::SecretKey = sk.clone().into(); + let sk2: litep2p_ed25519::SecretKey = sk.clone().into(); + let sk3 = libp2p_ed25519::SecretKey::try_from_bytes(&mut sk_bytes.clone()).unwrap(); + let sk4 = litep2p_ed25519::SecretKey::from_bytes(&mut sk_bytes.clone()).unwrap(); + + let kp: Keypair = sk.into(); + let kp1: libp2p_ed25519::Keypair = sk1.into(); + let kp2: litep2p_ed25519::Keypair = sk2.into(); + let kp3: libp2p_ed25519::Keypair = sk3.into(); + let kp4: litep2p_ed25519::Keypair = sk4.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + assert_eq!(sig, kp3.sign(msg)); + assert_eq!(sig, kp4.sign(msg)); + } + + #[test] + fn litep2p_sk_to_substrate_sk() { + let sk = litep2p_ed25519::SecretKey::generate(); + let sk1: SecretKey = sk.clone().into(); + let sk2 = SecretKey::try_from_bytes(&mut sk.to_bytes()).unwrap(); + + let kp: litep2p_ed25519::Keypair = sk.into(); + let kp1: Keypair = sk1.into(); + let kp2: Keypair = sk2.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + } + + #[test] + fn libp2p_sk_to_substrate_sk() { + let sk = libp2p_ed25519::SecretKey::generate(); + let sk_bytes = sk.as_ref().to_owned(); + let sk1: SecretKey = sk.clone().into(); + let sk2 = SecretKey::try_from_bytes(sk_bytes).unwrap(); + + let kp: libp2p_ed25519::Keypair = sk.into(); + let kp1: Keypair = sk1.into(); + let kp2: Keypair = sk2.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + } +} diff --git a/substrate/client/network/types/src/lib.rs b/substrate/client/network/types/src/lib.rs index 9a126c48c7eab66ab39dd55a081a3a938aa16b92..5684e38ab2e8474e171a24260a63c22fcc30694c 100644 --- a/substrate/client/network/types/src/lib.rs +++ b/substrate/client/network/types/src/lib.rs @@ -13,6 +13,12 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -mod peer_id; +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pub mod ed25519; +pub mod multiaddr; +pub mod multihash; +mod peer_id; pub use peer_id::PeerId; diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs new file mode 100644 index 0000000000000000000000000000000000000000..312bef9baab1254a963d5d886994d0812ea93382 --- /dev/null +++ b/substrate/client/network/types/src/multiaddr.rs @@ -0,0 +1,251 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use litep2p::types::multiaddr::{ + Error as LiteP2pError, Iter as LiteP2pIter, Multiaddr as LiteP2pMultiaddr, + Protocol as LiteP2pProtocol, +}; +use std::{ + fmt::{self, Debug, Display}, + str::FromStr, +}; + +mod protocol; +pub use protocol::Protocol; + +// Re-export the macro under shorter name under `multiaddr`. +pub use crate::build_multiaddr as multiaddr; + +/// [`Multiaddr`] type used in Substrate. Converted to libp2p's `Multiaddr` +/// or litep2p's `Multiaddr` when passed to the corresponding network backend. + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub struct Multiaddr { + multiaddr: LiteP2pMultiaddr, +} + +impl Multiaddr { + /// Create a new, empty multiaddress. + pub fn empty() -> Self { + Self { multiaddr: LiteP2pMultiaddr::empty() } + } + + /// Adds an address component to the end of this multiaddr. + pub fn push(&mut self, p: Protocol<'_>) { + self.multiaddr.push(p.into()) + } + + /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty. + pub fn pop<'a>(&mut self) -> Option> { + self.multiaddr.pop().map(Into::into) + } + + /// Like [`Multiaddr::push`] but consumes `self`. + pub fn with(self, p: Protocol<'_>) -> Self { + self.multiaddr.with(p.into()).into() + } + + /// Returns the components of this multiaddress. + pub fn iter(&self) -> Iter<'_> { + self.multiaddr.iter().into() + } + + /// Return a copy of this [`Multiaddr`]'s byte representation. + pub fn to_vec(&self) -> Vec { + self.multiaddr.to_vec() + } +} + +impl Display for Multiaddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.multiaddr, f) + } +} + +/// Remove an extra layer of nestedness by deferring to the wrapped value's [`Debug`]. +impl Debug for Multiaddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.multiaddr, f) + } +} + +impl AsRef<[u8]> for Multiaddr { + fn as_ref(&self) -> &[u8] { + self.multiaddr.as_ref() + } +} + +impl From for Multiaddr { + fn from(multiaddr: LiteP2pMultiaddr) -> Self { + Self { multiaddr } + } +} + +impl From for LiteP2pMultiaddr { + fn from(multiaddr: Multiaddr) -> Self { + multiaddr.multiaddr + } +} + +impl TryFrom> for Multiaddr { + type Error = ParseError; + + fn try_from(v: Vec) -> Result { + let multiaddr = LiteP2pMultiaddr::try_from(v)?; + Ok(Self { multiaddr }) + } +} + +/// Error when parsing a [`Multiaddr`] from string. +#[derive(Debug, thiserror::Error)] +pub enum ParseError { + /// Less data provided than indicated by length. + #[error("less data than indicated by length")] + DataLessThanLen, + /// Invalid multiaddress. + #[error("invalid multiaddress")] + InvalidMultiaddr, + /// Invalid protocol specification. + #[error("invalid protocol string")] + InvalidProtocolString, + /// Unknown protocol string identifier. + #[error("unknown protocol '{0}'")] + UnknownProtocolString(String), + /// Unknown protocol numeric id. + #[error("unknown protocol id {0}")] + UnknownProtocolId(u32), + /// Failed to decode unsigned varint. + #[error("failed to decode unsigned varint: {0}")] + InvalidUvar(Box), + /// Other error emitted when parsing into the wrapped type. + #[error("multiaddr parsing error: {0}")] + ParsingError(Box), +} + +impl From for ParseError { + fn from(error: LiteP2pError) -> Self { + match error { + LiteP2pError::DataLessThanLen => ParseError::DataLessThanLen, + LiteP2pError::InvalidMultiaddr => ParseError::InvalidMultiaddr, + LiteP2pError::InvalidProtocolString => ParseError::InvalidProtocolString, + LiteP2pError::UnknownProtocolString(s) => ParseError::UnknownProtocolString(s), + LiteP2pError::UnknownProtocolId(n) => ParseError::UnknownProtocolId(n), + LiteP2pError::InvalidUvar(e) => ParseError::InvalidUvar(Box::new(e)), + LiteP2pError::ParsingError(e) => ParseError::ParsingError(e), + error => ParseError::ParsingError(Box::new(error)), + } + } +} + +impl FromStr for Multiaddr { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + let multiaddr = LiteP2pMultiaddr::from_str(s)?; + Ok(Self { multiaddr }) + } +} + +impl TryFrom for Multiaddr { + type Error = ParseError; + + fn try_from(s: String) -> Result { + Self::from_str(&s) + } +} + +impl<'a> TryFrom<&'a str> for Multiaddr { + type Error = ParseError; + + fn try_from(s: &'a str) -> Result { + Self::from_str(s) + } +} + +/// Iterator over `Multiaddr` [`Protocol`]s. +pub struct Iter<'a>(LiteP2pIter<'a>); + +impl<'a> Iterator for Iter<'a> { + type Item = Protocol<'a>; + + fn next(&mut self) -> Option { + self.0.next().map(Into::into) + } +} + +impl<'a> From> for Iter<'a> { + fn from(iter: LiteP2pIter<'a>) -> Self { + Self(iter) + } +} + +impl<'a> IntoIterator for &'a Multiaddr { + type Item = Protocol<'a>; + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Iter<'a> { + self.multiaddr.into_iter().into() + } +} + +impl<'a> FromIterator> for Multiaddr { + fn from_iter(iter: T) -> Self + where + T: IntoIterator>, + { + LiteP2pMultiaddr::from_iter(iter.into_iter().map(Into::into)).into() + } +} + +impl<'a> From> for Multiaddr { + fn from(p: Protocol<'a>) -> Multiaddr { + let protocol: LiteP2pProtocol = p.into(); + let multiaddr: LiteP2pMultiaddr = protocol.into(); + multiaddr.into() + } +} + +/// Easy way for a user to create a `Multiaddr`. +/// +/// Example: +/// +/// ```rust +/// use sc_network_types::build_multiaddr; +/// let addr = build_multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16)); +/// ``` +/// +/// Each element passed to `multiaddr!` should be a variant of the `Protocol` enum. The +/// optional parameter is turned into the proper type with the `Into` trait. +/// +/// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`. +#[macro_export] +macro_rules! build_multiaddr { + ($($comp:ident $(($param:expr))*),+) => { + { + use std::iter; + let elem = iter::empty::<$crate::multiaddr::Protocol>(); + $( + let elem = { + let cmp = $crate::multiaddr::Protocol::$comp $(( $param.into() ))*; + elem.chain(iter::once(cmp)) + }; + )+ + elem.collect::<$crate::multiaddr::Multiaddr>() + } + } +} diff --git a/substrate/client/network/types/src/multiaddr/protocol.rs b/substrate/client/network/types/src/multiaddr/protocol.rs new file mode 100644 index 0000000000000000000000000000000000000000..800d08fe36bd657b855869bcb69a808961e32a5a --- /dev/null +++ b/substrate/client/network/types/src/multiaddr/protocol.rs @@ -0,0 +1,138 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::multihash::Multihash; +use litep2p::types::multiaddr::Protocol as LiteP2pProtocol; +use std::{ + borrow::Cow, + net::{Ipv4Addr, Ipv6Addr}, +}; + +/// [`Protocol`] describes all possible multiaddress protocols. +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum Protocol<'a> { + Dccp(u16), + Dns(Cow<'a, str>), + Dns4(Cow<'a, str>), + Dns6(Cow<'a, str>), + Dnsaddr(Cow<'a, str>), + Http, + Https, + Ip4(Ipv4Addr), + Ip6(Ipv6Addr), + P2pWebRtcDirect, + P2pWebRtcStar, + WebRTC, + Certhash(Multihash), + P2pWebSocketStar, + /// Contains the "port" to contact. Similar to TCP or UDP, 0 means "assign me a port". + Memory(u64), + Onion(Cow<'a, [u8; 10]>, u16), + Onion3(Cow<'a, [u8; 35]>, u16), + P2p(Multihash), + P2pCircuit, + Quic, + QuicV1, + Sctp(u16), + Tcp(u16), + Tls, + Noise, + Udp(u16), + Udt, + Unix(Cow<'a, str>), + Utp, + Ws(Cow<'a, str>), + Wss(Cow<'a, str>), +} + +impl<'a> From> for Protocol<'a> { + fn from(protocol: LiteP2pProtocol<'a>) -> Self { + match protocol { + LiteP2pProtocol::Dccp(port) => Protocol::Dccp(port), + LiteP2pProtocol::Dns(str) => Protocol::Dns(str), + LiteP2pProtocol::Dns4(str) => Protocol::Dns4(str), + LiteP2pProtocol::Dns6(str) => Protocol::Dns6(str), + LiteP2pProtocol::Dnsaddr(str) => Protocol::Dnsaddr(str), + LiteP2pProtocol::Http => Protocol::Http, + LiteP2pProtocol::Https => Protocol::Https, + LiteP2pProtocol::Ip4(ipv4_addr) => Protocol::Ip4(ipv4_addr), + LiteP2pProtocol::Ip6(ipv6_addr) => Protocol::Ip6(ipv6_addr), + LiteP2pProtocol::P2pWebRtcDirect => Protocol::P2pWebRtcDirect, + LiteP2pProtocol::P2pWebRtcStar => Protocol::P2pWebRtcStar, + LiteP2pProtocol::WebRTC => Protocol::WebRTC, + LiteP2pProtocol::Certhash(multihash) => Protocol::Certhash(multihash.into()), + LiteP2pProtocol::P2pWebSocketStar => Protocol::P2pWebSocketStar, + LiteP2pProtocol::Memory(port) => Protocol::Memory(port), + LiteP2pProtocol::Onion(str, port) => Protocol::Onion(str, port), + LiteP2pProtocol::Onion3(addr) => + Protocol::Onion3(Cow::Owned(*addr.hash()), addr.port()), + LiteP2pProtocol::P2p(multihash) => Protocol::P2p(multihash.into()), + LiteP2pProtocol::P2pCircuit => Protocol::P2pCircuit, + LiteP2pProtocol::Quic => Protocol::Quic, + LiteP2pProtocol::QuicV1 => Protocol::QuicV1, + LiteP2pProtocol::Sctp(port) => Protocol::Sctp(port), + LiteP2pProtocol::Tcp(port) => Protocol::Tcp(port), + LiteP2pProtocol::Tls => Protocol::Tls, + LiteP2pProtocol::Noise => Protocol::Noise, + LiteP2pProtocol::Udp(port) => Protocol::Udp(port), + LiteP2pProtocol::Udt => Protocol::Udt, + LiteP2pProtocol::Unix(str) => Protocol::Unix(str), + LiteP2pProtocol::Utp => Protocol::Utp, + LiteP2pProtocol::Ws(str) => Protocol::Ws(str), + LiteP2pProtocol::Wss(str) => Protocol::Wss(str), + } + } +} + +impl<'a> From> for LiteP2pProtocol<'a> { + fn from(protocol: Protocol<'a>) -> Self { + match protocol { + Protocol::Dccp(port) => LiteP2pProtocol::Dccp(port), + Protocol::Dns(str) => LiteP2pProtocol::Dns(str), + Protocol::Dns4(str) => LiteP2pProtocol::Dns4(str), + Protocol::Dns6(str) => LiteP2pProtocol::Dns6(str), + Protocol::Dnsaddr(str) => LiteP2pProtocol::Dnsaddr(str), + Protocol::Http => LiteP2pProtocol::Http, + Protocol::Https => LiteP2pProtocol::Https, + Protocol::Ip4(ipv4_addr) => LiteP2pProtocol::Ip4(ipv4_addr), + Protocol::Ip6(ipv6_addr) => LiteP2pProtocol::Ip6(ipv6_addr), + Protocol::P2pWebRtcDirect => LiteP2pProtocol::P2pWebRtcDirect, + Protocol::P2pWebRtcStar => LiteP2pProtocol::P2pWebRtcStar, + Protocol::WebRTC => LiteP2pProtocol::WebRTC, + Protocol::Certhash(multihash) => LiteP2pProtocol::Certhash(multihash.into()), + Protocol::P2pWebSocketStar => LiteP2pProtocol::P2pWebSocketStar, + Protocol::Memory(port) => LiteP2pProtocol::Memory(port), + Protocol::Onion(str, port) => LiteP2pProtocol::Onion(str, port), + Protocol::Onion3(str, port) => LiteP2pProtocol::Onion3((str.into_owned(), port).into()), + Protocol::P2p(multihash) => LiteP2pProtocol::P2p(multihash.into()), + Protocol::P2pCircuit => LiteP2pProtocol::P2pCircuit, + Protocol::Quic => LiteP2pProtocol::Quic, + Protocol::QuicV1 => LiteP2pProtocol::QuicV1, + Protocol::Sctp(port) => LiteP2pProtocol::Sctp(port), + Protocol::Tcp(port) => LiteP2pProtocol::Tcp(port), + Protocol::Tls => LiteP2pProtocol::Tls, + Protocol::Noise => LiteP2pProtocol::Noise, + Protocol::Udp(port) => LiteP2pProtocol::Udp(port), + Protocol::Udt => LiteP2pProtocol::Udt, + Protocol::Unix(str) => LiteP2pProtocol::Unix(str), + Protocol::Utp => LiteP2pProtocol::Utp, + Protocol::Ws(str) => LiteP2pProtocol::Ws(str), + Protocol::Wss(str) => LiteP2pProtocol::Wss(str), + } + } +} diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs new file mode 100644 index 0000000000000000000000000000000000000000..91f5b6353a7187e72fb49b1731ed1be6d8319bff --- /dev/null +++ b/substrate/client/network/types/src/multihash.rs @@ -0,0 +1,192 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! [`Multihash`] implemenattion used by substrate. Currently it's a wrapper over +//! multihash used by litep2p, but it can be switched to other implementation if needed. + +use litep2p::types::multihash::{ + Code as LiteP2pCode, Error as LiteP2pError, Multihash as LiteP2pMultihash, MultihashDigest as _, +}; +use std::fmt::{self, Debug}; + +/// Default [`Multihash`] implementations. Only hashes used by substrate are defined. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Code { + /// Identity hasher. + Identity, + /// SHA-256 (32-byte hash size). + Sha2_256, +} + +impl Code { + /// Calculate digest using this [`Code`]'s hashing algorithm. + pub fn digest(&self, input: &[u8]) -> Multihash { + LiteP2pCode::from(*self).digest(input).into() + } +} + +/// Error generated when converting to [`Code`]. +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Invalid multihash size. + #[error("invalid multihash size '{0}'")] + InvalidSize(u64), + /// The multihash code is not supported. + #[error("unsupported multihash code '{0:x}'")] + UnsupportedCode(u64), + /// Catch-all for other errors emitted when converting `u64` code to enum or parsing multihash + /// from bytes. Never generated as of multihash-0.17.0. + #[error("other error: {0}")] + Other(Box), +} + +impl From for Error { + fn from(error: LiteP2pError) -> Self { + match error { + LiteP2pError::InvalidSize(s) => Self::InvalidSize(s), + LiteP2pError::UnsupportedCode(c) => Self::UnsupportedCode(c), + e => Self::Other(Box::new(e)), + } + } +} + +impl From for LiteP2pCode { + fn from(code: Code) -> Self { + match code { + Code::Identity => LiteP2pCode::Identity, + Code::Sha2_256 => LiteP2pCode::Sha2_256, + } + } +} + +impl TryFrom for Code { + type Error = Error; + + fn try_from(code: LiteP2pCode) -> Result { + match code { + LiteP2pCode::Identity => Ok(Code::Identity), + LiteP2pCode::Sha2_256 => Ok(Code::Sha2_256), + _ => Err(Error::UnsupportedCode(code.into())), + } + } +} + +impl TryFrom for Code { + type Error = Error; + + fn try_from(code: u64) -> Result { + match LiteP2pCode::try_from(code) { + Ok(code) => code.try_into(), + Err(e) => Err(e.into()), + } + } +} + +impl From for u64 { + fn from(code: Code) -> Self { + LiteP2pCode::from(code).into() + } +} + +#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] +pub struct Multihash { + multihash: LiteP2pMultihash, +} + +impl Multihash { + /// Multihash code. + pub fn code(&self) -> u64 { + self.multihash.code() + } + + /// Multihash digest. + pub fn digest(&self) -> &[u8] { + self.multihash.digest() + } + + /// Wraps the digest in a multihash. + pub fn wrap(code: u64, input_digest: &[u8]) -> Result { + LiteP2pMultihash::wrap(code, input_digest).map(Into::into).map_err(Into::into) + } + + /// Parses a multihash from bytes. + /// + /// You need to make sure the passed in bytes have the length of 64. + pub fn from_bytes(bytes: &[u8]) -> Result { + LiteP2pMultihash::from_bytes(bytes).map(Into::into).map_err(Into::into) + } + + /// Returns the bytes of a multihash. + pub fn to_bytes(&self) -> Vec { + self.multihash.to_bytes() + } +} + +/// Remove extra layer of nestedness by deferring to the wrapped value's [`Debug`]. +impl Debug for Multihash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.multihash, f) + } +} + +impl From for Multihash { + fn from(multihash: LiteP2pMultihash) -> Self { + Multihash { multihash } + } +} + +impl From for LiteP2pMultihash { + fn from(multihash: Multihash) -> Self { + multihash.multihash + } +} + +// TODO: uncomment this after upgrading `multihash` crate to v0.19.1. +// +// impl From> for Multihash { +// fn from(generic: multihash::MultihashGeneric<64>) -> Self { +// LiteP2pMultihash::wrap(generic.code(), generic.digest()) +// .expect("both have size 64; qed") +// .into() +// } +// } +// +// impl From for multihash::Multihash<64> { +// fn from(multihash: Multihash) -> Self { +// multihash::Multihash::<64>::wrap(multihash.code(), multihash.digest()) +// .expect("both have size 64; qed") +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn code_from_u64() { + assert_eq!(Code::try_from(0x00).unwrap(), Code::Identity); + assert_eq!(Code::try_from(0x12).unwrap(), Code::Sha2_256); + assert!(matches!(Code::try_from(0x01).unwrap_err(), Error::UnsupportedCode(0x01))); + } + + #[test] + fn code_into_u64() { + assert_eq!(u64::from(Code::Identity), 0x00); + assert_eq!(u64::from(Code::Sha2_256), 0x12); + } +} diff --git a/substrate/client/network/types/src/peer_id.rs b/substrate/client/network/types/src/peer_id.rs index 14ac4a1e9aae8028e6197327a9fe7eec633e40b4..076be0a66c7b79ae09b4a31738a1869035181b86 100644 --- a/substrate/client/network/types/src/peer_id.rs +++ b/substrate/client/network/types/src/peer_id.rs @@ -16,8 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use multiaddr::{Multiaddr, Protocol}; -use multihash::{Code, Error, Multihash}; +use crate::{ + multiaddr::{Multiaddr, Protocol}, + multihash::{Code, Error, Multihash}, +}; use rand::Rng; use std::{fmt, hash::Hash, str::FromStr}; @@ -185,7 +187,7 @@ pub enum ParseError { #[error("unsupported multihash code '{0}'")] UnsupportedCode(u64), #[error("invalid multihash")] - InvalidMultihash(#[from] multihash::Error), + InvalidMultihash(#[from] crate::multihash::Error), } impl FromStr for PeerId { diff --git a/substrate/client/offchain/Cargo.toml b/substrate/client/offchain/Cargo.toml index b834241fe5a7e1b92b1683a92689b6d3de2a2995..2944ff7f4f49dd879b35a1ba70b214824fbdd089 100644 --- a/substrate/client/offchain/Cargo.toml +++ b/substrate/client/offchain/Cargo.toml @@ -16,9 +16,9 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" bytes = "1.1" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } fnv = "1.0.6" futures = "0.3.30" futures-timer = "3.0.2" diff --git a/substrate/client/rpc-api/Cargo.toml b/substrate/client/rpc-api/Cargo.toml index 169714d22453d92276b02d949fa86e06862467b4..d8f833e2b8d45eb217fe6f4f9d835038e6167705 100644 --- a/substrate/client/rpc-api/Cargo.toml +++ b/substrate/client/rpc-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["derive"], workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } @@ -28,4 +28,4 @@ sp-core = { path = "../../primitives/core" } sp-rpc = { path = "../../primitives/rpc" } sp-runtime = { path = "../../primitives/runtime" } sp-version = { path = "../../primitives/version" } -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } diff --git a/substrate/client/rpc-servers/Cargo.toml b/substrate/client/rpc-servers/Cargo.toml index bc21b5b1582f95165ff6d529361c85a413fb915e..7837c852a1c9b73992b9a24f911ce7bba937cdab 100644 --- a/substrate/client/rpc-servers/Cargo.toml +++ b/substrate/client/rpc-servers/Cargo.toml @@ -16,14 +16,16 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] +forwarded-header-value = "0.1.1" +futures = "0.3.30" +governor = "0.6.0" +http = "0.2.8" +hyper = "0.14.27" +ip_network = "0.4.1" jsonrpsee = { version = "0.22", features = ["server"] } log = { workspace = true, default-features = true } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } serde_json = { workspace = true, default-features = true } tokio = { version = "1.22.0", features = ["parking_lot"] } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } -tower-http = { version = "0.4.0", features = ["cors"] } tower = { version = "0.4.13", features = ["util"] } -http = "0.2.8" -hyper = "0.14.27" -futures = "0.3.30" -governor = "0.6.0" +tower-http = { version = "0.4.0", features = ["cors"] } diff --git a/substrate/client/rpc-servers/src/lib.rs b/substrate/client/rpc-servers/src/lib.rs index ad4b444c7ff425ea84ba25e756d61854c3a4569e..ba1fcf5e36771008e139bc69ff492eb645e2bcae 100644 --- a/substrate/client/rpc-servers/src/lib.rs +++ b/substrate/client/rpc-servers/src/lib.rs @@ -21,27 +21,28 @@ #![warn(missing_docs)] pub mod middleware; +pub mod utils; use std::{ convert::Infallible, error::Error as StdError, net::SocketAddr, num::NonZeroU32, time::Duration, }; -use http::header::HeaderValue; use hyper::{ server::conn::AddrStream, service::{make_service_fn, service_fn}, }; use jsonrpsee::{ server::{ - middleware::http::{HostFilterLayer, ProxyGetRequestLayer}, - stop_channel, ws, PingConfig, StopHandle, TowerServiceBuilder, + middleware::http::ProxyGetRequestLayer, stop_channel, ws, PingConfig, StopHandle, + TowerServiceBuilder, }, Methods, RpcModule, }; use tokio::net::TcpListener; use tower::Service; -use tower_http::cors::{AllowOrigin, CorsLayer}; +use utils::{build_rpc_api, format_cors, get_proxy_ip, host_filtering, try_into_cors}; +pub use ip_network::IpNetwork; pub use jsonrpsee::{ core::{ id_providers::{RandomIntegerIdProvider, RandomStringIdProvider}, @@ -85,6 +86,10 @@ pub struct Config<'a, M: Send + Sync + 'static> { pub batch_config: BatchRequestConfig, /// Rate limit calls per minute. pub rate_limit: Option, + /// Disable rate limit for certain ips. + pub rate_limit_whitelisted_ips: Vec, + /// Trust proxy headers for rate limiting. + pub rate_limit_trust_proxy_headers: bool, } #[derive(Debug, Clone)] @@ -117,11 +122,13 @@ where tokio_handle, rpc_api, rate_limit, + rate_limit_whitelisted_ips, + rate_limit_trust_proxy_headers, } = config; let std_listener = TcpListener::bind(addrs.as_slice()).await?.into_std()?; let local_addr = std_listener.local_addr().ok(); - let host_filter = hosts_filtering(cors.is_some(), local_addr); + let host_filter = host_filtering(cors.is_some(), local_addr); let http_middleware = tower::ServiceBuilder::new() .option_layer(host_filter) @@ -160,20 +167,39 @@ where stop_handle: stop_handle.clone(), }; - let make_service = make_service_fn(move |_conn: &AddrStream| { + let make_service = make_service_fn(move |addr: &AddrStream| { let cfg = cfg.clone(); + let rate_limit_whitelisted_ips = rate_limit_whitelisted_ips.clone(); + let ip = addr.remote_addr().ip(); async move { let cfg = cfg.clone(); + let rate_limit_whitelisted_ips = rate_limit_whitelisted_ips.clone(); Ok::<_, Infallible>(service_fn(move |req| { + let proxy_ip = + if rate_limit_trust_proxy_headers { get_proxy_ip(&req) } else { None }; + + let rate_limit_cfg = if rate_limit_whitelisted_ips + .iter() + .any(|ips| ips.contains(proxy_ip.unwrap_or(ip))) + { + log::debug!(target: "rpc", "ip={ip}, proxy_ip={:?} is trusted, disabling rate-limit", proxy_ip); + None + } else { + if !rate_limit_whitelisted_ips.is_empty() { + log::debug!(target: "rpc", "ip={ip}, proxy_ip={:?} is not trusted, rate-limit enabled", proxy_ip); + } + rate_limit + }; + let PerConnection { service_builder, metrics, tokio_handle, stop_handle, methods } = cfg.clone(); let is_websocket = ws::is_upgrade_request(&req); let transport_label = if is_websocket { "ws" } else { "http" }; - let middleware_layer = match (metrics, rate_limit) { + let middleware_layer = match (metrics, rate_limit_cfg) { (None, None) => None, (Some(metrics), None) => Some( MiddlewareLayer::new().with_metrics(Metrics::new(metrics, transport_label)), @@ -227,57 +253,3 @@ where Ok(server_handle) } - -fn hosts_filtering(enabled: bool, addr: Option) -> Option { - // If the local_addr failed, fallback to wildcard. - let port = addr.map_or("*".to_string(), |p| p.port().to_string()); - - if enabled { - // NOTE: The listening addresses are whitelisted by default. - let hosts = - [format!("localhost:{port}"), format!("127.0.0.1:{port}"), format!("[::1]:{port}")]; - Some(HostFilterLayer::new(hosts).expect("Valid hosts; qed")) - } else { - None - } -} - -fn build_rpc_api(mut rpc_api: RpcModule) -> RpcModule { - let mut available_methods = rpc_api.method_names().collect::>(); - // The "rpc_methods" is defined below and we want it to be part of the reported methods. - available_methods.push("rpc_methods"); - available_methods.sort(); - - rpc_api - .register_method("rpc_methods", move |_, _| { - serde_json::json!({ - "methods": available_methods, - }) - }) - .expect("infallible all other methods have their own address space; qed"); - - rpc_api -} - -fn try_into_cors( - maybe_cors: Option<&Vec>, -) -> Result> { - if let Some(cors) = maybe_cors { - let mut list = Vec::new(); - for origin in cors { - list.push(HeaderValue::from_str(origin)?); - } - Ok(CorsLayer::new().allow_origin(AllowOrigin::list(list))) - } else { - // allow all cors - Ok(CorsLayer::permissive()) - } -} - -fn format_cors(maybe_cors: Option<&Vec>) -> String { - if let Some(cors) = maybe_cors { - format!("{:?}", cors) - } else { - format!("{:?}", ["*"]) - } -} diff --git a/substrate/client/rpc-servers/src/utils.rs b/substrate/client/rpc-servers/src/utils.rs new file mode 100644 index 0000000000000000000000000000000000000000..d99b8e637d9df3f1322ee8083342f449f958a311 --- /dev/null +++ b/substrate/client/rpc-servers/src/utils.rs @@ -0,0 +1,189 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Substrate RPC server utils. + +use std::{ + error::Error as StdError, + net::{IpAddr, SocketAddr}, + str::FromStr, +}; + +use forwarded_header_value::ForwardedHeaderValue; +use hyper::{ + header::{HeaderName, HeaderValue}, + Request, +}; +use jsonrpsee::{server::middleware::http::HostFilterLayer, RpcModule}; +use tower_http::cors::{AllowOrigin, CorsLayer}; + +const X_FORWARDED_FOR: HeaderName = HeaderName::from_static("x-forwarded-for"); +const X_REAL_IP: HeaderName = HeaderName::from_static("x-real-ip"); +const FORWARDED: HeaderName = HeaderName::from_static("forwarded"); + +pub(crate) fn host_filtering(enabled: bool, addr: Option) -> Option { + // If the local_addr failed, fallback to wildcard. + let port = addr.map_or("*".to_string(), |p| p.port().to_string()); + + if enabled { + // NOTE: The listening addresses are whitelisted by default. + let hosts = + [format!("localhost:{port}"), format!("127.0.0.1:{port}"), format!("[::1]:{port}")]; + Some(HostFilterLayer::new(hosts).expect("Valid hosts; qed")) + } else { + None + } +} + +pub(crate) fn build_rpc_api(mut rpc_api: RpcModule) -> RpcModule { + let mut available_methods = rpc_api.method_names().collect::>(); + // The "rpc_methods" is defined below and we want it to be part of the reported methods. + available_methods.push("rpc_methods"); + available_methods.sort(); + + rpc_api + .register_method("rpc_methods", move |_, _| { + serde_json::json!({ + "methods": available_methods, + }) + }) + .expect("infallible all other methods have their own address space; qed"); + + rpc_api +} + +pub(crate) fn try_into_cors( + maybe_cors: Option<&Vec>, +) -> Result> { + if let Some(cors) = maybe_cors { + let mut list = Vec::new(); + for origin in cors { + list.push(HeaderValue::from_str(origin)?); + } + Ok(CorsLayer::new().allow_origin(AllowOrigin::list(list))) + } else { + // allow all cors + Ok(CorsLayer::permissive()) + } +} + +pub(crate) fn format_cors(maybe_cors: Option<&Vec>) -> String { + if let Some(cors) = maybe_cors { + format!("{:?}", cors) + } else { + format!("{:?}", ["*"]) + } +} + +/// Extracts the IP addr from the HTTP request. +/// +/// It is extracted in the following order: +/// 1. `Forwarded` header. +/// 2. `X-Forwarded-For` header. +/// 3. `X-Real-Ip`. +pub(crate) fn get_proxy_ip(req: &Request) -> Option { + if let Some(ip) = req + .headers() + .get(&FORWARDED) + .and_then(|v| v.to_str().ok()) + .and_then(|v| ForwardedHeaderValue::from_forwarded(v).ok()) + .and_then(|v| v.remotest_forwarded_for_ip()) + { + return Some(ip); + } + + if let Some(ip) = req + .headers() + .get(&X_FORWARDED_FOR) + .and_then(|v| v.to_str().ok()) + .and_then(|v| ForwardedHeaderValue::from_x_forwarded_for(v).ok()) + .and_then(|v| v.remotest_forwarded_for_ip()) + { + return Some(ip); + } + + if let Some(ip) = req + .headers() + .get(&X_REAL_IP) + .and_then(|v| v.to_str().ok()) + .and_then(|v| IpAddr::from_str(v).ok()) + { + return Some(ip); + } + + None +} + +#[cfg(test)] +mod tests { + use super::*; + use hyper::header::HeaderValue; + + fn request() -> hyper::Request { + hyper::Request::builder().body(hyper::Body::empty()).unwrap() + } + + #[test] + fn empty_works() { + let req = request(); + let host = get_proxy_ip(&req); + assert!(host.is_none()) + } + + #[test] + fn host_from_x_real_ip() { + let mut req = request(); + + req.headers_mut().insert(&X_REAL_IP, HeaderValue::from_static("127.0.0.1")); + let ip = get_proxy_ip(&req); + assert_eq!(Some(IpAddr::from_str("127.0.0.1").unwrap()), ip); + } + + #[test] + fn ip_from_forwarded_works() { + let mut req = request(); + + req.headers_mut().insert( + &FORWARDED, + HeaderValue::from_static("for=192.0.2.60;proto=http;by=203.0.113.43;host=example.com"), + ); + let ip = get_proxy_ip(&req); + assert_eq!(Some(IpAddr::from_str("192.0.2.60").unwrap()), ip); + } + + #[test] + fn ip_from_forwarded_multiple() { + let mut req = request(); + + req.headers_mut().append(&FORWARDED, HeaderValue::from_static("for=127.0.0.1")); + req.headers_mut().append(&FORWARDED, HeaderValue::from_static("for=192.0.2.60")); + req.headers_mut().append(&FORWARDED, HeaderValue::from_static("for=192.0.2.61")); + let ip = get_proxy_ip(&req); + assert_eq!(Some(IpAddr::from_str("127.0.0.1").unwrap()), ip); + } + + #[test] + fn ip_from_x_forwarded_works() { + let mut req = request(); + + req.headers_mut() + .insert(&X_FORWARDED_FOR, HeaderValue::from_static("127.0.0.1,192.0.2.60,0.0.0.1")); + let ip = get_proxy_ip(&req); + assert_eq!(Some(IpAddr::from_str("127.0.0.1").unwrap()), ip); + } +} diff --git a/substrate/client/rpc-spec-v2/Cargo.toml b/substrate/client/rpc-spec-v2/Cargo.toml index f2fc7bee6e203d963cb30dd531563a67f4241feb..8977c842d03806c50372fc58452d5c35206ae163 100644 --- a/substrate/client/rpc-spec-v2/Cargo.toml +++ b/substrate/client/rpc-spec-v2/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } # Internal chain structures for "chain_spec". sc-chain-spec = { path = "../chain-spec" } # Pool for submitting extrinsics required by "transaction" @@ -30,7 +30,7 @@ sp-version = { path = "../../primitives/version" } sc-client-api = { path = "../api" } sc-utils = { path = "../utils" } sc-rpc = { path = "../rpc" } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } thiserror = { workspace = true } serde = { workspace = true, default-features = true } hex = "0.4" @@ -38,7 +38,7 @@ futures = "0.3.30" parking_lot = "0.12.1" tokio-stream = { version = "0.1.14", features = ["sync"] } tokio = { version = "1.22.0", features = ["sync"] } -array-bytes = "6.1" +array-bytes = "6.2.2" log = { workspace = true, default-features = true } futures-util = { version = "0.3.30", default-features = false } rand = "0.8.5" diff --git a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs index 3495d9e54490c0214c75359843ce0bbf42aa5465..a6edc344bc63fda4cb04caa21dfd20b2df8bd0ad 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs @@ -864,7 +864,7 @@ mod tests { Arc>>, ) { let backend = Arc::new(sc_client_api::in_mem::Backend::new()); - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = substrate_test_runtime_client::WasmExecutor::default(); let client_config = sc_service::ClientConfig::default(); let genesis_block_builder = sc_service::GenesisBlockBuilder::new( &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), diff --git a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs index 4bab2194e082acf65e47bd0a3917ee23c2a81884..b195e05b6649abb524c973b350b52833a34fd794 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs @@ -16,13 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use super::*; use crate::{ chain_head::{api::ChainHeadApiClient, event::MethodResponse, test_utils::ChainHeadMockClient}, common::events::{StorageQuery, StorageQueryType, StorageResultType}, hex_string, }; - -use super::*; use assert_matches::assert_matches; use codec::{Decode, Encode}; use futures::Future; @@ -32,7 +31,6 @@ use jsonrpsee::{ }, rpc_params, MethodsError as Error, RpcModule, }; - use sc_block_builder::BlockBuilderBuilder; use sc_client_api::ChildInfo; use sc_service::client::new_in_mem; @@ -2489,6 +2487,7 @@ async fn follow_report_multiple_pruned_block() { client.finalize_block(block_3_hash, None).unwrap(); // Finalizing block 3 directly will also result in block 1 and 2 being finalized. + // It will also mark block 2 and block 3 from the fork as pruned. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Finalized(Finalized { finalized_block_hashes: vec![ @@ -2496,7 +2495,7 @@ async fn follow_report_multiple_pruned_block() { format!("{:?}", block_2_hash), format!("{:?}", block_3_hash), ], - pruned_block_hashes: vec![], + pruned_block_hashes: vec![format!("{:?}", block_2_f_hash), format!("{:?}", block_3_f_hash)], }); assert_eq!(event, expected); @@ -2506,7 +2505,6 @@ async fn follow_report_multiple_pruned_block() { // ^^^ finalized // -> block 1 -> block 2_f -> block 3_f // - // Mark block 4 as finalized to force block 2_f and 3_f to get pruned. let block_4 = BlockBuilderBuilder::new(&*client) .on_parent_block(block_3.hash()) @@ -2537,11 +2535,11 @@ async fn follow_report_multiple_pruned_block() { }); assert_eq!(event, expected); - // Block 4 and 5 be reported as pruned, not just the stale head (block 5). + // Blocks from the fork were pruned earlier. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Finalized(Finalized { finalized_block_hashes: vec![format!("{:?}", block_4_hash)], - pruned_block_hashes: vec![format!("{:?}", block_2_f_hash), format!("{:?}", block_3_f_hash)], + pruned_block_hashes: vec![], }); assert_eq!(event, expected); } @@ -2550,7 +2548,7 @@ async fn follow_report_multiple_pruned_block() { async fn pin_block_references() { // Manually construct an in-memory backend and client. let backend = Arc::new(sc_client_api::in_mem::Backend::new()); - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = substrate_test_runtime_client::WasmExecutor::default(); let client_config = sc_service::ClientConfig::default(); let genesis_block_builder = sc_service::GenesisBlockBuilder::new( @@ -3716,16 +3714,8 @@ async fn follow_unique_pruned_blocks() { // The chainHead will see block 5 as the best block. However, the // client will finalize the block 6, which is on another fork. // - // When the block 6 is finalized, block 2 block 3 block 4 and block 5 are placed on an invalid - // fork. However, pruning of blocks happens on level N - 1. - // Therefore, no pruned blocks are reported yet. + // When the block 6 is finalized all blocks from the stale forks (2, 3, 4, 5) are pruned. // - // When the block 7 is finalized, block 3 is detected as stale. At this step, block 2 and 3 - // are reported as pruned. - // - // When the block 8 is finalized, block 5 block 4 and block 2 are detected as stale. However, - // only blocks 5 and 4 are reported as pruned. This is because the block 2 was previously - // reported. // Initial setup steps: let block_1_hash = @@ -3778,16 +3768,33 @@ async fn follow_unique_pruned_blocks() { }); assert_eq!(event, expected); - // Block 2 must be reported as pruned, even if it was the previous best. - let event: FollowEvent = get_next_event(&mut sub).await; + // All blocks from stale forks are pruned when we finalize block 6. + let mut event: FollowEvent = get_next_event(&mut sub).await; + + // Sort pruned block hashes to counter flaky test caused by event generation (get_pruned_hashes) + if let FollowEvent::Finalized(Finalized { pruned_block_hashes, .. }) = &mut event { + pruned_block_hashes.sort(); + } + let expected_pruned_block_hashes = { + let mut hashes = vec![ + format!("{:?}", block_2_hash), + format!("{:?}", block_3_hash), + format!("{:?}", block_4_hash), + format!("{:?}", block_5_hash), + ]; + hashes.sort(); + hashes + }; + let expected = FollowEvent::Finalized(Finalized { finalized_block_hashes: vec![ format!("{:?}", block_1_hash), format!("{:?}", block_2_f_hash), format!("{:?}", block_6_hash), ], - pruned_block_hashes: vec![], + pruned_block_hashes: expected_pruned_block_hashes, }); + assert_eq!(event, expected); // Pruned hash can be unpinned. @@ -3804,9 +3811,10 @@ async fn follow_unique_pruned_blocks() { client.finalize_block(block_7_hash, None).unwrap(); let event: FollowEvent = get_next_event(&mut sub).await; + // All necessary blocks were pruned on block 6 finalization. let expected = FollowEvent::Finalized(Finalized { finalized_block_hashes: vec![format!("{:?}", block_7_hash)], - pruned_block_hashes: vec![format!("{:?}", block_2_hash), format!("{:?}", block_3_hash)], + pruned_block_hashes: vec![], }); assert_eq!(event, expected); @@ -3817,10 +3825,11 @@ async fn follow_unique_pruned_blocks() { // Finalize the block 8. client.finalize_block(block_8_hash, None).unwrap(); + // All necessary blocks were pruned on block 6 finalization. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Finalized(Finalized { finalized_block_hashes: vec![format!("{:?}", block_8_hash)], - pruned_block_hashes: vec![format!("{:?}", block_4_hash), format!("{:?}", block_5_hash)], + pruned_block_hashes: vec![], }); assert_eq!(event, expected); } diff --git a/substrate/client/rpc/Cargo.toml b/substrate/client/rpc/Cargo.toml index dff34215b025c26fa3e6f4fa2949dcd0d2e4203a..7dd46b2ab4c31e7be4168e588a8c95e900cb213a 100644 --- a/substrate/client/rpc/Cargo.toml +++ b/substrate/client/rpc/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" jsonrpsee = { version = "0.22", features = ["server"] } log = { workspace = true, default-features = true } diff --git a/substrate/client/rpc/src/utils.rs b/substrate/client/rpc/src/utils.rs index 6ec48efef846c719db4e009b3a14926db0577d5f..3b5372615e733dba860faa453063548189fc6354 100644 --- a/substrate/client/rpc/src/utils.rs +++ b/substrate/client/rpc/src/utils.rs @@ -143,7 +143,7 @@ async fn inner_pipe_from_stream( // // Process remaining items and terminate. Either::Right((Either::Right((None, pending_fut)), _)) => { - if pending_fut.await.is_err() { + if !pending_fut.is_terminated() && pending_fut.await.is_err() { return; } @@ -231,4 +231,28 @@ mod tests { _ = rx.next().await.unwrap(); assert!(sub.next::().await.is_none()); } + + #[tokio::test] + async fn subscription_is_dropped_when_stream_is_empty() { + let notify_rx = std::sync::Arc::new(tokio::sync::Notify::new()); + let notify_tx = notify_rx.clone(); + + let mut module = RpcModule::new(notify_tx); + module + .register_subscription("sub", "my_sub", "unsub", |_, pending, notify_tx| async move { + // emulate empty stream for simplicity: otherwise we need some mechanism + // to sync buffer and channel send operations + let stream = futures::stream::empty::<()>(); + // this should exit immediately + pipe_from_stream(pending, stream).await; + // notify that the `pipe_from_stream` has returned + notify_tx.notify_one(); + Ok(()) + }) + .unwrap(); + module.subscribe("sub", EmptyServerParams::new(), 1).await.unwrap(); + + // it should fire once `pipe_from_stream` returns + notify_rx.notified().await; + } } diff --git a/substrate/client/service/Cargo.toml b/substrate/client/service/Cargo.toml index b93196e86f1d3674b2894a21783e269831a27656..dfdd485f15c00550119d9aebf8594b33cdba4df1 100644 --- a/substrate/client/service/Cargo.toml +++ b/substrate/client/service/Cargo.toml @@ -63,7 +63,7 @@ sc-chain-spec = { path = "../chain-spec" } sc-client-api = { path = "../api" } sp-api = { path = "../../primitives/api" } sc-client-db = { path = "../db", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } sc-executor = { path = "../executor" } sc-transaction-pool = { path = "../transaction-pool" } sp-transaction-pool = { path = "../../primitives/transaction-pool" } diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index d0d7cba3862409c2df0d71ea9c6758dd83105340..06fc2ea3b3049492c3755603f661dc378797cc6e 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -37,8 +37,8 @@ use sc_client_api::{ use sc_client_db::{Backend, DatabaseSettings}; use sc_consensus::import_queue::ImportQueue; use sc_executor::{ - sp_wasm_interface::HostFunctions, HeapAllocStrategy, NativeElseWasmExecutor, - NativeExecutionDispatch, RuntimeVersionOf, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, + sp_wasm_interface::HostFunctions, HeapAllocStrategy, NativeExecutionDispatch, RuntimeVersionOf, + WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, }; use sc_keystore::LocalKeystore; use sc_network::{ @@ -262,11 +262,15 @@ where Ok((client, backend, keystore_container, task_manager)) } -/// Creates a [`NativeElseWasmExecutor`] according to [`Configuration`]. +/// Creates a [`NativeElseWasmExecutor`](sc_executor::NativeElseWasmExecutor) according to +/// [`Configuration`]. +#[deprecated(note = "Please switch to `new_wasm_executor`. Will be removed at end of 2024.")] +#[allow(deprecated)] pub fn new_native_or_wasm_executor( config: &Configuration, -) -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new_with_wasm_executor(new_wasm_executor(config)) +) -> sc_executor::NativeElseWasmExecutor { + #[allow(deprecated)] + sc_executor::NativeElseWasmExecutor::new_with_wasm_executor(new_wasm_executor(config)) } /// Creates a [`WasmExecutor`] according to [`Configuration`]. diff --git a/substrate/client/service/src/client/call_executor.rs b/substrate/client/service/src/client/call_executor.rs index 86b5c7c61fcd2cbe062784fe53f8e9ba30adf6e0..9da4d2192576909f95428933623a1e3160e1f9ad 100644 --- a/substrate/client/service/src/client/call_executor.rs +++ b/substrate/client/service/src/client/call_executor.rs @@ -337,26 +337,17 @@ mod tests { use super::*; use backend::Backend; use sc_client_api::in_mem; - use sc_executor::{NativeElseWasmExecutor, WasmExecutor}; + use sc_executor::WasmExecutor; use sp_core::{ testing::TaskExecutor, traits::{FetchRuntimeCode, WrappedRuntimeCode}, }; use std::collections::HashMap; - use substrate_test_runtime_client::{runtime, GenesisInit, LocalExecutorDispatch}; - - fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new_with_wasm_executor( - WasmExecutor::builder() - .with_max_runtime_instances(1) - .with_runtime_cache_size(2) - .build(), - ) - } + use substrate_test_runtime_client::{runtime, GenesisInit}; #[test] fn should_get_override_if_exists() { - let executor = executor(); + let executor = WasmExecutor::default(); let overrides = crate::client::wasm_override::dummy_overrides(); let onchain_code = WrappedRuntimeCode(substrate_test_runtime::wasm_binary_unwrap().into()); @@ -425,7 +416,7 @@ mod tests { fn returns_runtime_version_from_substitute() { const SUBSTITUTE_SPEC_NAME: &str = "substitute-spec-name-cool"; - let executor = executor(); + let executor = WasmExecutor::default(); let backend = Arc::new(in_mem::Backend::::new()); diff --git a/substrate/client/service/src/client/client.rs b/substrate/client/service/src/client/client.rs index 35e8b53a09cf2d802a0c4a873f7ecb8099764e83..3c25c233775bea6ed8297d144bcadf823b918e7e 100644 --- a/substrate/client/service/src/client/client.rs +++ b/substrate/client/service/src/client/client.rs @@ -978,8 +978,12 @@ where // The stale heads are the leaves that will be displaced after the // block is finalized. - let stale_heads = - self.backend.blockchain().displaced_leaves_after_finalizing(block_number)?; + let stale_heads = self + .backend + .blockchain() + .displaced_leaves_after_finalizing(hash, block_number)? + .hashes() + .collect(); let header = self .backend diff --git a/substrate/client/service/src/client/wasm_override.rs b/substrate/client/service/src/client/wasm_override.rs index 725c8ab9429aca18998c4e94c467ff5851348a7c..678ae22bec11117ddfbf1815422638625e602085 100644 --- a/substrate/client/service/src/client/wasm_override.rs +++ b/substrate/client/service/src/client/wasm_override.rs @@ -264,24 +264,21 @@ pub fn dummy_overrides() -> WasmOverride { #[cfg(test)] mod tests { use super::*; - use sc_executor::{HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor}; + use sc_executor::{HeapAllocStrategy, WasmExecutor}; use std::fs::{self, File}; - use substrate_test_runtime_client::LocalExecutorDispatch; - - fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::::new_with_wasm_executor( - WasmExecutor::builder() - .with_onchain_heap_alloc_strategy(HeapAllocStrategy::Static {extra_pages: 128}) - .with_offchain_heap_alloc_strategy(HeapAllocStrategy::Static {extra_pages: 128}) - .with_max_runtime_instances(1) - .with_runtime_cache_size(2) - .build() - ) + + fn executor() -> WasmExecutor { + WasmExecutor::builder() + .with_onchain_heap_alloc_strategy(HeapAllocStrategy::Static { extra_pages: 128 }) + .with_offchain_heap_alloc_strategy(HeapAllocStrategy::Static { extra_pages: 128 }) + .with_max_runtime_instances(1) + .with_runtime_cache_size(2) + .build() } fn wasm_test(fun: F) where - F: Fn(&Path, &[u8], &NativeElseWasmExecutor), + F: Fn(&Path, &[u8], &WasmExecutor), { let exec = executor(); let bytes = substrate_test_runtime::wasm_binary_unwrap(); diff --git a/substrate/client/service/src/config.rs b/substrate/client/service/src/config.rs index 59e307d7f93b529f37ab457dd6bfe0b312065444..187e18aa3cace20c9fe9ffe2e9f3fdcbb6658bbd 100644 --- a/substrate/client/service/src/config.rs +++ b/substrate/client/service/src/config.rs @@ -34,6 +34,7 @@ pub use sc_network::{ }, Multiaddr, }; +pub use sc_rpc_server::IpNetwork; pub use sc_telemetry::TelemetryEndpoints; pub use sc_transaction_pool::Options as TransactionPoolOptions; use sp_core::crypto::SecretString; @@ -108,6 +109,10 @@ pub struct Configuration { pub rpc_batch_config: RpcBatchRequestConfig, /// RPC rate limit per minute. pub rpc_rate_limit: Option, + /// RPC rate limit whitelisted ip addresses. + pub rpc_rate_limit_whitelisted_ips: Vec, + /// RPC rate limit trust proxy headers. + pub rpc_rate_limit_trust_proxy_headers: bool, /// Prometheus endpoint configuration. `None` if disabled. pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index e46cfab50a3ebdcb4e6eb8f746ec27751cd77847..a51bb4012d5d8ac0a4fb39e73c5a872a33e5fa7d 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -54,15 +54,17 @@ use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; pub use self::{ builder::{ - build_network, new_client, new_db_backend, new_full_client, new_full_parts, - new_full_parts_record_import, new_full_parts_with_genesis_builder, - new_native_or_wasm_executor, new_wasm_executor, spawn_tasks, BuildNetworkParams, + build_network, gen_rpc_module, init_telemetry, new_client, new_db_backend, new_full_client, + new_full_parts, new_full_parts_record_import, new_full_parts_with_genesis_builder, + new_wasm_executor, propagate_transaction_notifications, spawn_tasks, BuildNetworkParams, KeystoreContainer, NetworkStarter, SpawnTasksParams, TFullBackend, TFullCallExecutor, TFullClient, }, client::{ClientConfig, LocalCallExecutor}, error::Error, }; +#[allow(deprecated)] +pub use builder::new_native_or_wasm_executor; pub use sc_chain_spec::{ construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock, @@ -74,7 +76,7 @@ pub use config::{ }; pub use sc_chain_spec::{ ChainSpec, ChainType, Extension as ChainSpecExtension, GenericChainSpec, NoExtension, - Properties, RuntimeGenesis, + Properties, }; pub use sc_consensus::ImportQueue; @@ -406,6 +408,8 @@ where cors: config.rpc_cors.as_ref(), tokio_handle: config.tokio_handle.clone(), rate_limit: config.rpc_rate_limit, + rate_limit_whitelisted_ips: config.rpc_rate_limit_whitelisted_ips.clone(), + rate_limit_trust_proxy_headers: config.rpc_rate_limit_trust_proxy_headers, }; // TODO: https://github.com/paritytech/substrate/issues/13773 diff --git a/substrate/client/service/test/Cargo.toml b/substrate/client/service/test/Cargo.toml index 2de984689badbacae254c7a596e996baa491dda5..e95e06cee267e68ca4b87f7179c8c66b9de40f61 100644 --- a/substrate/client/service/test/Cargo.toml +++ b/substrate/client/service/test/Cargo.toml @@ -16,11 +16,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-channel = "1.8.0" -array-bytes = "6.1" +array-bytes = "6.2.2" fdlimit = "0.3.0" futures = "0.3.30" log = { workspace = true, default-features = true } -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" parking_lot = "0.12.1" tempfile = "3.1.0" tokio = { version = "1.22.0", features = ["time"] } diff --git a/substrate/client/service/test/src/client/mod.rs b/substrate/client/service/test/src/client/mod.rs index 51dcc4966e58838a4055f59ff033e16010c1d585..6542830c998b3a4f29df2f6a32f9d71c0aee688a 100644 --- a/substrate/client/service/test/src/client/mod.rs +++ b/substrate/client/service/test/src/client/mod.rs @@ -28,6 +28,7 @@ use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, DatabaseSource, Pru use sc_consensus::{ BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, }; +use sc_executor::WasmExecutor; use sc_service::client::{new_in_mem, Client, LocalCallExecutor}; use sp_api::ProvideRuntimeApi; use sp_consensus::{BlockOrigin, Error as ConsensusError, SelectChain}; @@ -42,8 +43,6 @@ use sp_storage::{ChildInfo, StorageKey}; use std::{collections::HashSet, sync::Arc}; use substrate_test_runtime::TestAPI; use substrate_test_runtime_client::{ - new_native_or_wasm_executor, - prelude::*, runtime::{ currency::DOLLARS, genesismap::{insert_genesis_block, GenesisStorageBuilder}, @@ -79,7 +78,7 @@ fn construct_block( StateMachine::new( backend, &mut overlay, - &new_native_or_wasm_executor(), + &WasmExecutor::default(), "Core_initialize_block", &header.encode(), &mut Default::default(), @@ -93,7 +92,7 @@ fn construct_block( StateMachine::new( backend, &mut overlay, - &new_native_or_wasm_executor(), + &WasmExecutor::default(), "BlockBuilder_apply_extrinsic", &tx.encode(), &mut Default::default(), @@ -107,7 +106,7 @@ fn construct_block( let ret_data = StateMachine::new( backend, &mut overlay, - &new_native_or_wasm_executor(), + &WasmExecutor::default(), "BlockBuilder_finalize_block", &[], &mut Default::default(), @@ -175,7 +174,7 @@ fn construct_genesis_should_work_with_native() { let _ = StateMachine::new( &backend, &mut overlay, - &new_native_or_wasm_executor(), + &WasmExecutor::default(), "Core_execute_block", &b1data, &mut Default::default(), @@ -206,7 +205,7 @@ fn construct_genesis_should_work_with_wasm() { let _ = StateMachine::new( &backend, &mut overlay, - &new_native_or_wasm_executor(), + &WasmExecutor::default(), "Core_execute_block", &b1data, &mut Default::default(), @@ -1165,7 +1164,7 @@ fn finalizing_diverged_block_should_trigger_reorg() { // G -> A1 -> A2 // \ - // -> B1 -> B2 + // -> B1 -> B2 -> B3 let mut finality_notifications = client.finality_notification_stream(); @@ -1250,8 +1249,8 @@ fn finalizing_diverged_block_should_trigger_reorg() { ClientExt::finalize_block(&client, b3.hash(), None).unwrap(); - finality_notification_check(&mut finality_notifications, &[b1.hash()], &[]); - finality_notification_check(&mut finality_notifications, &[b2.hash(), b3.hash()], &[a2.hash()]); + finality_notification_check(&mut finality_notifications, &[b1.hash()], &[a2.hash()]); + finality_notification_check(&mut finality_notifications, &[b2.hash(), b3.hash()], &[]); assert!(matches!(finality_notifications.try_recv().unwrap_err(), TryRecvError::Empty)); } @@ -1372,8 +1371,12 @@ fn finality_notifications_content() { // Import and finalize D4 block_on(client.import_as_final(BlockOrigin::Own, d4.clone())).unwrap(); - finality_notification_check(&mut finality_notifications, &[a1.hash(), a2.hash()], &[c1.hash()]); - finality_notification_check(&mut finality_notifications, &[d3.hash(), d4.hash()], &[b2.hash()]); + finality_notification_check( + &mut finality_notifications, + &[a1.hash(), a2.hash()], + &[c1.hash(), b2.hash()], + ); + finality_notification_check(&mut finality_notifications, &[d3.hash(), d4.hash()], &[a3.hash()]); assert!(matches!(finality_notifications.try_recv().unwrap_err(), TryRecvError::Empty)); } @@ -1602,9 +1605,9 @@ fn doesnt_import_blocks_that_revert_finality() { block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap(); ClientExt::finalize_block(&client, a3.hash(), None).unwrap(); - finality_notification_check(&mut finality_notifications, &[a1.hash(), a2.hash()], &[]); + finality_notification_check(&mut finality_notifications, &[a1.hash(), a2.hash()], &[b2.hash()]); - finality_notification_check(&mut finality_notifications, &[a3.hash()], &[b2.hash()]); + finality_notification_check(&mut finality_notifications, &[a3.hash()], &[]); assert!(matches!(finality_notifications.try_recv().unwrap_err(), TryRecvError::Empty)); } @@ -2072,7 +2075,7 @@ fn cleans_up_closed_notification_sinks_on_block_import() { use substrate_test_runtime_client::GenesisInit; let backend = Arc::new(sc_client_api::in_mem::Backend::new()); - let executor = new_native_or_wasm_executor(); + let executor = WasmExecutor::default(); let client_config = sc_service::ClientConfig::default(); let genesis_block_builder = sc_service::GenesisBlockBuilder::new( @@ -2099,11 +2102,7 @@ fn cleans_up_closed_notification_sinks_on_block_import() { type TestClient = Client< in_mem::Backend, - LocalCallExecutor< - Block, - in_mem::Backend, - sc_executor::NativeElseWasmExecutor, - >, + LocalCallExecutor, WasmExecutor>, Block, RuntimeApi, >; diff --git a/substrate/client/service/test/src/lib.rs b/substrate/client/service/test/src/lib.rs index b9abd8446f7dd6b24f12813b6716d4697f2bdf19..e60bd9410c6453594469c21661875334d1501c68 100644 --- a/substrate/client/service/test/src/lib.rs +++ b/substrate/client/service/test/src/lib.rs @@ -31,7 +31,7 @@ use sc_service::{ client::Client, config::{BasePath, DatabaseSource, KeystoreConfig, RpcBatchRequestConfig}, BlocksPruning, ChainSpecExtension, Configuration, Error, GenericChainSpec, Role, - RuntimeGenesis, SpawnTaskHandle, TaskManager, + SpawnTaskHandle, TaskManager, }; use sc_transaction_pool_api::TransactionPool; use sp_blockchain::HeaderBackend; @@ -46,16 +46,16 @@ mod client; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); -struct TestNet { +struct TestNet { runtime: Runtime, authority_nodes: Vec<(usize, F, U, MultiaddrWithPeerId)>, full_nodes: Vec<(usize, F, U, MultiaddrWithPeerId)>, - chain_spec: GenericChainSpec, + chain_spec: GenericChainSpec, base_port: u16, nodes: usize, } -impl Drop for TestNet { +impl Drop for TestNet { fn drop(&mut self) { // Drop the nodes before dropping the runtime, as the runtime otherwise waits for all // futures to be ended and we run into a dead lock. @@ -162,7 +162,7 @@ where } } -impl TestNet +impl TestNet where F: Clone + Send + 'static, U: Clone + Send + 'static, @@ -193,12 +193,9 @@ where } } -fn node_config< - G: RuntimeGenesis + 'static, - E: ChainSpecExtension + Clone + 'static + Send + Sync, ->( +fn node_config( index: usize, - spec: &GenericChainSpec, + spec: &GenericChainSpec, role: Role, tokio_handle: tokio::runtime::Handle, key_seed: Option, @@ -252,6 +249,8 @@ fn node_config< rpc_message_buffer_capacity: Default::default(), rpc_batch_config: RpcBatchRequestConfig::Unlimited, rpc_rate_limit: None, + rpc_rate_limit_whitelisted_ips: Default::default(), + rpc_rate_limit_trust_proxy_headers: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, @@ -270,19 +269,18 @@ fn node_config< } } -impl TestNet +impl TestNet where F: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send + Sync, - G: RuntimeGenesis + 'static, { fn new( temp: &TempDir, - spec: GenericChainSpec, + spec: GenericChainSpec, full: impl Iterator Result<(F, U), Error>>, authorities: impl Iterator Result<(F, U), Error>)>, base_port: u16, - ) -> TestNet { + ) -> TestNet { sp_tracing::try_init_simple(); fdlimit::raise_fd_limit().unwrap(); let runtime = Runtime::new().expect("Error creating tokio runtime"); @@ -363,10 +361,9 @@ fn tempdir_with_prefix(prefix: &str) -> TempDir { .expect("Error creating test dir") } -pub fn connectivity(spec: GenericChainSpec, full_builder: Fb) +pub fn connectivity(spec: GenericChainSpec, full_builder: Fb) where E: ChainSpecExtension + Clone + 'static + Send + Sync, - G: RuntimeGenesis + 'static, Fb: Fn(Configuration) -> Result, F: TestNetNode, { @@ -440,8 +437,8 @@ where } } -pub fn sync( - spec: GenericChainSpec, +pub fn sync( + spec: GenericChainSpec, full_builder: Fb, mut make_block_and_import: B, mut extrinsic_factory: ExF, @@ -452,7 +449,6 @@ pub fn sync( ExF: FnMut(&F, &U) -> ::Extrinsic, U: Clone + Send + 'static, E: ChainSpecExtension + Clone + 'static + Send + Sync, - G: RuntimeGenesis + 'static, { const NUM_FULL_NODES: usize = 10; const NUM_BLOCKS: usize = 512; @@ -511,15 +507,14 @@ pub fn sync( network.run_until_all_full(|_index, service| service.transaction_pool().ready().count() == 1); } -pub fn consensus( - spec: GenericChainSpec, +pub fn consensus( + spec: GenericChainSpec, full_builder: Fb, authorities: impl IntoIterator, ) where Fb: Fn(Configuration) -> Result, F: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send + Sync, - G: RuntimeGenesis + 'static, { const NUM_FULL_NODES: usize = 10; const NUM_BLOCKS: usize = 10; // 10 * 2 sec block production time = ~20 seconds diff --git a/substrate/client/state-db/Cargo.toml b/substrate/client/state-db/Cargo.toml index 400dda20c223443687292315b4974e5125570553..e203eb5a3282fa1ed73c75426b6039f046bef7d7 100644 --- a/substrate/client/state-db/Cargo.toml +++ b/substrate/client/state-db/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } log = { workspace = true, default-features = true } parking_lot = "0.12.1" sp-core = { path = "../../primitives/core" } diff --git a/substrate/client/sync-state-rpc/Cargo.toml b/substrate/client/sync-state-rpc/Cargo.toml index 09dc611caa044debeabce4f15686465535f076ed..d5bdc920f7c9b48991354f5df917a3b3d72c86fa 100644 --- a/substrate/client/sync-state-rpc/Cargo.toml +++ b/substrate/client/sync-state-rpc/Cargo.toml @@ -15,8 +15,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +codec = { package = "parity-scale-codec", version = "3.6.12" } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } serde = { features = ["derive"], workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } thiserror = { workspace = true } diff --git a/substrate/client/telemetry/src/endpoints.rs b/substrate/client/telemetry/src/endpoints.rs index c7a60726a5656108dfb588d96c8ede33bb4de391..c49b114152ae1473a22bd3ef76e808ddfaef6bbd 100644 --- a/substrate/client/telemetry/src/endpoints.rs +++ b/substrate/client/telemetry/src/endpoints.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use sc_network::{multiaddr, Multiaddr}; +use libp2p::multiaddr::{self, Multiaddr}; use serde::{Deserialize, Deserializer, Serialize}; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the diff --git a/substrate/client/telemetry/src/lib.rs b/substrate/client/telemetry/src/lib.rs index f8a201e7611c2fa50a871e663e5f6c21f76ba07a..7e3a4ee8639308bd4678288db583e31c5085af5b 100644 --- a/substrate/client/telemetry/src/lib.rs +++ b/substrate/client/telemetry/src/lib.rs @@ -37,9 +37,9 @@ #![warn(missing_docs)] use futures::{channel::mpsc, prelude::*}; +use libp2p::Multiaddr; use log::{error, warn}; use parking_lot::Mutex; -use sc_network::Multiaddr; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use serde::Serialize; use std::{ diff --git a/substrate/client/telemetry/src/node.rs b/substrate/client/telemetry/src/node.rs index 9b2443799d3deb23967973aa6670c6d92ea0bbfd..0bbdbfb622ef1ba478b62174d277e49ac836ff64 100644 --- a/substrate/client/telemetry/src/node.rs +++ b/substrate/client/telemetry/src/node.rs @@ -18,9 +18,8 @@ use crate::TelemetryPayload; use futures::{channel::mpsc, prelude::*}; -use libp2p::core::transport::Transport; +use libp2p::{core::transport::Transport, Multiaddr}; use rand::Rng as _; -use sc_network::Multiaddr; use std::{ fmt, mem, pin::Pin, diff --git a/substrate/client/tracing/Cargo.toml b/substrate/client/tracing/Cargo.toml index ba1a7c51ab8d837206551b5088f4a6a83640ed65..df674d24c6dd79b36ef7aa7aa36d389a7702678d 100644 --- a/substrate/client/tracing/Cargo.toml +++ b/substrate/client/tracing/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] ansi_term = "0.12.1" is-terminal = "0.4.9" chrono = "0.4.31" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } lazy_static = "1.4.0" libc = "0.2.152" log = { workspace = true, default-features = true } @@ -29,8 +29,8 @@ rustc-hash = "1.1.0" serde = { workspace = true, default-features = true } thiserror = { workspace = true } tracing = "0.1.29" -tracing-log = "0.1.3" -tracing-subscriber = { workspace = true, features = ["parking_lot"] } +tracing-log = "0.2.0" +tracing-subscriber = { workspace = true, features = ["env-filter", "parking_lot"] } sc-client-api = { path = "../api" } sc-tracing-proc-macro = { path = "proc-macro" } sp-api = { path = "../../primitives/api" } @@ -41,7 +41,7 @@ sp-runtime = { path = "../../primitives/runtime" } sp-tracing = { path = "../../primitives/tracing" } [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" tracing-subscriber = { workspace = true, features = ["chrono", "parking_lot"] } [[bench]] diff --git a/substrate/client/tracing/src/logging/mod.rs b/substrate/client/tracing/src/logging/mod.rs index 8b2ad9b598b5be905ccb97c15817f249022f2b78..05ec9fcf6ef08bc06a77a9f543322d57dc091400 100644 --- a/substrate/client/tracing/src/logging/mod.rs +++ b/substrate/client/tracing/src/logging/mod.rs @@ -141,6 +141,14 @@ where .add_directive( parse_default_directive("libp2p_mdns::behaviour::iface=off") .expect("provided directive is valid"), + ) + // Disable annoying log messages from rustls + .add_directive( + parse_default_directive("rustls::common_state=off") + .expect("provided directive is valid"), + ) + .add_directive( + parse_default_directive("rustls::conn=off").expect("provided directive is valid"), ); if let Ok(lvl) = std::env::var("RUST_LOG") { diff --git a/substrate/client/transaction-pool/Cargo.toml b/substrate/client/transaction-pool/Cargo.toml index e2a0b87eaabb79383299036f92f5b3899b1b4e04..351650297ffc599a0081dff9cf0514dc6c6fc810 100644 --- a/substrate/client/transaction-pool/Cargo.toml +++ b/substrate/client/transaction-pool/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" futures-timer = "3.0.2" linked-hash-map = "0.5.4" @@ -38,9 +38,9 @@ sp-tracing = { path = "../../primitives/tracing" } sp-transaction-pool = { path = "../../primitives/transaction-pool" } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" assert_matches = "1.3.0" -criterion = "0.4.0" +criterion = "0.5.1" sc-block-builder = { path = "../block-builder" } sp-consensus = { path = "../../primitives/consensus/common" } substrate-test-runtime = { path = "../../test-utils/runtime" } diff --git a/substrate/client/transaction-pool/README.md b/substrate/client/transaction-pool/README.md index 7a53727d576103800375a99d0544b3b67efad79e..30a3a8118b5233cd76856f0cf1c2eab6e94a22ed 100644 --- a/substrate/client/transaction-pool/README.md +++ b/substrate/client/transaction-pool/README.md @@ -49,7 +49,7 @@ pool, it's broadcasting status, block inclusion, finality, etc. ## Transaction Validity details -Information retrieved from the the runtime are encapsulated in the `TransactionValidity` +Information retrieved from the runtime are encapsulated in the `TransactionValidity` type. ```rust diff --git a/substrate/client/transaction-pool/api/Cargo.toml b/substrate/client/transaction-pool/api/Cargo.toml index 1bb72ef55442216e321c564838a93a75a44f62eb..be80a7706b3efe653ceaf071f42a4e017bc428db 100644 --- a/substrate/client/transaction-pool/api/Cargo.toml +++ b/substrate/client/transaction-pool/api/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" log = { workspace = true, default-features = true } serde = { features = ["derive"], workspace = true, default-features = true } diff --git a/substrate/frame/Cargo.toml b/substrate/frame/Cargo.toml index ef8d8758f3df12d6f88b58069420f1535379c6b7..3942f06ce6eec966dd2883e679e3cfe570251b35 100644 --- a/substrate/frame/Cargo.toml +++ b/substrate/frame/Cargo.toml @@ -4,10 +4,9 @@ version = "0.1.0" authors = ["Parity Technologies "] edition.workspace = true license = "Apache-2.0" -homepage = "paritytech.github.io" +homepage = "https://paritytech.github.io" repository.workspace = true description = "Experimental: The single package to get you started with building frame pallets and runtimes" -publish = false [lints] workspace = true @@ -19,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # external deps -parity-scale-codec = { version = "3.2.2", default-features = false, features = [ +parity-scale-codec = { version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ @@ -47,10 +46,18 @@ sp-session = { default-features = false, path = "../primitives/session", optiona sp-consensus-aura = { default-features = false, path = "../primitives/consensus/aura", optional = true } sp-consensus-grandpa = { default-features = false, path = "../primitives/consensus/grandpa", optional = true } sp-inherents = { default-features = false, path = "../primitives/inherents", optional = true } +sp-storage = { default-features = false, path = "../primitives/storage", optional = true } frame-executive = { default-features = false, path = "../frame/executive", optional = true } frame-system-rpc-runtime-api = { default-features = false, path = "../frame/system/rpc/runtime-api", optional = true } +# Used for runtime benchmarking +frame-benchmarking = { default-features = false, path = "../frame/benchmarking", optional = true } +frame-system-benchmarking = { default-features = false, path = "../frame/system/benchmarking", optional = true } + +# Used for try-runtime +frame-try-runtime = { default-features = false, path = "../frame/try-runtime", optional = true } + docify = "0.2.8" log = { workspace = true } @@ -68,6 +75,7 @@ runtime = [ "sp-inherents", "sp-offchain", "sp-session", + "sp-storage", "sp-transaction-pool", "sp-version", @@ -75,10 +83,13 @@ runtime = [ "frame-system-rpc-runtime-api", ] std = [ + "frame-benchmarking?/std", "frame-executive?/std", "frame-support/std", + "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api?/std", "frame-system/std", + "frame-try-runtime?/std", "log/std", "parity-scale-codec/std", "scale-info/std", @@ -94,6 +105,22 @@ std = [ "sp-runtime/std", "sp-session?/std", "sp-std/std", + "sp-storage/std", "sp-transaction-pool?/std", "sp-version?/std", ] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-examples/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/alliance/Cargo.toml b/substrate/frame/alliance/Cargo.toml index af1fcb296f6726983c654238dbc2d2161e4eec1a..10e2feba62376d9cd8346f44531dbd3e6bc47870 100644 --- a/substrate/frame/alliance/Cargo.toml +++ b/substrate/frame/alliance/Cargo.toml @@ -16,10 +16,10 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = { version = "6.1", optional = true } +array-bytes = { version = "6.2.2", optional = true } log = { workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-std = { path = "../../primitives/std", default-features = false } @@ -36,7 +36,7 @@ pallet-identity = { path = "../identity", default-features = false } pallet-collective = { path = "../collective", default-features = false, optional = true } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" sp-crypto-hashing = { path = "../../primitives/crypto/hashing", default-features = false } pallet-balances = { path = "../balances" } pallet-collective = { path = "../collective" } diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs index 7116e69efa17ec88134699570b2235b8b0973d7c..a9cfd6d0fde0eb149e4f33db86823e7e711426cd 100644 --- a/substrate/frame/alliance/src/mock.rs +++ b/substrate/frame/alliance/src/mock.rs @@ -42,7 +42,6 @@ type BlockNumber = u64; type AccountId = u64; parameter_types! { - pub const BlockHashCount: BlockNumber = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(Weight::MAX); } diff --git a/substrate/frame/asset-conversion/Cargo.toml b/substrate/frame/asset-conversion/Cargo.toml index cf50d7b22af9b11a82011fe8e23c78ccef1112fa..bfcda2299d5a116eca62a5870a84823876bc89f5 100644 --- a/substrate/frame/asset-conversion/Cargo.toml +++ b/substrate/frame/asset-conversion/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { version = "0.4.20", default-features = false } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } diff --git a/substrate/frame/asset-conversion/ops/Cargo.toml b/substrate/frame/asset-conversion/ops/Cargo.toml index e421e904a3a17933ebeefc3affea7e5d9cc5d702..c5efbf9f6f442b0430cecab10badb4ca13e49d0a 100644 --- a/substrate/frame/asset-conversion/ops/Cargo.toml +++ b/substrate/frame/asset-conversion/ops/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { version = "0.4.20", default-features = false } frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } diff --git a/substrate/frame/asset-conversion/ops/src/lib.rs b/substrate/frame/asset-conversion/ops/src/lib.rs index 6cc7bfa2e9965abb63fb816e0ffecd6b77b5df8a..a655a9cb44525fe58bf07f283c0cf3cdf2c9fd42 100644 --- a/substrate/frame/asset-conversion/ops/src/lib.rs +++ b/substrate/frame/asset-conversion/ops/src/lib.rs @@ -248,6 +248,7 @@ pub mod pallet { T::DepositAsset::burn_from( &depositor, deposit + deposit_asset_ed, + Preservation::Expendable, Precision::Exact, Fortitude::Force, )?; @@ -260,6 +261,7 @@ pub mod pallet { T::DepositAsset::burn_from( &depositor, deposit + deposit_asset_ed, + Preservation::Expendable, Precision::Exact, Fortitude::Force, )?; @@ -272,6 +274,7 @@ pub mod pallet { T::DepositAsset::burn_from( &depositor, deposit + deposit_asset_ed, + Preservation::Expendable, Precision::Exact, Fortitude::Force, )?; diff --git a/substrate/frame/asset-conversion/src/lib.rs b/substrate/frame/asset-conversion/src/lib.rs index bb6e70a7fe9387259a7fdaaa0836032809e677ed..62acb693efb1c1e36bf22ad0530649f796a0d5a7 100644 --- a/substrate/frame/asset-conversion/src/lib.rs +++ b/substrate/frame/asset-conversion/src/lib.rs @@ -596,7 +596,14 @@ pub mod pallet { ); // burn the provided lp token amount that includes the fee - T::PoolAssets::burn_from(pool.lp_token.clone(), &sender, lp_token_burn, Exact, Polite)?; + T::PoolAssets::burn_from( + pool.lp_token.clone(), + &sender, + lp_token_burn, + Expendable, + Exact, + Polite, + )?; T::Assets::transfer(*asset1, &pool_account, &withdraw_to, amount1, Expendable)?; T::Assets::transfer(*asset2, &pool_account, &withdraw_to, amount2, Expendable)?; diff --git a/substrate/frame/asset-rate/Cargo.toml b/substrate/frame/asset-rate/Cargo.toml index cd502148a8d8f116afcbcde8969490a454da81b7..4662469e46ce423edaab234041a852a42b0711bb 100644 --- a/substrate/frame/asset-rate/Cargo.toml +++ b/substrate/frame/asset-rate/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/assets/Cargo.toml b/substrate/frame/assets/Cargo.toml index ed6df77e15232d7249fdcdb5da41a673ef420994..9647ae4db6baa6ada63350153b8a10993e940401 100644 --- a/substrate/frame/assets/Cargo.toml +++ b/substrate/frame/assets/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-std = { path = "../../primitives/std", default-features = false } diff --git a/substrate/frame/atomic-swap/Cargo.toml b/substrate/frame/atomic-swap/Cargo.toml index c641071df902d0fa78f4794292bacd824f9712bb..8083c12d4b39fb0b860a738f700168bcad0bc2f3 100644 --- a/substrate/frame/atomic-swap/Cargo.toml +++ b/substrate/frame/atomic-swap/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } diff --git a/substrate/frame/aura/Cargo.toml b/substrate/frame/aura/Cargo.toml index 92ff3a0c56589d204cabe9770281f34d30f1eca9..9264d2f4a643cdedd02fa17f81f90d949c2c0729 100644 --- a/substrate/frame/aura/Cargo.toml +++ b/substrate/frame/aura/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/authority-discovery/Cargo.toml b/substrate/frame/authority-discovery/Cargo.toml index a7aba711a5686088241e4507e686683114641bf7..c21f9b5c904556f8a0c01a0e5f1e468e32685ee5 100644 --- a/substrate/frame/authority-discovery/Cargo.toml +++ b/substrate/frame/authority-discovery/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/authority-discovery/src/lib.rs b/substrate/frame/authority-discovery/src/lib.rs index ed9240d99e8d5bb2b814fe80e0211c601378651c..16f71960d693bec3de2babe446470e2db94bb8b9 100644 --- a/substrate/frame/authority-discovery/src/lib.rs +++ b/substrate/frame/authority-discovery/src/lib.rs @@ -48,13 +48,11 @@ pub mod pallet { } #[pallet::storage] - #[pallet::getter(fn keys)] /// Keys of the current authority set. pub(super) type Keys = StorageValue<_, WeakBoundedVec, ValueQuery>; #[pallet::storage] - #[pallet::getter(fn next_keys)] /// Keys of the next authority set. pub(super) type NextKeys = StorageValue<_, WeakBoundedVec, ValueQuery>; diff --git a/substrate/frame/authorship/Cargo.toml b/substrate/frame/authorship/Cargo.toml index 2bfd59a48e10e0cee249d62680e66d7ce426cc3f..dd78e3404ef0b3c30adfa5b24bd4444c2fec10d1 100644 --- a/substrate/frame/authorship/Cargo.toml +++ b/substrate/frame/authorship/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } impl-trait-for-tuples = "0.2.2" diff --git a/substrate/frame/babe/Cargo.toml b/substrate/frame/babe/Cargo.toml index 9f6ef2bc05ea18e96786bd59b697c0290fd2d398..d06b7f7454648ea529595aa91e1e3a0f9e2b5486 100644 --- a/substrate/frame/babe/Cargo.toml +++ b/substrate/frame/babe/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/bags-list/Cargo.toml b/substrate/frame/bags-list/Cargo.toml index 5deb504d0a4f2846748bd0fb4970cfbfdde41733..3429d2f28a6cc7445e383a28e5f817b876251f2b 100644 --- a/substrate/frame/bags-list/Cargo.toml +++ b/substrate/frame/bags-list/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # parity -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/substrate/frame/balances/Cargo.toml b/substrate/frame/balances/Cargo.toml index 1cc9ac5d8fd25c318351ede5e934d1ef93d89db6..4da14aea12809f09c797d0eb0925e1c43bfdc8d6 100644 --- a/substrate/frame/balances/Cargo.toml +++ b/substrate/frame/balances/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/balances/src/benchmarking.rs b/substrate/frame/balances/src/benchmarking.rs index 0ce1240eb5d3987e43f7dba2734cec3b6fbea62a..e4229f2d7f0fafa96260710f218e73dd63832893 100644 --- a/substrate/frame/balances/src/benchmarking.rs +++ b/substrate/frame/balances/src/benchmarking.rs @@ -44,7 +44,7 @@ mod benchmarks { let caller = whitelisted_caller(); // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()).max(1u32.into()); let _ = as Currency<_>>::make_free_balance_be(&caller, balance); // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, @@ -297,6 +297,44 @@ mod benchmarks { assert_eq!(Balances::::total_issuance(), ti + delta); } + /// Benchmark `burn` extrinsic with the worst possible condition - burn kills the account. + #[benchmark] + fn burn_allow_death() { + let existential_deposit = T::ExistentialDeposit::get(); + let caller = whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + let _ = as Currency<_>>::make_free_balance_be(&caller, balance); + + // Burn enough to kill the account. + let burn_amount = balance - existential_deposit + 1u32.into(); + + #[extrinsic_call] + burn(RawOrigin::Signed(caller.clone()), burn_amount, false); + + assert_eq!(Balances::::free_balance(&caller), Zero::zero()); + } + + // Benchmark `burn` extrinsic with the case where account is kept alive. + #[benchmark] + fn burn_keep_alive() { + let existential_deposit = T::ExistentialDeposit::get(); + let caller = whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + let _ = as Currency<_>>::make_free_balance_be(&caller, balance); + + // Burn minimum possible amount which should not kill the account. + let burn_amount = 1u32.into(); + + #[extrinsic_call] + burn(RawOrigin::Signed(caller.clone()), burn_amount, true); + + assert_eq!(Balances::::free_balance(&caller), balance - burn_amount); + } + impl_benchmark_test_suite! { Balances, crate::tests::ExtBuilder::default().build(), diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index bd811955d63c62d0226c9757145ea80a6298ea24..56eb81b49e2db695abbb8d705db7cef21f599416 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -542,8 +542,8 @@ pub mod pallet { #[pallet::hooks] impl, I: 'static> Hooks> for Pallet { - #[cfg(not(feature = "insecure_zero_ed"))] fn integrity_test() { + #[cfg(not(feature = "insecure_zero_ed"))] assert!( !>::ExistentialDeposit::get().is_zero(), "The existential deposit must be greater than zero!" @@ -555,6 +555,29 @@ pub mod pallet { T::MaxFreezes::get(), ::VARIANT_COUNT, ); } + + #[cfg(feature = "try-runtime")] + fn try_state(_n: BlockNumberFor) -> Result<(), sp_runtime::TryRuntimeError> { + Holds::::iter_keys().try_for_each(|k| { + if Holds::::decode_len(k).unwrap_or(0) > + T::RuntimeHoldReason::VARIANT_COUNT as usize + { + Err("Found `Hold` with too many elements") + } else { + Ok(()) + } + })?; + + Freezes::::iter_keys().try_for_each(|k| { + if Freezes::::decode_len(k).unwrap_or(0) > T::MaxFreezes::get() as usize { + Err("Found `Freeze` with too many elements") + } else { + Ok(()) + } + })?; + + Ok(()) + } } #[pallet::call(weight(>::WeightInfo))] @@ -767,6 +790,32 @@ pub mod pallet { Ok(()) } + + /// Burn the specified liquid free balance from the origin account. + /// + /// If the origin's account ends up below the existential deposit as a result + /// of the burn and `keep_alive` is false, the account will be reaped. + /// + /// Unlike sending funds to a _burn_ address, which merely makes the funds inaccessible, + /// this `burn` operation will reduce total issuance by the amount _burned_. + #[pallet::call_index(10)] + #[pallet::weight(if *keep_alive {T::WeightInfo::burn_allow_death() } else {T::WeightInfo::burn_keep_alive()})] + pub fn burn( + origin: OriginFor, + #[pallet::compact] value: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let source = ensure_signed(origin)?; + let preservation = if keep_alive { Preserve } else { Expendable }; + >::burn_from( + &source, + value, + preservation, + Precision::Exact, + Polite, + )?; + Ok(()) + } } impl, I: 'static> Pallet { diff --git a/substrate/frame/balances/src/migration.rs b/substrate/frame/balances/src/migration.rs index 38d9c07ff7e002f6a7a57189b7ebce6830b52c75..568c3fbb7cf0926f9f23b2bdd23d840fa85bad5c 100644 --- a/substrate/frame/balances/src/migration.rs +++ b/substrate/frame/balances/src/migration.rs @@ -91,7 +91,7 @@ impl, I: 'static> OnRuntimeUpgrade for ResetInactive { StorageVersion::new(0).put::>(); log::info!(target: LOG_TARGET, "Storage to version 0"); - T::DbWeight::get().reads_writes(1, 2) + T::DbWeight::get().reads_writes(1, 3) } else { log::info!( target: LOG_TARGET, diff --git a/substrate/frame/balances/src/tests/currency_tests.rs b/substrate/frame/balances/src/tests/currency_tests.rs index 450b1a84aa878552cdd8e9bd38918099b7edb463..9ad4aca64406b8ab1e284bf69d081211d47b37d9 100644 --- a/substrate/frame/balances/src/tests/currency_tests.rs +++ b/substrate/frame/balances/src/tests/currency_tests.rs @@ -701,7 +701,7 @@ fn account_removal_on_free_too_low() { fn burn_must_work() { ExtBuilder::default().monied(true).build_and_execute_with(|| { let init_total_issuance = Balances::total_issuance(); - let imbalance = Balances::burn(10); + let imbalance = >::burn(10); assert_eq!(Balances::total_issuance(), init_total_issuance - 10); drop(imbalance); assert_eq!(Balances::total_issuance(), init_total_issuance); diff --git a/substrate/frame/balances/src/tests/dispatchable_tests.rs b/substrate/frame/balances/src/tests/dispatchable_tests.rs index 4be68f61693b4f1c92b066fc396218a48550632e..4bc96f6b43d97444252f42e4820d97168ed50e1e 100644 --- a/substrate/frame/balances/src/tests/dispatchable_tests.rs +++ b/substrate/frame/balances/src/tests/dispatchable_tests.rs @@ -335,3 +335,47 @@ fn force_adjust_total_issuance_rejects_more_than_inactive() { assert_eq!(Balances::active_issuance(), 10); }); } + +#[test] +fn burn_works() { + ExtBuilder::default().build().execute_with(|| { + // Prepare account with initial balance + let (account, init_balance) = (1, 37); + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account, init_balance)); + let init_issuance = Balances::total_issuance(); + let (keep_alive, allow_death) = (true, false); + + // 1. Cannot burn more than what's available + assert_noop!( + Balances::burn(Some(account).into(), init_balance + 1, allow_death), + TokenError::FundsUnavailable, + ); + + // 2. Burn some funds, without reaping the account + let burn_amount_1 = 1; + assert_ok!(Balances::burn(Some(account).into(), burn_amount_1, allow_death)); + System::assert_last_event(RuntimeEvent::Balances(Event::Burned { + who: account, + amount: burn_amount_1, + })); + assert_eq!(Balances::total_issuance(), init_issuance - burn_amount_1); + assert_eq!(Balances::total_balance(&account), init_balance - burn_amount_1); + + // 3. Cannot burn funds below existential deposit if `keep_alive` is `true` + let burn_amount_2 = + init_balance - burn_amount_1 - ::ExistentialDeposit::get() + 1; + assert_noop!( + Balances::burn(Some(account).into(), init_balance + 1, keep_alive), + TokenError::FundsUnavailable, + ); + + // 4. Burn some more funds, this time reaping the account + assert_ok!(Balances::burn(Some(account).into(), burn_amount_2, allow_death)); + System::assert_last_event(RuntimeEvent::Balances(Event::Burned { + who: account, + amount: burn_amount_2, + })); + assert_eq!(Balances::total_issuance(), init_issuance - burn_amount_1 - burn_amount_2); + assert!(Balances::total_balance(&account).is_zero()); + }); +} diff --git a/substrate/frame/balances/src/tests/general_tests.rs b/substrate/frame/balances/src/tests/general_tests.rs index 0f3e015d0a89242dd321285b84a134bd907702ec..a855fae5616af369776454955bd83ffaa5656303 100644 --- a/substrate/frame/balances/src/tests/general_tests.rs +++ b/substrate/frame/balances/src/tests/general_tests.rs @@ -109,3 +109,35 @@ fn regression_historic_acc_does_not_evaporate_reserve() { }); }); } + +#[cfg(feature = "try-runtime")] +#[test] +fn try_state_works() { + use crate::{Config, Freezes, Holds}; + use frame_support::{ + storage, + traits::{Get, Hooks, VariantCount}, + }; + + ExtBuilder::default().build_and_execute_with(|| { + storage::unhashed::put( + &Holds::::hashed_key_for(1), + &vec![0u8; ::RuntimeHoldReason::VARIANT_COUNT as usize + 1], + ); + + assert!(format!("{:?}", Balances::try_state(0).unwrap_err()) + .contains("Found `Hold` with too many elements")); + }); + + ExtBuilder::default().build_and_execute_with(|| { + let max_freezes: u32 = ::MaxFreezes::get(); + + storage::unhashed::put( + &Freezes::::hashed_key_for(1), + &vec![0u8; max_freezes as usize + 1], + ); + + assert!(format!("{:?}", Balances::try_state(0).unwrap_err()) + .contains("Found `Freeze` with too many elements")); + }); +} diff --git a/substrate/frame/balances/src/weights.rs b/substrate/frame/balances/src/weights.rs index f99fc45107614a96f223f4113e03ed6c6cab4041..e82c97160efcfdac6b994345e0baeb787e69bcb9 100644 --- a/substrate/frame/balances/src/weights.rs +++ b/substrate/frame/balances/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_balances -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/balances/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/balances/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -60,6 +58,8 @@ pub trait WeightInfo { fn force_unreserve() -> Weight; fn upgrade_accounts(u: u32, ) -> Weight; fn force_adjust_total_issuance() -> Weight; + fn burn_allow_death() -> Weight; + fn burn_keep_alive() -> Weight; } /// Weights for `pallet_balances` using the Substrate node and recommended hardware. @@ -71,8 +71,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 50_062_000 picoseconds. - Weight::from_parts(51_214_000, 3593) + // Minimum execution time: 47_552_000 picoseconds. + Weight::from_parts(48_363_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -82,8 +82,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 39_700_000 picoseconds. - Weight::from_parts(40_754_000, 3593) + // Minimum execution time: 37_565_000 picoseconds. + Weight::from_parts(38_159_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -93,8 +93,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 14_939_000 picoseconds. - Weight::from_parts(15_302_000, 3593) + // Minimum execution time: 14_147_000 picoseconds. + Weight::from_parts(14_687_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -104,8 +104,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 20_516_000 picoseconds. - Weight::from_parts(21_179_000, 3593) + // Minimum execution time: 19_188_000 picoseconds. + Weight::from_parts(19_929_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -115,8 +115,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 51_281_000 picoseconds. - Weight::from_parts(52_145_000, 6196) + // Minimum execution time: 48_903_000 picoseconds. + Weight::from_parts(49_944_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -126,8 +126,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 48_988_000 picoseconds. - Weight::from_parts(49_935_000, 3593) + // Minimum execution time: 46_573_000 picoseconds. + Weight::from_parts(47_385_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -137,8 +137,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_594_000 picoseconds. - Weight::from_parts(18_232_000, 3593) + // Minimum execution time: 16_750_000 picoseconds. + Weight::from_parts(17_233_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,10 +149,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_701_000 picoseconds. - Weight::from_parts(16_897_000, 990) - // Standard Error: 11_684 - .saturating_add(Weight::from_parts(14_375_201, 0).saturating_mul(u.into())) + // Minimum execution time: 16_333_000 picoseconds. + Weight::from_parts(16_588_000, 990) + // Standard Error: 12_254 + .saturating_add(Weight::from_parts(13_973_659, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -161,8 +161,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_692_000 picoseconds. - Weight::from_parts(7_140_000, 0) + // Minimum execution time: 6_265_000 picoseconds. + Weight::from_parts(6_594_000, 0) + } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 30_151_000 picoseconds. + Weight::from_parts(30_968_000, 0) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 20_055_000 picoseconds. + Weight::from_parts(20_711_000, 0) } } @@ -174,8 +188,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 50_062_000 picoseconds. - Weight::from_parts(51_214_000, 3593) + // Minimum execution time: 47_552_000 picoseconds. + Weight::from_parts(48_363_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -185,8 +199,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 39_700_000 picoseconds. - Weight::from_parts(40_754_000, 3593) + // Minimum execution time: 37_565_000 picoseconds. + Weight::from_parts(38_159_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -196,8 +210,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 14_939_000 picoseconds. - Weight::from_parts(15_302_000, 3593) + // Minimum execution time: 14_147_000 picoseconds. + Weight::from_parts(14_687_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -207,8 +221,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 20_516_000 picoseconds. - Weight::from_parts(21_179_000, 3593) + // Minimum execution time: 19_188_000 picoseconds. + Weight::from_parts(19_929_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -218,8 +232,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 51_281_000 picoseconds. - Weight::from_parts(52_145_000, 6196) + // Minimum execution time: 48_903_000 picoseconds. + Weight::from_parts(49_944_000, 6196) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -229,8 +243,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 48_988_000 picoseconds. - Weight::from_parts(49_935_000, 3593) + // Minimum execution time: 46_573_000 picoseconds. + Weight::from_parts(47_385_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -240,8 +254,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_594_000 picoseconds. - Weight::from_parts(18_232_000, 3593) + // Minimum execution time: 16_750_000 picoseconds. + Weight::from_parts(17_233_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -252,10 +266,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_701_000 picoseconds. - Weight::from_parts(16_897_000, 990) - // Standard Error: 11_684 - .saturating_add(Weight::from_parts(14_375_201, 0).saturating_mul(u.into())) + // Minimum execution time: 16_333_000 picoseconds. + Weight::from_parts(16_588_000, 990) + // Standard Error: 12_254 + .saturating_add(Weight::from_parts(13_973_659, 0).saturating_mul(u.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -264,7 +278,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_692_000 picoseconds. - Weight::from_parts(7_140_000, 0) + // Minimum execution time: 6_265_000 picoseconds. + Weight::from_parts(6_594_000, 0) + } + fn burn_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 30_151_000 picoseconds. + Weight::from_parts(30_968_000, 0) + } + fn burn_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 20_055_000 picoseconds. + Weight::from_parts(20_711_000, 0) } } diff --git a/substrate/frame/beefy-mmr/Cargo.toml b/substrate/frame/beefy-mmr/Cargo.toml index 8fcb8e1d559bea2c5082e49cc0002d15745639c0..51abc306265d60a3ffc990fb6878831e12593a60 100644 --- a/substrate/frame/beefy-mmr/Cargo.toml +++ b/substrate/frame/beefy-mmr/Cargo.toml @@ -12,8 +12,8 @@ homepage = "https://substrate.io" workspace = true [dependencies] -array-bytes = { version = "6.1", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +array-bytes = { version = "6.2.2", optional = true } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } @@ -32,7 +32,7 @@ sp-api = { path = "../../primitives/api", default-features = false } sp-state-machine = { path = "../../primitives/state-machine", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" sp-staking = { path = "../../primitives/staking" } [features] diff --git a/substrate/frame/beefy/Cargo.toml b/substrate/frame/beefy/Cargo.toml index f181f4d41cdcb2567654d21b0fefb88b507d6f69..890ac1399b9dfcee8d71348d8eac9ff7b3ae2546 100644 --- a/substrate/frame/beefy/Cargo.toml +++ b/substrate/frame/beefy/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://substrate.io" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } serde = { optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/benchmarking/Cargo.toml b/substrate/frame/benchmarking/Cargo.toml index 8210e8cfa626063a32b5528b5469f7029857299f..b5824ab2ec2eeaa2126bd72f6832e87736a8f914 100644 --- a/substrate/frame/benchmarking/Cargo.toml +++ b/substrate/frame/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } linregress = { version = "0.5.1", optional = true } log = { workspace = true } paste = "1.0" @@ -36,7 +36,7 @@ sp-storage = { path = "../../primitives/storage", default-features = false } static_assertions = "1.1.0" [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" rusty-fork = { version = "0.3.0", default-features = false } sp-keystore = { path = "../../primitives/keystore" } diff --git a/substrate/frame/benchmarking/pov/Cargo.toml b/substrate/frame/benchmarking/pov/Cargo.toml index 5d3aaa7890488018eb3715ed13845a7e3d130b50..e4f3c272a63e4938aa2efd6fa30784543383c82a 100644 --- a/substrate/frame/benchmarking/pov/Cargo.toml +++ b/substrate/frame/benchmarking/pov/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "..", default-features = false } frame-support = { path = "../../support", default-features = false } diff --git a/substrate/frame/bounties/Cargo.toml b/substrate/frame/bounties/Cargo.toml index 3307e47e9818934d629ff1989aff08ff03de9acf..fac0054359060fd3c63741eaa1897c66990f5523 100644 --- a/substrate/frame/bounties/Cargo.toml +++ b/substrate/frame/bounties/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } log = { workspace = true } diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index c099fc48b7a3bceb94e8b026386c84aed4edf818..c930868bf10159326bae978553eadcbd3fe03128 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -303,12 +303,10 @@ pub mod pallet { /// Number of bounty proposals that have been made. #[pallet::storage] - #[pallet::getter(fn bounty_count)] pub type BountyCount, I: 'static = ()> = StorageValue<_, BountyIndex, ValueQuery>; /// Bounties that have been made. #[pallet::storage] - #[pallet::getter(fn bounties)] pub type Bounties, I: 'static = ()> = StorageMap< _, Twox64Concat, @@ -318,13 +316,11 @@ pub mod pallet { /// The description of each bounty. #[pallet::storage] - #[pallet::getter(fn bounty_descriptions)] pub type BountyDescriptions, I: 'static = ()> = StorageMap<_, Twox64Concat, BountyIndex, BoundedVec>; /// Bounty indices that have been approved but not yet funded. #[pallet::storage] - #[pallet::getter(fn bounty_approvals)] pub type BountyApprovals, I: 'static = ()> = StorageValue<_, BoundedVec, ValueQuery>; @@ -849,7 +845,7 @@ impl, I: 'static> Pallet { description.try_into().map_err(|_| Error::::ReasonTooBig)?; ensure!(value >= T::BountyValueMinimum::get(), Error::::InvalidValue); - let index = Self::bounty_count(); + let index = BountyCount::::get(); // reserve deposit for new bounty let bond = T::BountyDepositBase::get() + diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index de747db53749902ad6164265e3cad139ddefa7da..a89f4ff9fbf301a8d03d9ad040a1b4009e7b18f6 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -534,7 +534,7 @@ fn propose_bounty_works() { assert_eq!(Balances::free_balance(0), 100 - deposit); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 0, @@ -545,9 +545,12 @@ fn propose_bounty_works() { } ); - assert_eq!(Bounties::bounty_descriptions(0).unwrap(), b"1234567890".to_vec()); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"1234567890".to_vec() + ); - assert_eq!(Bounties::bounty_count(), 1); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); }); } @@ -598,10 +601,10 @@ fn close_bounty_works() { assert_eq!(Balances::reserved_balance(0), 0); assert_eq!(Balances::free_balance(0), 100 - deposit); - assert_eq!(Bounties::bounties(0), None); + assert_eq!(pallet_bounties::Bounties::::get(0), None); assert!(!pallet_treasury::Proposals::::contains_key(0)); - assert_eq!(Bounties::bounty_descriptions(0), None); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0), None); }); } @@ -622,7 +625,7 @@ fn approve_bounty_works() { let deposit: u64 = 80 + 5; assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 0, @@ -632,7 +635,7 @@ fn approve_bounty_works() { status: BountyStatus::Approved, } ); - assert_eq!(Bounties::bounty_approvals(), vec![0]); + assert_eq!(pallet_bounties::BountyApprovals::::get(), vec![0]); assert_noop!( Bounties::close_bounty(RuntimeOrigin::root(), 0), @@ -650,7 +653,7 @@ fn approve_bounty_works() { assert_eq!(Balances::free_balance(0), 100); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 0, @@ -693,7 +696,7 @@ fn assign_curator_works() { assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, fee)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee, @@ -720,7 +723,7 @@ fn assign_curator_works() { let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee, @@ -755,7 +758,7 @@ fn unassign_curator_works() { assert_ok!(Bounties::unassign_curator(RuntimeOrigin::signed(4), 0)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee, @@ -773,7 +776,7 @@ fn unassign_curator_works() { assert_ok!(Bounties::unassign_curator(RuntimeOrigin::root(), 0)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee, @@ -817,7 +820,7 @@ fn award_and_claim_bounty_works() { assert_ok!(Bounties::award_bounty(RuntimeOrigin::signed(4), 0, 3)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee, @@ -851,8 +854,8 @@ fn award_and_claim_bounty_works() { assert_eq!(Balances::free_balance(3), 56); assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 0); - assert_eq!(Bounties::bounties(0), None); - assert_eq!(Bounties::bounty_descriptions(0), None); + assert_eq!(pallet_bounties::Bounties::::get(0), None); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0), None); }); } @@ -892,8 +895,8 @@ fn claim_handles_high_fee() { assert_eq!(Balances::free_balance(3), 0); assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 0); - assert_eq!(Bounties::bounties(0), None); - assert_eq!(Bounties::bounty_descriptions(0), None); + assert_eq!(pallet_bounties::Bounties::::get(0), None); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0), None); }); } @@ -918,7 +921,7 @@ fn cancel_and_refund() { )); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 0, @@ -978,8 +981,8 @@ fn award_and_cancel() { assert_eq!(Balances::free_balance(0), 95); assert_eq!(Balances::reserved_balance(0), 0); - assert_eq!(Bounties::bounties(0), None); - assert_eq!(Bounties::bounty_descriptions(0), None); + assert_eq!(pallet_bounties::Bounties::::get(0), None); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0), None); }); } @@ -1015,7 +1018,7 @@ fn expire_and_unassign() { assert_ok!(Bounties::unassign_curator(RuntimeOrigin::signed(0), 0)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 10, @@ -1065,7 +1068,7 @@ fn extend_expiry() { assert_ok!(Bounties::extend_bounty_expiry(RuntimeOrigin::signed(4), 0, Vec::new())); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 10, @@ -1079,7 +1082,7 @@ fn extend_expiry() { assert_ok!(Bounties::extend_bounty_expiry(RuntimeOrigin::signed(4), 0, Vec::new())); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 10, @@ -1190,7 +1193,7 @@ fn unassign_curator_self() { assert_ok!(Bounties::unassign_curator(RuntimeOrigin::signed(1), 0)); assert_eq!( - Bounties::bounties(0).unwrap(), + pallet_bounties::Bounties::::get(0).unwrap(), Bounty { proposer: 0, fee: 10, diff --git a/substrate/frame/broker/Cargo.toml b/substrate/frame/broker/Cargo.toml index ce8d41530451f978873a15a9a2e5538976ae706e..8f3f30ec58ebc2ff868cee03037939d0e9aac884 100644 --- a/substrate/frame/broker/Cargo.toml +++ b/substrate/frame/broker/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { workspace = true } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } bitvec = { version = "1.0.0", default-features = false } sp-api = { path = "../../primitives/api", default-features = false } diff --git a/substrate/frame/child-bounties/Cargo.toml b/substrate/frame/child-bounties/Cargo.toml index 14a5e25e13da6a246e3935c90839a350bf773d2e..09271632df54b74601d5d318a4749bffcbc86777 100644 --- a/substrate/frame/child-bounties/Cargo.toml +++ b/substrate/frame/child-bounties/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } log = { workspace = true } diff --git a/substrate/frame/child-bounties/src/benchmarking.rs b/substrate/frame/child-bounties/src/benchmarking.rs index 1973564d0dc1dacca9d30421cda2b4b03771cef9..947cfcfaa96a2daeb88c68c9cda501c42554fbe3 100644 --- a/substrate/frame/child-bounties/src/benchmarking.rs +++ b/substrate/frame/child-bounties/src/benchmarking.rs @@ -109,7 +109,7 @@ fn activate_bounty( child_bounty_setup.reason.clone(), )?; - child_bounty_setup.bounty_id = Bounties::::bounty_count() - 1; + child_bounty_setup.bounty_id = pallet_bounties::BountyCount::::get() - 1; let approve_origin = T::SpendOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; diff --git a/substrate/frame/child-bounties/src/lib.rs b/substrate/frame/child-bounties/src/lib.rs index 1eedeaa5a1ae3c5aa6b3804117921eab63768d1e..04a1f9799cb86e8831a849620b8288fc0692a9c8 100644 --- a/substrate/frame/child-bounties/src/lib.rs +++ b/substrate/frame/child-bounties/src/lib.rs @@ -181,19 +181,16 @@ pub mod pallet { /// Number of total child bounties. #[pallet::storage] - #[pallet::getter(fn child_bounty_count)] pub type ChildBountyCount = StorageValue<_, BountyIndex, ValueQuery>; /// Number of child bounties per parent bounty. /// Map of parent bounty index to number of child bounties. #[pallet::storage] - #[pallet::getter(fn parent_child_bounties)] pub type ParentChildBounties = StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>; /// Child bounties that have been added. #[pallet::storage] - #[pallet::getter(fn child_bounties)] pub type ChildBounties = StorageDoubleMap< _, Twox64Concat, @@ -205,13 +202,11 @@ pub mod pallet { /// The description of each child-bounty. #[pallet::storage] - #[pallet::getter(fn child_bounty_descriptions)] pub type ChildBountyDescriptions = StorageMap<_, Twox64Concat, BountyIndex, BoundedVec>; /// The cumulative child-bounty curator fee for each parent bounty. #[pallet::storage] - #[pallet::getter(fn children_curator_fees)] pub type ChildrenCuratorFees = StorageMap<_, Twox64Concat, BountyIndex, BalanceOf, ValueQuery>; @@ -251,7 +246,7 @@ pub mod pallet { description.try_into().map_err(|_| BountiesError::::ReasonTooBig)?; ensure!(value >= T::ChildBountyValueMinimum::get(), BountiesError::::InvalidValue); ensure!( - Self::parent_child_bounties(parent_bounty_id) <= + ParentChildBounties::::get(parent_bounty_id) <= T::MaxActiveChildBountyCount::get() as u32, Error::::TooManyChildBounties, ); @@ -276,15 +271,15 @@ pub mod pallet { )?; // Get child-bounty ID. - let child_bounty_id = Self::child_bounty_count(); + let child_bounty_id = ChildBountyCount::::get(); let child_bounty_account = Self::child_bounty_account_id(child_bounty_id); // Transfer funds from parent bounty to child-bounty. T::Currency::transfer(&parent_bounty_account, &child_bounty_account, value, KeepAlive)?; // Increment the active child-bounty count. - >::mutate(parent_bounty_id, |count| count.saturating_inc()); - >::put(child_bounty_id.saturating_add(1)); + ParentChildBounties::::mutate(parent_bounty_id, |count| count.saturating_inc()); + ChildBountyCount::::put(child_bounty_id.saturating_add(1)); // Create child-bounty instance. Self::create_child_bounty( @@ -710,12 +705,12 @@ pub mod pallet { }); // Update the active child-bounty tracking count. - >::mutate(parent_bounty_id, |count| { + ParentChildBounties::::mutate(parent_bounty_id, |count| { count.saturating_dec() }); // Remove the child-bounty description. - >::remove(child_bounty_id); + ChildBountyDescriptions::::remove(child_bounty_id); // Remove the child-bounty instance from the state. *maybe_child_bounty = None; @@ -817,7 +812,7 @@ impl Pallet { fn ensure_bounty_active( bounty_id: BountyIndex, ) -> Result<(T::AccountId, BlockNumberFor), DispatchError> { - let parent_bounty = pallet_bounties::Pallet::::bounties(bounty_id) + let parent_bounty = pallet_bounties::Bounties::::get(bounty_id) .ok_or(BountiesError::::InvalidIndex)?; if let BountyStatus::Active { curator, update_due } = parent_bounty.get_status() { Ok((curator, update_due)) @@ -862,7 +857,7 @@ impl Pallet { ChildrenCuratorFees::::mutate(parent_bounty_id, |value| { *value = value.saturating_sub(child_bounty.fee) }); - >::mutate(parent_bounty_id, |count| { + ParentChildBounties::::mutate(parent_bounty_id, |count| { *count = count.saturating_sub(1) }); @@ -880,7 +875,7 @@ impl Pallet { debug_assert!(transfer_result.is_ok()); // Remove the child-bounty description. - >::remove(child_bounty_id); + ChildBountyDescriptions::::remove(child_bounty_id); *maybe_child_bounty = None; @@ -901,14 +896,14 @@ impl pallet_bounties::ChildBountyManager> for Pallet fn child_bounties_count( bounty_id: pallet_bounties::BountyIndex, ) -> pallet_bounties::BountyIndex { - Self::parent_child_bounties(bounty_id) + ParentChildBounties::::get(bounty_id) } fn children_curator_fees(bounty_id: pallet_bounties::BountyIndex) -> BalanceOf { // This is asked for when the parent bounty is being claimed. No use of // keeping it in state after that. Hence removing. - let children_fee_total = Self::children_curator_fees(bounty_id); - >::remove(bounty_id); + let children_fee_total = ChildrenCuratorFees::::get(bounty_id); + ChildrenCuratorFees::::remove(bounty_id); children_fee_total } } diff --git a/substrate/frame/child-bounties/src/tests.rs b/substrate/frame/child-bounties/src/tests.rs index 30601f821e4384827059ffc694ab0108a347bf8b..d9405d3d28977c2cac3b42a034eb5fcfe8e56e8f 100644 --- a/substrate/frame/child-bounties/src/tests.rs +++ b/substrate/frame/child-bounties/src/tests.rs @@ -264,7 +264,7 @@ fn add_child_bounty() { // DB check. // Check the child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -275,10 +275,13 @@ fn add_child_bounty() { ); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 1); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 1); // Check the child-bounty description status. - assert_eq!(ChildBounties::child_bounty_descriptions(0).unwrap(), b"12345-p1".to_vec(),); + assert_eq!( + pallet_child_bounties::ChildBountyDescriptions::::get(0).unwrap(), + b"12345-p1".to_vec(), + ); }); } @@ -340,7 +343,7 @@ fn child_bounty_assign_curator() { assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee)); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -364,7 +367,7 @@ fn child_bounty_assign_curator() { let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -441,7 +444,7 @@ fn award_claim_child_bounty() { let expected_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -479,7 +482,7 @@ fn award_claim_child_bounty() { assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 0); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 0); }); } @@ -528,7 +531,7 @@ fn close_child_bounty_added() { assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(4), 0, 0)); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 0); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 0); // Parent-bounty account status. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); @@ -582,7 +585,7 @@ fn close_child_bounty_active() { assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(4), 0, 0)); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 0); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 0); // Ensure child-bounty curator balance is unreserved. assert_eq!(Balances::free_balance(8), 101); @@ -647,7 +650,7 @@ fn close_child_bounty_pending() { ); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 1); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 1); // Ensure no changes in child-bounty curator balance. assert_eq!(Balances::reserved_balance(8), expected_child_deposit); @@ -739,7 +742,7 @@ fn child_bounty_curator_proposed_unassign_curator() { assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, 2)); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -757,7 +760,7 @@ fn child_bounty_curator_proposed_unassign_curator() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -820,7 +823,7 @@ fn child_bounty_active_unassign_curator() { let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -838,7 +841,7 @@ fn child_bounty_active_unassign_curator() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -859,7 +862,7 @@ fn child_bounty_active_unassign_curator() { let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -877,7 +880,7 @@ fn child_bounty_active_unassign_curator() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -896,7 +899,7 @@ fn child_bounty_active_unassign_curator() { assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(6), 0, 0)); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -914,7 +917,7 @@ fn child_bounty_active_unassign_curator() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -935,7 +938,7 @@ fn child_bounty_active_unassign_curator() { let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -963,7 +966,7 @@ fn child_bounty_active_unassign_curator() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1025,7 +1028,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1056,7 +1059,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1087,7 +1090,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { let expected_deposit = CuratorDepositMin::get(); assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1116,7 +1119,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { // Verify updated child-bounty status. assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1186,7 +1189,7 @@ fn close_parent_with_child_bounty() { assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::root(), 0, 0)); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 0); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 0); // Try close parent-bounty again. // Should pass this time. @@ -1235,7 +1238,7 @@ fn children_curator_fee_calculation_test() { // Propose curator for child-bounty. assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee)); // Check curator fee added to the sum. - assert_eq!(ChildBounties::children_curator_fees(0), fee); + assert_eq!(pallet_child_bounties::ChildrenCuratorFees::::get(0), fee); // Accept curator for child-bounty. assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0)); // Award child-bounty. @@ -1244,7 +1247,7 @@ fn children_curator_fee_calculation_test() { let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( - ChildBounties::child_bounties(0, 0).unwrap(), + pallet_child_bounties::ChildBounties::::get(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, @@ -1264,7 +1267,7 @@ fn children_curator_fee_calculation_test() { assert_ok!(ChildBounties::claim_child_bounty(RuntimeOrigin::signed(7), 0, 0)); // Check the child-bounty count. - assert_eq!(ChildBounties::parent_child_bounties(0), 0); + assert_eq!(pallet_child_bounties::ParentChildBounties::::get(0), 0); // Award the parent bounty. assert_ok!(Bounties::award_bounty(RuntimeOrigin::signed(4), 0, 9)); diff --git a/substrate/frame/collective/Cargo.toml b/substrate/frame/collective/Cargo.toml index 850390409abc9646afbdb058dd2392d9f35869aa..d966370238bc4f2c8597555187a1830280752732 100644 --- a/substrate/frame/collective/Cargo.toml +++ b/substrate/frame/collective/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml index d963ac261d1940fc9fa4d88101df2ca35cf99c43..bd4ded1a1170c9356730eaef9ffbc28e0b6a356a 100644 --- a/substrate/frame/contracts/Cargo.toml +++ b/substrate/frame/contracts/Cargo.toml @@ -20,7 +20,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] paste = { version = "1.0", default-features = false } bitflags = "1.3" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } @@ -56,7 +56,7 @@ xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-feature xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" assert_matches = "1" env_logger = "0.11" pretty_assertions = "1" diff --git a/substrate/frame/contracts/README.md b/substrate/frame/contracts/README.md index 09dc770300ca8491af062bbde9e820deccdd1341..6440f14b9eced560971304b5f809dc0b64cde50a 100644 --- a/substrate/frame/contracts/README.md +++ b/substrate/frame/contracts/README.md @@ -34,19 +34,6 @@ calls are reverted. Assuming correct error handling by contract A, A's other cal One `ref_time` `Weight` is defined as one picosecond of execution time on the runtime's reference machine. -#### Schedule - -The `Schedule` is where, among other things, the cost of every action a contract can do is defined. These costs are derived -from the benchmarks of this pallet. Instead of looking at the raw benchmark results it is advised to look at the `Schedule` -if one wants to manually inspect the performance characteristics. The `Schedule` can be printed like this: - -```sh -RUST_LOG=runtime::contracts=info cargo run --features runtime-benchmarks --bin substrate-node -- benchmark pallet --extra -p pallet_contracts -e print_schedule -``` - -Please note that the `Schedule` will be printed multiple times. This is because we are (ab)using a benchmark to print -the struct. - ### Revert Behaviour Contract call failures are not cascading. When failures occur in a sub-call, they do not "bubble up", and the call will @@ -125,7 +112,7 @@ Contracts can emit messages to the client when called as RPC through the API. This is exposed in [ink!](https://use.ink) via [`ink_env::debug_message()`](https://paritytech.github.io/ink/ink_env/fn.debug_message.html). -Those messages are gathered into an internal buffer and sent to the RPC client. It is up the the individual client if +Those messages are gathered into an internal buffer and sent to the RPC client. It is up to the individual client if and how those messages are presented to the user. This buffer is also printed as a debug message. In order to see these messages on the node console the log level for the diff --git a/substrate/frame/contracts/mock-network/Cargo.toml b/substrate/frame/contracts/mock-network/Cargo.toml index 387c3ca39d049f7674541e24a36b300683326260..a348b7308d1232109a4763dcc764fdac87deee6d 100644 --- a/substrate/frame/contracts/mock-network/Cargo.toml +++ b/substrate/frame/contracts/mock-network/Cargo.toml @@ -12,7 +12,7 @@ description = "A mock network for testing pallet-contracts" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } diff --git a/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs b/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs index cc81b6bd636e54187e3ba09500fc39b472ed1943..bfdf6dd97eaf17fc0601f78c7c179e411c3a143d 100644 --- a/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs +++ b/substrate/frame/contracts/mock-network/src/mocks/msg_queue.rs @@ -47,17 +47,15 @@ pub mod pallet { pub struct Pallet(_); #[pallet::storage] - #[pallet::getter(fn parachain_id)] pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery>; #[pallet::storage] - #[pallet::getter(fn received_dmp)] /// A queue of received DMP messages pub(super) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; impl Get for Pallet { fn get() -> ParaId { - Self::parachain_id() + ParachainId::::get() } } @@ -89,6 +87,14 @@ pub mod pallet { ParachainId::::put(para_id); } + pub fn parachain_id() -> ParaId { + ParachainId::::get() + } + + pub fn received_dmp() -> Vec> { + ReceivedDmp::::get() + } + fn handle_xcmp_message( sender: ParaId, _sent_at: RelayBlockNumber, @@ -169,7 +175,7 @@ pub mod pallet { limit, Weight::zero(), ); - >::append(x); + ReceivedDmp::::append(x); Self::deposit_event(Event::ExecutedDownward(id, outcome)); }, }, diff --git a/substrate/frame/contracts/mock-network/src/parachain.rs b/substrate/frame/contracts/mock-network/src/parachain.rs index 843efab1502e7304991682d1f13180ee28288fe2..f35846ba32c31e0b260ffe428f459f0a14b9256b 100644 --- a/substrate/frame/contracts/mock-network/src/parachain.rs +++ b/substrate/frame/contracts/mock-network/src/parachain.rs @@ -49,10 +49,6 @@ use xcm_executor::{traits::JustTry, Config, XcmExecutor}; pub type SovereignAccountOf = (AccountId32Aliases, ParentIsPreset); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -64,7 +60,6 @@ impl frame_system::Config for Runtime { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockWeights = (); type BlockLength = (); type Version = (); @@ -285,6 +280,7 @@ impl Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } impl mock_msg_queue::Config for Runtime { diff --git a/substrate/frame/contracts/mock-network/src/relay_chain.rs b/substrate/frame/contracts/mock-network/src/relay_chain.rs index d5e0ec9c83fa73cc88f567f573f0d2172af23a7a..8829fff3d0436d95b3e44d87b2258d13c167efc1 100644 --- a/substrate/frame/contracts/mock-network/src/relay_chain.rs +++ b/substrate/frame/contracts/mock-network/src/relay_chain.rs @@ -43,10 +43,6 @@ use super::{ primitives::{AccountId, Balance}, }; -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -58,7 +54,6 @@ impl frame_system::Config for Runtime { type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type BlockWeights = (); type BlockLength = (); type Version = (); @@ -185,6 +180,7 @@ impl Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = XcmPallet; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/substrate/frame/contracts/proc-macro/src/lib.rs b/substrate/frame/contracts/proc-macro/src/lib.rs index 1794d09d5ad28e08bf9579bed4f311f469be832c..356b42268da6f534e99aacb60ead7111d5dd3b58 100644 --- a/substrate/frame/contracts/proc-macro/src/lib.rs +++ b/substrate/frame/contracts/proc-macro/src/lib.rs @@ -132,6 +132,7 @@ struct HostFn { alias_to: Option, /// Formulating the predicate inverted makes the expression using it simpler. not_deprecated: bool, + cfg: Option, } enum HostFnReturn { @@ -163,13 +164,13 @@ impl ToTokens for HostFn { impl HostFn { pub fn try_from(mut item: syn::ItemFn) -> syn::Result { let err = |span, msg| { - let msg = format!("Invalid host function definition. {}", msg); + let msg = format!("Invalid host function definition.\n{}", msg); syn::Error::new(span, msg) }; // process attributes let msg = - "only #[version()], #[unstable], #[prefixed_alias] and #[deprecated] attributes are allowed."; + "Only #[version()], #[unstable], #[prefixed_alias], #[cfg] and #[deprecated] attributes are allowed."; let span = item.span(); let mut attrs = item.attrs.clone(); attrs.retain(|a| !a.path().is_ident("doc")); @@ -177,6 +178,7 @@ impl HostFn { let mut is_stable = true; let mut alias_to = None; let mut not_deprecated = true; + let mut cfg = None; while let Some(attr) = attrs.pop() { let ident = attr.path().get_ident().ok_or(err(span, msg))?.to_string(); match ident.as_str() { @@ -206,7 +208,13 @@ impl HostFn { } not_deprecated = false; }, - _ => return Err(err(span, msg)), + "cfg" => { + if cfg.is_some() { + return Err(err(span, "#[cfg] can only be specified once")) + } + cfg = Some(attr); + }, + id => return Err(err(span, &format!("Unsupported attribute \"{id}\". {msg}"))), } } let name = item.sig.ident.to_string(); @@ -311,6 +319,7 @@ impl HostFn { is_stable, alias_to, not_deprecated, + cfg, }) }, _ => Err(err(span, &msg)), @@ -528,8 +537,9 @@ fn expand_env(def: &EnvDef, docs: bool) -> TokenStream2 { /// - real implementation, to register it in the contract execution environment; /// - dummy implementation, to be used as mocks for contract validation step. fn expand_impls(def: &EnvDef) -> TokenStream2 { - let impls = expand_functions(def, true, quote! { crate::wasm::Runtime }); - let dummy_impls = expand_functions(def, false, quote! { () }); + let impls = expand_functions(def, ExpandMode::Impl); + let dummy_impls = expand_functions(def, ExpandMode::MockImpl); + let bench_impls = expand_functions(def, ExpandMode::BenchImpl); quote! { impl<'a, E: Ext> crate::wasm::Environment> for Env @@ -545,6 +555,14 @@ fn expand_impls(def: &EnvDef) -> TokenStream2 { } } + #[cfg(feature = "runtime-benchmarks")] + pub struct BenchEnv(::core::marker::PhantomData); + + #[cfg(feature = "runtime-benchmarks")] + impl BenchEnv { + #bench_impls + } + impl crate::wasm::Environment<()> for Env { fn define( @@ -560,18 +578,38 @@ fn expand_impls(def: &EnvDef) -> TokenStream2 { } } -fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) -> TokenStream2 { +enum ExpandMode { + Impl, + BenchImpl, + MockImpl, +} + +impl ExpandMode { + fn expand_blocks(&self) -> bool { + match *self { + ExpandMode::Impl | ExpandMode::BenchImpl => true, + ExpandMode::MockImpl => false, + } + } + + fn host_state(&self) -> TokenStream2 { + match *self { + ExpandMode::Impl | ExpandMode::BenchImpl => quote! { crate::wasm::runtime::Runtime }, + ExpandMode::MockImpl => quote! { () }, + } + } +} + +fn expand_functions(def: &EnvDef, expand_mode: ExpandMode) -> TokenStream2 { let impls = def.host_funcs.iter().map(|f| { // skip the context and memory argument let params = f.item.sig.inputs.iter().skip(2); - - let (module, name, body, wasm_output, output) = ( - f.module(), - &f.name, - &f.item.block, - f.returns.to_wasm_sig(), - &f.item.sig.output - ); + let module = f.module(); + let cfg = &f.cfg; + let name = &f.name; + let body = &f.item.block; + let wasm_output = f.returns.to_wasm_sig(); + let output = &f.item.sig.output; let is_stable = f.is_stable; let not_deprecated = f.not_deprecated; @@ -608,23 +646,34 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) // - We replace any code by unreachable! // - Allow unused variables as the code that uses is not expanded // - We don't need to map the error as we simply panic if they code would ever be executed - let inner = if expand_blocks { - quote! { || #output { - let (memory, ctx) = __caller__ - .data() - .memory() - .expect("Memory must be set when setting up host data; qed") - .data_and_store_mut(&mut __caller__); - #wrapped_body_with_trace - } } - } else { - quote! { || -> #wasm_output { - // This is part of the implementation for `Environment<()>` which is not - // meant to be actually executed. It is only for validation which will - // never call host functions. - ::core::unreachable!() - } } + let expand_blocks = expand_mode.expand_blocks(); + let inner = match expand_mode { + ExpandMode::Impl => { + quote! { || #output { + let (memory, ctx) = __caller__ + .data() + .memory() + .expect("Memory must be set when setting up host data; qed") + .data_and_store_mut(&mut __caller__); + #wrapped_body_with_trace + } } + }, + ExpandMode::BenchImpl => { + let body = &body.stmts; + quote!{ + #(#body)* + } + }, + ExpandMode::MockImpl => { + quote! { || -> #wasm_output { + // This is part of the implementation for `Environment<()>` which is not + // meant to be actually executed. It is only for validation which will + // never call host functions. + ::core::unreachable!() + } } + }, }; + let into_host = if expand_blocks { quote! { |reason| { @@ -655,6 +704,11 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) .map_err(TrapReason::from) .map_err(#into_host)? }; + + // Charge gas for host function execution. + __caller__.data_mut().charge_gas(crate::wasm::RuntimeCosts::HostFn) + .map_err(TrapReason::from) + .map_err(#into_host)?; } } else { quote! { } @@ -676,29 +730,51 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) quote! { } }; - quote! { - // We need to allow all interfaces when runtime benchmarks are performed because - // we generate the weights even when those interfaces are not enabled. This - // is necessary as the decision whether we allow unstable or deprecated functions - // is a decision made at runtime. Generation of the weights happens statically. - if ::core::cfg!(feature = "runtime-benchmarks") || - ((#is_stable || __allow_unstable__) && (#not_deprecated || __allow_deprecated__)) - { - #allow_unused - linker.define(#module, #name, ::wasmi::Func::wrap(&mut*store, |mut __caller__: ::wasmi::Caller<#host_state>, #( #params, )*| -> #wasm_output { - #sync_gas_before - let mut func = #inner; - let result = func().map_err(#into_host).map(::core::convert::Into::into); - #sync_gas_after - result - }))?; - } + match expand_mode { + ExpandMode::BenchImpl => { + let name = Ident::new(&format!("{module}_{name}"), Span::call_site()); + quote! { + pub fn #name(ctx: &mut crate::wasm::Runtime, memory: &mut [u8], #(#params),*) #output { + #inner + } + } + }, + _ => { + let host_state = expand_mode.host_state(); + quote! { + // We need to allow all interfaces when runtime benchmarks are performed because + // we generate the weights even when those interfaces are not enabled. This + // is necessary as the decision whether we allow unstable or deprecated functions + // is a decision made at runtime. Generation of the weights happens statically. + #cfg + if ::core::cfg!(feature = "runtime-benchmarks") || + ((#is_stable || __allow_unstable__) && (#not_deprecated || __allow_deprecated__)) + { + #allow_unused + linker.define(#module, #name, ::wasmi::Func::wrap(&mut*store, |mut __caller__: ::wasmi::Caller<#host_state>, #( #params, )*| -> #wasm_output { + #sync_gas_before + let mut func = #inner; + let result = func().map_err(#into_host).map(::core::convert::Into::into); + #sync_gas_after + result + }))?; + } + } + }, } }); - quote! { - let __allow_unstable__ = matches!(allow_unstable, AllowUnstableInterface::Yes); - let __allow_deprecated__ = matches!(allow_deprecated, AllowDeprecatedInterface::Yes); - #( #impls )* + + match expand_mode { + ExpandMode::BenchImpl => { + quote! { + #( #impls )* + } + }, + _ => quote! { + let __allow_unstable__ = matches!(allow_unstable, AllowUnstableInterface::Yes); + let __allow_deprecated__ = matches!(allow_deprecated, AllowDeprecatedInterface::Yes); + #( #impls )* + }, } } diff --git a/substrate/frame/contracts/src/benchmarking/call_builder.rs b/substrate/frame/contracts/src/benchmarking/call_builder.rs index 285fe0052b4d95a200eaebd0a86fb77d729aacfd..5d73d825fca9a76d15742c7a44b32b11a95fed51 100644 --- a/substrate/frame/contracts/src/benchmarking/call_builder.rs +++ b/substrate/frame/contracts/src/benchmarking/call_builder.rs @@ -25,6 +25,7 @@ use crate::{ }; use codec::{Encode, HasCompact}; use core::fmt::Debug; +use frame_benchmarking::benchmarking; use sp_core::Get; use sp_std::prelude::*; @@ -57,6 +58,16 @@ pub struct CallSetup { data: Vec, } +impl Default for CallSetup +where + T: Config + pallet_balances::Config, + as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode, +{ + fn default() -> Self { + Self::new(WasmModule::dummy()) + } +} + impl CallSetup where T: Config + pallet_balances::Config, @@ -70,6 +81,17 @@ where let storage_meter = Meter::new(&origin, None, 0u32.into()).unwrap(); + // Whitelist contract account, as it is already accounted for in the call benchmark + benchmarking::add_to_whitelist( + frame_system::Account::::hashed_key_for(&contract.account_id).into(), + ); + + // Whitelist the contract's contractInfo as it is already accounted for in the call + // benchmark + benchmarking::add_to_whitelist( + crate::ContractInfoOf::::hashed_key_for(&contract.account_id).into(), + ); + Self { contract, dest, @@ -150,21 +172,29 @@ where } #[macro_export] -macro_rules! call_builder( - ($func: ident, $module:expr) => { - $crate::call_builder!($func, _contract, $module); +macro_rules! memory( + ($($bytes:expr,)*) => { + vec![] + .into_iter() + $(.chain($bytes))* + .collect::>() }; - ($func: ident, $contract: ident, $module:expr) => { - let mut setup = CallSetup::::new($module); - $crate::call_builder!($func, $contract, setup: setup); +); + +#[macro_export] +macro_rules! build_runtime( + ($runtime:ident, $memory:ident: [$($segment:expr,)*]) => { + $crate::build_runtime!($runtime, _contract, $memory: [$($segment,)*]); }; - ($func:ident, setup: $setup: ident) => { - $crate::call_builder!($func, _contract, setup: $setup); + ($runtime:ident, $contract:ident, $memory:ident: [$($bytes:expr,)*]) => { + $crate::build_runtime!($runtime, $contract); + let mut $memory = $crate::memory!($($bytes,)*); }; - ($func:ident, $contract: ident, setup: $setup: ident) => { - let data = $setup.data(); - let $contract = $setup.contract(); - let (mut ext, module) = $setup.ext(); - let $func = CallSetup::::prepare_call(&mut ext, module, data); + ($runtime:ident, $contract:ident) => { + let mut setup = CallSetup::::default(); + let $contract = setup.contract(); + let input = setup.data(); + let (mut ext, _) = setup.ext(); + let mut $runtime = crate::wasm::Runtime::new(&mut ext, input); }; ); diff --git a/substrate/frame/contracts/src/benchmarking/code.rs b/substrate/frame/contracts/src/benchmarking/code.rs index b97cf168e26d4562e4f4a3b7f07ad243174e7a98..65bcf30683c05e83515815ae33ffe5d9c4aadb70 100644 --- a/substrate/frame/contracts/src/benchmarking/code.rs +++ b/substrate/frame/contracts/src/benchmarking/code.rs @@ -288,17 +288,15 @@ impl WasmModule { module.into() } - /// Creates a wasm module that calls the imported function named `getter_name` `repeat` - /// times. The imported function is expected to have the "getter signature" of - /// (out_ptr: u32, len_ptr: u32) -> (). - pub fn getter(module_name: &'static str, getter_name: &'static str, repeat: u32) -> Self { + /// Creates a wasm module that calls the imported function `noop` `repeat` times. + pub fn noop(repeat: u32) -> Self { let pages = max_pages::(); ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: module_name, - name: getter_name, - params: vec![ValueType::I32, ValueType::I32], + module: "seal0", + name: "noop", + params: vec![], return_type: None, }], // Write the output buffer size. The output size will be overwritten by the @@ -312,35 +310,7 @@ impl WasmModule { call_body: Some(body::repeated( repeat, &[ - Instruction::I32Const(4), // ptr where to store output - Instruction::I32Const(0), // ptr to length - Instruction::Call(0), // call the imported function - ], - )), - ..Default::default() - } - .into() - } - - /// Creates a wasm module that calls the imported hash function named `name` `repeat` times - /// with an input of size `data_size`. Hash functions have the signature - /// (input_ptr: u32, input_len: u32, output_ptr: u32) -> () - pub fn hasher(name: &'static str, repeat: u32, data_size: u32) -> Self { - ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name, - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - call_body: Some(body::repeated( - repeat, - &[ - Instruction::I32Const(0), // input_ptr - Instruction::I32Const(data_size as i32), // input_len - Instruction::I32Const(0), // output_ptr - Instruction::Call(0), + Instruction::Call(0), // call the imported function ], )), ..Default::default() @@ -353,21 +323,6 @@ impl WasmModule { pub mod body { use super::*; - /// When generating contract code by repeating a Wasm sequence, it's sometimes necessary - /// to change those instructions on each repetition. The variants of this enum describe - /// various ways in which this can happen. - pub enum DynInstr { - /// Insert the associated instruction. - Regular(Instruction), - /// Insert a I32Const with incrementing value for each insertion. - /// (start_at, increment_by) - Counter(u32, u32), - } - - pub fn plain(instructions: Vec) -> FuncBody { - FuncBody::new(Vec::new(), Instructions::new(instructions)) - } - pub fn repeated(repetitions: u32, instructions: &[Instruction]) -> FuncBody { repeated_with_locals(&[], repetitions, instructions) } @@ -401,24 +356,6 @@ pub mod body { instructions.push(Instruction::End); FuncBody::new(locals.to_vec(), Instructions::new(instructions)) } - - pub fn repeated_dyn(repetitions: u32, mut instructions: Vec) -> FuncBody { - // We need to iterate over indices because we cannot cycle over mutable references - let body = (0..instructions.len()) - .cycle() - .take(instructions.len() * usize::try_from(repetitions).unwrap()) - .flat_map(|idx| match &mut instructions[idx] { - DynInstr::Regular(instruction) => vec![instruction.clone()], - DynInstr::Counter(offset, increment_by) => { - let current = *offset; - *offset += *increment_by; - vec![Instruction::I32Const(current as i32)] - }, - }) - .chain(sp_std::iter::once(Instruction::End)) - .collect(); - FuncBody::new(Vec::new(), Instructions::new(body)) - } } /// The maximum amount of pages any contract is allowed to have according to the current `Schedule`. diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 952ef180be21860b4a13a26fdf07bf03251f00a2..7c993bc9a7718d7ada98198bf7c1f7df236aead1 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -23,33 +23,31 @@ mod code; mod sandbox; use self::{ call_builder::CallSetup, - code::{ - body::{self, DynInstr::*}, - DataSegment, ImportedFunction, ImportedMemory, Location, ModuleDefinition, WasmModule, - }, + code::{body, ImportedMemory, Location, ModuleDefinition, WasmModule}, sandbox::Sandbox, }; use crate::{ - exec::Key, + exec::{Key, SeedOf}, migration::{ codegen::LATEST_MIGRATION_VERSION, v09, v10, v11, v12, v13, v14, v15, v16, MigrationStep, }, + wasm::BenchEnv, Pallet as Contracts, *, }; use codec::{Encode, MaxEncodedLen}; use frame_benchmarking::v2::*; use frame_support::{ - self, + self, assert_ok, pallet_prelude::StorageVersion, traits::{fungible::InspectHold, Currency}, weights::{Weight, WeightMeter}, }; use frame_system::RawOrigin; use pallet_balances; -use pallet_contracts_uapi::CallFlags; +use pallet_contracts_uapi::{CallFlags, ReturnErrorCode}; use sp_runtime::traits::{Bounded, Hash}; use sp_std::prelude::*; -use wasm_instrument::parity_wasm::elements::{BlockType, Instruction, Local, ValueType}; +use wasm_instrument::parity_wasm::elements::{Instruction, Local, ValueType}; /// How many runs we do per API benchmark. /// @@ -442,13 +440,6 @@ mod benchmarks { Ok(()) } - // This constructs a contract that is maximal expensive to instrument. - // It creates a maximum number of metering blocks per byte. - // The size of the salt influences the runtime because is is hashed in order to - // determine the contract address. All code is generated to the `call` function so that - // we don't benchmark the actual execution of this code but merely what it takes to load - // a code of that size into the sandbox. - // // `c`: Size of the code in bytes. // `i`: Size of the input in bytes. // `s`: Size of the salt in bytes. @@ -482,7 +473,6 @@ mod benchmarks { assert_eq!(T::Currency::balance(&addr), value + Pallet::::min_balance()); } - // Instantiate uses a dummy contract constructor to measure the overhead of the instantiate. // `i`: Size of the input in bytes. // `s`: Size of the salt in bytes. #[benchmark(pov_mode = Measured)] @@ -621,507 +611,306 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn seal_caller(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_caller", r)); - - let res; + fn noop_host_fn(r: Linear<0, API_BENCHMARK_RUNS>) { + let mut setup = CallSetup::::new(WasmModule::noop(r)); + let (mut ext, module) = setup.ext(); + let func = CallSetup::::prepare_call(&mut ext, module, vec![]); #[block] { - res = func.call(); + func.call(); } - assert_eq!(res.did_revert(), false); } #[benchmark(pov_mode = Measured)] - fn seal_is_contract(r: Linear<0, API_BENCHMARK_RUNS>) { - let accounts = (0..r).map(|n| account::("account", n, 0)).collect::>(); - let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); - let accounts_bytes = accounts.iter().flat_map(|a| a.encode()).collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_is_contract", - params: vec![ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: accounts_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, account_len as u32), // address_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info().unwrap(); - // every account would be a contract (worst case) - for acc in accounts.iter() { - >::insert(acc, info.clone()); - } + fn seal_caller() { + let len = ::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_caller(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert_eq!( + &::decode(&mut &memory[4..]).unwrap(), + runtime.ext().caller().account_id().unwrap() + ); } #[benchmark(pov_mode = Measured)] - fn seal_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) { - let accounts = (0..r).map(|n| account::("account", n, 0)).collect::>(); - let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); - let accounts_bytes = accounts.iter().flat_map(|a| a.encode()).collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_code_hash", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { - offset: 0, - value: 32u32.to_le_bytes().to_vec(), // output length - }, - DataSegment { offset: 36, value: accounts_bytes }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(36, account_len as u32), // address_ptr - Regular(Instruction::I32Const(4)), // ptr to output data - Regular(Instruction::I32Const(0)), // ptr to output length - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info().unwrap(); - // every account would be a contract (worst case) - for acc in accounts.iter() { - >::insert(acc, info.clone()); - } + fn seal_is_contract() { + let Contract { account_id, .. } = + Contract::::with_index(1, WasmModule::dummy(), vec![]).unwrap(); - let res; + build_runtime!(runtime, memory: [account_id.encode(), ]); + + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_is_contract(&mut runtime, &mut memory, 0); } - assert_eq!(res.did_revert(), false); + + assert_eq!(result.unwrap(), 1); } #[benchmark(pov_mode = Measured)] - fn seal_own_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_own_code_hash", r)); + fn seal_code_hash() { + let contract = Contract::::with_index(1, WasmModule::dummy(), vec![]).unwrap(); + let len = as MaxEncodedLen>::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], contract.account_id.encode(), ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_code_hash(&mut runtime, &mut memory, 4 + len, 4, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert_eq!( + as Decode>::decode(&mut &memory[4..]).unwrap(), + contract.info().unwrap().code_hash + ); } #[benchmark(pov_mode = Measured)] - fn seal_caller_is_origin(r: Linear<0, API_BENCHMARK_RUNS>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_caller_is_origin", - params: vec![], - return_type: Some(ValueType::I32), - }], - call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), - ..Default::default() - }); - call_builder!(func, code); - - let res; + fn seal_own_code_hash() { + let len = as MaxEncodedLen>::max_encoded_len() as u32; + build_runtime!(runtime, contract, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_own_code_hash(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert_eq!( + as Decode>::decode(&mut &memory[4..]).unwrap(), + contract.info().unwrap().code_hash + ); } #[benchmark(pov_mode = Measured)] - fn seal_caller_is_root(r: Linear<0, API_BENCHMARK_RUNS>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "caller_is_root", - params: vec![], - return_type: Some(ValueType::I32), - }], - call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.set_origin(Origin::Root); - call_builder!(func, setup: setup); + fn seal_caller_is_origin() { + build_runtime!(runtime, memory: []); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_caller_is_origin(&mut runtime, &mut memory); } - assert_eq!(res.did_revert(), false); + assert_eq!(result.unwrap(), 1u32); } #[benchmark(pov_mode = Measured)] - fn seal_address(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_address", r)); + fn seal_caller_is_root() { + let mut setup = CallSetup::::default(); + setup.set_origin(Origin::Root); + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_caller_is_root(&mut runtime, &mut [0u8; 0]); } - assert_eq!(res.did_revert(), false); + assert_eq!(result.unwrap(), 1u32); } #[benchmark(pov_mode = Measured)] - fn seal_gas_left(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal1", "gas_left", r)); + fn seal_address() { + let len = as MaxEncodedLen>::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_address(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + &::decode(&mut &memory[4..]).unwrap(), + runtime.ext().address() + ); } #[benchmark(pov_mode = Measured)] - fn seal_balance(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_balance", r)); + fn seal_gas_left() { + // use correct max_encoded_len when new version of parity-scale-codec is released + let len = 18u32; + assert!(::max_encoded_len() as u32 != len); + build_runtime!(runtime, memory: [32u32.to_le_bytes(), vec![0u8; len as _], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal1_gas_left(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + ::decode(&mut &memory[4..]).unwrap(), + runtime.ext().gas_meter().gas_left() + ); } #[benchmark(pov_mode = Measured)] - fn seal_value_transferred(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_value_transferred", r)); - - let res; + fn seal_balance() { + let len = ::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_seal_balance(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + ::decode(&mut &memory[4..]).unwrap(), + runtime.ext().balance().into() + ); } #[benchmark(pov_mode = Measured)] - fn seal_minimum_balance(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_minimum_balance", r)); - - let res; + fn seal_value_transferred() { + let len = ::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_value_transferred(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + ::decode(&mut &memory[4..]).unwrap(), + runtime.ext().value_transferred().into() + ); } #[benchmark(pov_mode = Measured)] - fn seal_block_number(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_block_number", r)); - - let res; + fn seal_minimum_balance() { + let len = ::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_minimum_balance(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + ::decode(&mut &memory[4..]).unwrap(), + runtime.ext().minimum_balance().into() + ); } #[benchmark(pov_mode = Measured)] - fn seal_now(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::getter("seal0", "seal_now", r)); - - let res; + fn seal_block_number() { + let len = as MaxEncodedLen>::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_seal_block_number(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!( + >::decode(&mut &memory[4..]).unwrap(), + runtime.ext().block_number() + ); } #[benchmark(pov_mode = Measured)] - fn seal_weight_to_fee(r: Linear<0, API_BENCHMARK_RUNS>) { - let pages = code::max_pages::(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "weight_to_fee", - params: vec![ValueType::I64, ValueType::I64, ValueType::I32, ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { - offset: 0, - value: (pages * 64 * 1024 - 4).to_le_bytes().to_vec(), - }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I64Const(500_000), - Instruction::I64Const(300_000), - Instruction::I32Const(4), - Instruction::I32Const(0), - Instruction::Call(0), - ], - )), - ..Default::default() - }); - call_builder!(func, code); - - let res; + fn seal_now() { + let len = as MaxEncodedLen>::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_seal_now(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!(>::decode(&mut &memory[4..]).unwrap(), *runtime.ext().now()); } #[benchmark(pov_mode = Measured)] - fn seal_input(r: Linear<0, API_BENCHMARK_RUNS>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_input", - params: vec![ValueType::I32, ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { offset: 0, value: 0u32.to_le_bytes().to_vec() }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(4), // ptr where to store output - Instruction::I32Const(0), // ptr to length - Instruction::Call(0), - ], - )), - ..Default::default() - }); - - call_builder!(func, code); - - let res; + fn seal_weight_to_fee() { + let len = ::max_encoded_len() as u32; + build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); + let weight = Weight::from_parts(500_000, 300_000); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal1_weight_to_fee( + &mut runtime, + &mut memory, + weight.ref_time(), + weight.proof_size(), + 4, + 0, + ); } - assert_eq!(res.did_revert(), false); - } - - #[benchmark(pov_mode = Measured)] - fn seal_input_per_byte( - n: Linear<0, { code::max_pages::() * 64 * 1024 }>, - ) -> Result<(), BenchmarkError> { - let buffer_size = code::max_pages::() * 64 * 1024 - 4; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_input", - params: vec![ValueType::I32, ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { - offset: 0, - value: buffer_size.to_le_bytes().to_vec(), - }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(4), // ptr where to store output - Instruction::I32Const(0), // ptr to length - Instruction::Call(0), - Instruction::End, - ])), - ..Default::default() - }); - let instance = Contract::::new(code, vec![])?; - let data = vec![42u8; n.min(buffer_size) as usize]; - let origin = RawOrigin::Signed(instance.caller.clone()); - #[extrinsic_call] - call(origin, instance.addr, 0u32.into(), Weight::MAX, None, data); - Ok(()) + assert_ok!(result); + assert_eq!( + >::decode(&mut &memory[4..]).unwrap(), + runtime.ext().get_weight_price(weight) + ); } - // We cannot call `seal_return` multiple times. Therefore our weight determination is not - // as precise as with other APIs. Because this function can only be called once per - // contract it cannot be used as an attack vector. #[benchmark(pov_mode = Measured)] - fn seal_return(r: Linear<0, 1>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_return", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(0), // data_len - Instruction::Call(0), - ], - )), - ..Default::default() - }); - call_builder!(func, code); - - let res; + fn seal_input(n: Linear<0, { code::max_pages::() * 64 * 1024 - 4 }>) { + let mut setup = CallSetup::::default(); + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![42u8; n as usize]); + let mut memory = memory!(n.to_le_bytes(), vec![0u8; n as usize],); + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_input(&mut runtime, &mut memory, 4, 0); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!(&memory[4..], &vec![42u8; n as usize]); } #[benchmark(pov_mode = Measured)] - fn seal_return_per_byte(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_return", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(n as i32), // data_len - Instruction::Call(0), - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, code); + fn seal_return(n: Linear<0, { code::max_pages::() * 64 * 1024 - 4 }>) { + build_runtime!(runtime, memory: [n.to_le_bytes(), vec![42u8; n as usize], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_seal_return(&mut runtime, &mut memory, 0, 0, n); } - assert_eq!(res.did_revert(), false); + + assert!(matches!( + result, + Err(crate::wasm::TrapReason::Return(crate::wasm::ReturnData { .. })) + )); } - // The same argument as for `seal_return` is true here. #[benchmark(pov_mode = Measured)] - fn seal_terminate(r: Linear<0, 1>) -> Result<(), BenchmarkError> { + fn seal_terminate( + n: Linear<0, { T::MaxDelegateDependencies::get() }>, + ) -> Result<(), BenchmarkError> { let beneficiary = account::("beneficiary", 0, 0); - let beneficiary_bytes = beneficiary.encode(); - let beneficiary_len = beneficiary_bytes.len(); let caller = whitelisted_caller(); + build_runtime!(runtime, memory: [beneficiary.encode(),]); + T::Currency::set_balance(&caller, caller_funding::()); - // Maximize the delegate_dependencies to account for the worst-case scenario. - let code_hashes = (0..T::MaxDelegateDependencies::get()) - .map(|i| { - let new_code = WasmModule::::dummy_with_bytes(65 + i); - Contracts::::store_code_raw(new_code.code, caller.clone())?; - Ok(new_code.hash) - }) - .collect::, &'static str>>()?; - let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ - ImportedFunction { - module: "seal0", - name: "seal_terminate", - params: vec![ValueType::I32, ValueType::I32], - return_type: None, - }, - ImportedFunction { - module: "seal0", - name: "lock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None, - }, - ], - data_segments: vec![ - DataSegment { offset: 0, value: beneficiary_bytes }, - DataSegment { offset: beneficiary_len as u32, value: code_hashes_bytes }, - ], - deploy_body: Some(body::repeated_dyn( - T::MaxDelegateDependencies::get(), - vec![ - Counter(beneficiary_len as u32, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(1)), - ], - )), - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(0), // beneficiary_ptr - Instruction::I32Const(beneficiary_len as i32), // beneficiary_len - Instruction::Call(0), - ], - )), - ..Default::default() + (0..n).for_each(|i| { + let new_code = WasmModule::::dummy_with_bytes(65 + i); + Contracts::::store_code_raw(new_code.code, caller.clone()).unwrap(); + runtime.ext().lock_delegate_dependency(new_code.hash).unwrap(); }); - let instance = Contract::::new(code, vec![])?; - let origin = RawOrigin::Signed(instance.caller.clone()); - assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into()); - assert_eq!( - T::Currency::balance(&instance.account_id), - Pallet::::min_balance() * 2u32.into() - ); - assert_ne!( - T::Currency::balance_on_hold( - &HoldReason::StorageDepositReserve.into(), - &instance.account_id - ), - 0u32.into() - ); - assert_eq!( - ContractInfoOf::::get(&instance.account_id) - .unwrap() - .delegate_dependencies_count() as u32, - T::MaxDelegateDependencies::get() - ); - #[extrinsic_call] - call(origin, instance.addr.clone(), 0u32.into(), Weight::MAX, None, vec![]); - - if r > 0 { - assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into()); - assert_eq!( - T::Currency::balance_on_hold( - &HoldReason::StorageDepositReserve.into(), - &instance.account_id - ), - 0u32.into() - ); - assert_eq!( - T::Currency::total_balance(&beneficiary), - Pallet::::min_balance() * 2u32.into() - ); + + let result; + #[block] + { + result = BenchEnv::seal1_terminate(&mut runtime, &mut memory, 0); } + + assert!(matches!(result, Err(crate::wasm::TrapReason::Termination))); + Ok(()) } @@ -1129,161 +918,77 @@ mod benchmarks { // number (< 1 KB). Therefore we are not overcharging too much in case a smaller subject is // used. #[benchmark(pov_mode = Measured)] - fn seal_random(r: Linear<0, API_BENCHMARK_RUNS>) { - let pages = code::max_pages::(); + fn seal_random() { let subject_len = T::Schedule::get().limits.subject_len; assert!(subject_len < 1024); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_random", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { - offset: 0, - value: (pages * 64 * 1024 - subject_len - 4).to_le_bytes().to_vec(), - }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(4), // subject_ptr - Instruction::I32Const(subject_len as i32), // subject_len - Instruction::I32Const((subject_len + 4) as i32), // out_ptr - Instruction::I32Const(0), // out_len_ptr - Instruction::Call(0), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + let output_len = + <(SeedOf, BlockNumberFor) as MaxEncodedLen>::max_encoded_len() as u32; - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - } + build_runtime!(runtime, memory: [ + output_len.to_le_bytes(), + vec![42u8; subject_len as _], + vec![0u8; output_len as _], + ]); - // Overhead of calling the function without any topic. - // We benchmark for the worst case (largest event). - #[benchmark(pov_mode = Measured)] - fn seal_deposit_event(r: Linear<0, API_BENCHMARK_RUNS>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_deposit_event", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(0), // topics_ptr - Instruction::I32Const(0), // topics_len - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(0), // data_len - Instruction::Call(0), - ], - )), - ..Default::default() - }); - - call_builder!(func, code); - - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_random( + &mut runtime, + &mut memory, + 4, // subject_ptr + subject_len, // subject_len + subject_len + 4, // output_ptr + 0, // output_len_ptr + ); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert_ok!(<(SeedOf, BlockNumberFor)>::decode(&mut &memory[subject_len as _..])); } // Benchmark the overhead that topics generate. // `t`: Number of topics // `n`: Size of event payload in bytes #[benchmark(pov_mode = Measured)] - fn seal_deposit_event_per_topic_and_byte( + fn seal_deposit_event( t: Linear<0, { T::Schedule::get().limits.event_topics }>, n: Linear<0, { T::Schedule::get().limits.payload_len }>, ) { let topics = (0..t).map(|i| T::Hashing::hash_of(&i)).collect::>().encode(); - let topics_len = topics.len(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_deposit_event", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { offset: 0, value: topics }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // topics_ptr - Instruction::I32Const(topics_len as i32), // topics_len - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(n as i32), // data_len - Instruction::Call(0), - Instruction::End, - ])), - ..Default::default() - }); + let topics_len = topics.len() as u32; - call_builder!(func, code); + build_runtime!(runtime, memory: [ + n.to_le_bytes(), + topics, + vec![0u8; n as _], + ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_deposit_event( + &mut runtime, + &mut memory, + 4, // topics_ptr + topics_len, // topics_len + 4 + topics_len, // data_ptr + 0, // data_len + ); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); } - // Benchmark debug_message call with zero input data. + // Benchmark debug_message call // Whereas this function is used in RPC mode only, it still should be secured // against an excessive use. - #[benchmark(pov_mode = Measured)] - fn seal_debug_message(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory { min_pages: 1, max_pages: 1 }), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_debug_message", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - call_body: Some(body::repeated( - r, - &[ - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), // value_len - Instruction::Call(0), - Instruction::Drop, - ], - )), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.enable_debug_message(); - call_builder!(func, setup: setup); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } - - // Vary size of input in bytes up to maximum allowed contract memory - // or maximum allowed debug buffer size, whichever is less. + // + // i: size of input in bytes up to maximum allowed contract memory or maximum allowed debug + // buffer size, whichever is less. #[benchmark] - fn seal_debug_message_per_byte( + fn seal_debug_message( i: Linear< 0, { @@ -1291,1619 +996,586 @@ mod benchmarks { .min(T::MaxDebugBufferLen::get()) }, >, - ) -> Result<(), BenchmarkError> { - // We benchmark versus messages containing printable ASCII codes. - // About 1Kb goes to the contract code instructions, - // whereas all the space left we use for the initialization of the debug messages data. - let message = (0..T::MaxCodeLen::get() - 1024) - .zip((32..127).cycle()) - .map(|i| i.1) - .collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory { - min_pages: T::Schedule::get().limits.memory_pages, - max_pages: T::Schedule::get().limits.memory_pages, - }), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_debug_message", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: message }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(i as i32), // value_len - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); + ) { + let mut setup = CallSetup::::default(); setup.enable_debug_message(); - call_builder!(func, setup: setup); + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); + // Fill memory with printable ASCII bytes. + let mut memory = (0..i).zip((32..127).cycle()).map(|i| i.1).collect::>(); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_debug_message(&mut runtime, &mut memory, 0, i); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); assert_eq!(setup.debug_message().unwrap().len() as u32, i); - Ok(()) } - // Only the overhead of calling the function itself with minimal arguments. - // The contract is a bit more complex because it needs to use different keys in order - // to generate unique storage accesses. However, it is still dominated by the storage - // accesses. We store something at all the keys that we are about to write to - // because re-writing at an existing key is always more expensive than writing - // to an key with no data behind it. - // - // # Note - // - // We need to use a smaller `r` because the keys are big and writing them all into the wasm - // might exceed the code size. + // n: new byte size + // o: old byte size #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_set_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0..r) - .map(|n| { - let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); - h - }) - .collect::>(); - let keys_bytes = keys.iter().flatten().cloned().collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal2", - name: "set_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: keys_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // value_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - - call_builder!(func, instance, code); - let info = instance.info()?; - for key in keys { - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - } - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } - - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_set_storage_per_new_byte( + fn seal_set_storage( n: Linear<0, { T::Schedule::get().limits.payload_len }>, + o: Linear<0, { T::Schedule::get().limits.payload_len }>, ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal2", - name: "set_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key.clone() }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(n as i32), // value_len - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } + let key = Key::::try_from_var(vec![0u8; max_key_len as usize]) + .map_err(|_| "Key has wrong length")?; + let value = vec![1u8; n as usize]; - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_set_storage_per_old_byte( - n: Linear<0, { T::Schedule::get().limits.payload_len }>, - ) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal2", - name: "set_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key.clone() }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), /* value_len is 0 as testing vs - * pre-existing value len */ - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); + build_runtime!(runtime, instance, memory: [ key.to_vec(), value.clone(), ]); let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![42u8; n as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } - - // Similar to seal_set_storage. We store all the keys that we are about to - // delete beforehand in order to prevent any optimizations that could occur when - // deleting a non existing key. We generate keys of a maximum length, and have to - // the amount of runs in order to make resulting contract code size less than MaxCodeLen. - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_clear_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0..r) - .map(|n| { - let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); - h - }) - .collect::>(); - let key_bytes = keys.iter().flatten().cloned().collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "clear_storage", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info()?; - for key in keys { - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) + info.write(&key, Some(vec![42u8; o as usize]), None, false) .map_err(|_| "Failed to write to storage during setup.")?; - } - >::insert(&instance.account_id, info); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal2_set_storage( + &mut runtime, + &mut memory, + 0, // key_ptr + max_key_len, // key_len + max_key_len, // value_ptr + n, // value_len + ); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert_eq!(info.read(&key).unwrap(), value); Ok(()) } #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_clear_storage_per_byte( + fn seal_clear_storage( n: Linear<0, { T::Schedule::get().limits.payload_len }>, ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "clear_storage", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key.clone() }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); + let key = Key::::try_from_var(vec![0u8; max_key_len as usize]) + .map_err(|_| "Key has wrong length")?; + build_runtime!(runtime, instance, memory: [ key.to_vec(), ]); let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![42u8; n as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } - // We make sure that all storage accesses are to unique keys. - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_get_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0..r) - .map(|n| { - let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); - h - }) - .collect::>(); - let key_bytes = keys.iter().flatten().cloned().collect::>(); - let key_bytes_len = key_bytes.len(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "get_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: key_bytes }, - DataSegment { - offset: key_bytes_len as u32, - value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), - }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, max_key_len), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr - Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info()?; - for key in keys { - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) + info.write(&key, Some(vec![42u8; n as usize]), None, false) .map_err(|_| "Failed to write to storage during setup.")?; - } - >::insert(&instance.account_id, info); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal1_clear_storage(&mut runtime, &mut memory, 0, max_key_len); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); + assert!(info.read(&key).is_none()); Ok(()) } #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_get_storage_per_byte( + fn seal_get_storage( n: Linear<0, { T::Schedule::get().limits.payload_len }>, ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "get_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: key.clone() }, - DataSegment { - offset: max_key_len, - value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), - }, - ], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const((max_key_len + 4) as i32), // out_ptr - Instruction::I32Const(max_key_len as i32), // out_len_ptr - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); + let key = Key::::try_from_var(vec![0u8; max_key_len as usize]) + .map_err(|_| "Key has wrong length")?; + build_runtime!(runtime, instance, memory: [ key.to_vec(), n.to_le_bytes(), vec![0u8; n as _], ]); let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![42u8; n as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - >::insert(&instance.account_id, info); - let res; + info.write(&key, Some(vec![42u8; n as usize]), None, false) + .map_err(|_| "Failed to write to storage during setup.")?; + + let out_ptr = max_key_len + 4; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal1_get_storage( + &mut runtime, + &mut memory, + 0, // key_ptr + max_key_len, // key_len + out_ptr, // out_ptr + max_key_len, // out_len_ptr + ); } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert_eq!(&info.read(&key).unwrap(), &memory[out_ptr as usize..]); Ok(()) } - // We make sure that all storage accesses are to unique keys. #[benchmark(skip_meta, pov_mode = Measured)] fn seal_contains_storage( - r: Linear<0, { API_BENCHMARK_RUNS / 2 }>, + n: Linear<0, { T::Schedule::get().limits.payload_len }>, ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0..r) - .map(|n| { - let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); - h - }) - .collect::>(); - let key_bytes = keys.iter().flatten().cloned().collect::>(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "contains_storage", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); + let key = Key::::try_from_var(vec![0u8; max_key_len as usize]) + .map_err(|_| "Key has wrong length")?; + build_runtime!(runtime, instance, memory: [ key.to_vec(), ]); let info = instance.info()?; - for key in keys { - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) + + info.write(&key, Some(vec![42u8; n as usize]), None, false) .map_err(|_| "Failed to write to storage during setup.")?; - } - >::insert(&instance.account_id, info); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal1_contains_storage(&mut runtime, &mut memory, 0, max_key_len); } - assert_eq!(res.did_revert(), false); + + assert_eq!(result.unwrap(), n); Ok(()) } #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_contains_storage_per_byte( + fn seal_take_storage( n: Linear<0, { T::Schedule::get().limits.payload_len }>, ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "contains_storage", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: key.clone() }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); + let key = Key::::try_from_var(vec![0u8; max_key_len as usize]) + .map_err(|_| "Key has wrong length")?; + build_runtime!(runtime, instance, memory: [ key.to_vec(), n.to_le_bytes(), vec![0u8; n as _], ]); let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![42u8; n as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - >::insert(&instance.account_id, info); - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } - - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_take_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0..r) - .map(|n| { - let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); - h - }) - .collect::>(); - let key_bytes = keys.iter().flatten().cloned().collect::>(); - let key_bytes_len = key_bytes.len(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "take_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: key_bytes }, - DataSegment { - offset: key_bytes_len as u32, - value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), - }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr - Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info()?; - for key in keys { - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![]), - None, - false, - ) + let value = vec![42u8; n as usize]; + info.write(&key, Some(value.clone()), None, false) .map_err(|_| "Failed to write to storage during setup.")?; - } - >::insert(&instance.account_id, info); - let res; + let out_ptr = max_key_len + 4; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_take_storage( + &mut runtime, + &mut memory, + 0, // key_ptr + max_key_len, // key_len + out_ptr, // out_ptr + max_key_len, // out_len_ptr + ); } - assert_eq!(res.did_revert(), false); - Ok(()) - } - #[benchmark(skip_meta, pov_mode = Measured)] - fn seal_take_storage_per_byte( - n: Linear<0, { T::Schedule::get().limits.payload_len }>, - ) -> Result<(), BenchmarkError> { - let max_key_len = T::MaxStorageKeyLen::get(); - let key = vec![0u8; max_key_len as usize]; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "take_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: key.clone() }, - DataSegment { - offset: max_key_len, - value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), - }, - ], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const((max_key_len + 4) as i32), // out_ptr - Instruction::I32Const(max_key_len as i32), // out_len_ptr - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - call_builder!(func, instance, code); - let info = instance.info()?; - info.write( - &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, - Some(vec![42u8; n as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; - >::insert(&instance.account_id, info); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert!(&info.read(&key).is_none()); + assert_eq!(&value, &memory[out_ptr as usize..]); Ok(()) } // We transfer to unique accounts. #[benchmark(pov_mode = Measured)] - fn seal_transfer(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { - let accounts = - (0..r).map(|i| account::("receiver", i, 0)).collect::>(); - let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); - let account_bytes = accounts.iter().flat_map(|x| x.encode()).collect(); + fn seal_transfer() { + let account = account::("receiver", 0, 0); let value = Pallet::::min_balance(); assert!(value > 0u32.into()); - let value_bytes = value.encode(); - let value_len = value_bytes.len(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_transfer", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: value_bytes }, - DataSegment { offset: value_len as u32, value: account_bytes }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(value_len as u32, account_len as u32), // account_ptr - Regular(Instruction::I32Const(account_len as i32)), // account_len - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(value_len as i32)), // value_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.set_balance(value * (r + 1).into()); - call_builder!(func, setup: setup); - for account in &accounts { - assert_eq!(T::Currency::total_balance(account), 0u32.into()); - } + let mut setup = CallSetup::::default(); + setup.set_balance(value); + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - - for account in &accounts { - assert_eq!(T::Currency::total_balance(account), value); - } - Ok(()) - } - - // We call unique accounts. - // - // This is a slow call: We reduce the number of runs. - #[benchmark(pov_mode = Measured)] - fn seal_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let dummy_code = WasmModule::::dummy_with_bytes(0); - let callees = (0..r) - .map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![])) - .collect::, _>>()?; - let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0); - let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect(); - let value: BalanceOf = 0u32.into(); + let account_bytes = account.encode(); + let account_len = account_bytes.len() as u32; let value_bytes = value.encode(); - let value_len = BalanceOf::::max_encoded_len() as u32; - // Set an own limit every 2nd call - let own_limit = (u32::MAX - 100).into(); - let deposits = (0..r) - .map(|i| if i % 2 == 0 { 0u32.into() } else { own_limit }) - .collect::>>(); - let deposits_bytes: Vec = deposits.iter().flat_map(|i| i.encode()).collect(); - let deposits_len = deposits_bytes.len() as u32; - let deposit_len = value_len; - let callee_offset = value_len + deposits_len; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal2", - name: "call", - params: vec![ - ValueType::I32, - ValueType::I32, - ValueType::I64, - ValueType::I64, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: value_bytes }, - DataSegment { offset: value_len, value: deposits_bytes }, - DataSegment { offset: callee_offset, value: callee_bytes }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Regular(Instruction::I32Const(0)), // flags - Counter(callee_offset, callee_len as u32), // callee_ptr - Regular(Instruction::I64Const(0)), // ref_time weight - Regular(Instruction::I64Const(0)), // proof_size weight - Counter(value_len, deposit_len as u32), // deposit_limit_ptr - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.set_storage_deposit_limit(BalanceOf::::from(u32::MAX.into())); - call_builder!(func, setup: setup); + let value_len = value_bytes.len() as u32; + let mut memory = memory!(account_bytes, value_bytes,); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_transfer( + &mut runtime, + &mut memory, + 0, // account_ptr + account_len, + account_len, + value_len, + ); } - assert_eq!(res.did_revert(), false); - Ok(()) - } - // This is a slow call: We reduce the number of runs. - #[benchmark(pov_mode = Measured)] - fn seal_delegate_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let hashes = (0..r) - .map(|i| { - let code = WasmModule::::dummy_with_bytes(i); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(code.code, caller)?; - Ok(code.hash) - }) - .collect::, &'static str>>()?; - let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::>(); - let hashes_offset = 0; - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_delegate_call", - params: vec![ - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: hashes_offset as u32, value: hashes_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Regular(Instruction::I32Const(0)), // flags - Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) + assert_ok!(result); } + // t: with or without some value to transfer + // i: size of the input data #[benchmark(pov_mode = Measured)] - fn seal_call_per_transfer_clone_byte( - t: Linear<0, { 1 }>, - c: Linear<0, { code::max_pages::() * 64 * 1024 }>, - ) -> Result<(), BenchmarkError> { - let callee = Contract::with_index(5, >::dummy(), vec![])?; + fn seal_call(t: Linear<0, 1>, i: Linear<0, { code::max_pages::() * 64 * 1024 }>) { + let Contract { account_id: callee, .. } = + Contract::::with_index(1, WasmModule::dummy(), vec![]).unwrap(); + let callee_bytes = callee.encode(); + let callee_len = callee_bytes.len() as u32; + let value: BalanceOf = t.into(); let value_bytes = value.encode(); - let value_len = value_bytes.len(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "seal_call", - params: vec![ - ValueType::I32, - ValueType::I32, - ValueType::I64, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: value_bytes }, - DataSegment { offset: value_len as u32, value: callee.account_id.encode() }, - ], - call_body: Some(body::plain(vec![ - Instruction::I32Const(CallFlags::CLONE_INPUT.bits() as i32), // flags - Instruction::I32Const(value_len as i32), // callee_ptr - Instruction::I64Const(0), // gas - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), // input_data_ptr - Instruction::I32Const(0), // input_data_len - Instruction::I32Const(SENTINEL as i32), // output_ptr - Instruction::I32Const(0), // output_len_ptr - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.set_data(vec![42; c as usize]); - call_builder!(func, setup: setup); - let res; - #[block] - { - res = func.call(); + let deposit: BalanceOf = (u32::MAX - 100).into(); + let deposit_bytes = deposit.encode(); + let deposit_len = deposit_bytes.len() as u32; + + let mut setup = CallSetup::::default(); + setup.set_storage_deposit_limit(deposit); + setup.set_data(vec![42; i as usize]); + setup.set_origin(Origin::from_account_id(setup.contract().account_id.clone())); + + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); + let mut memory = memory!(callee_bytes, deposit_bytes, value_bytes,); + + let result; + #[block] + { + result = BenchEnv::seal2_call( + &mut runtime, + &mut memory, + CallFlags::CLONE_INPUT.bits(), // flags + 0, // callee_ptr + 0, // ref_time_limit + 0, // proof_size_limit + callee_len, // deposit_ptr + callee_len + deposit_len, // value_ptr + 0, // input_data_ptr + 0, // input_data_len + SENTINEL, // output_ptr + 0, // output_len_ptr + ); } - assert_eq!(res.did_revert(), false); - Ok(()) + + assert_ok!(result); } - // We assume that every instantiate sends at least the minimum balance. - // This is a slow call: we reduce the number of runs. #[benchmark(pov_mode = Measured)] - fn seal_instantiate(r: Linear<1, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { - let hashes = (0..r) - .map(|i| { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - call_body: Some(body::plain(vec![ - // We need to add this in order to make contracts unique, - // so that they can be deployed from the same sender. - Instruction::I32Const(i as i32), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(code.code, caller)?; - Ok(code.hash) - }) - .collect::, &'static str>>()?; - let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::>(); - let hashes_len = &hashes_bytes.len(); - let value = Pallet::::min_balance(); - assert!(value > 0u32.into()); - let value_bytes = value.encode(); - let value_len = BalanceOf::::max_encoded_len(); - let addr_len = T::AccountId::max_encoded_len(); - // Offsets where to place static data in contract memory. - let hashes_offset = value_len; - let addr_len_offset = hashes_offset + hashes_len; - let addr_offset = addr_len_offset + addr_len; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal2", - name: "instantiate", - params: vec![ - ValueType::I32, - ValueType::I64, - ValueType::I64, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: value_bytes }, - DataSegment { offset: hashes_offset as u32, value: hashes_bytes }, - DataSegment { - offset: addr_len_offset as u32, - value: addr_len.to_le_bytes().into(), - }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr - Regular(Instruction::I64Const(0)), // ref_time weight - Regular(Instruction::I64Const(0)), // proof_size weight - Regular(Instruction::I32Const(SENTINEL as i32)), /* deposit limit ptr: use - * parent's limit */ - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr - Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr - Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::I32Const(0)), // salt_ptr - Regular(Instruction::I32Const(0)), // salt_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); - setup.set_balance((value + Pallet::::min_balance()) * (r + 1).into()); - call_builder!(func, instance, setup: setup); - let addresses = hashes - .iter() - .map(|hash| Contracts::::contract_address(&instance.account_id, hash, &[], &[])) - .collect::>(); - - for addr in &addresses { - if ContractInfoOf::::get(&addr).is_some() { - return Err("Expected that contract does not exist at this point.".into()); - } - } + fn seal_delegate_call() -> Result<(), BenchmarkError> { + let hash = Contract::::with_index(1, WasmModule::dummy(), vec![])?.info()?.code_hash; + + let mut setup = CallSetup::::default(); + setup.set_origin(Origin::from_account_id(setup.contract().account_id.clone())); + + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); + let mut memory = memory!(hash.encode(),); - let res; + let result; #[block] { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - for addr in &addresses { - ContractInfoOf::::get(&addr).ok_or("Contract should have been instantiated")?; + result = BenchEnv::seal0_delegate_call( + &mut runtime, + &mut memory, + 0, // flags + 0, // code_hash_ptr + 0, // input_data_ptr + 0, // input_data_len + SENTINEL, // output_ptr + 0, + ); } + + assert_ok!(result); Ok(()) } + // t: value to transfer + // i: size of input in bytes + // s: size of salt in bytes #[benchmark(pov_mode = Measured)] - fn seal_instantiate_per_transfer_input_salt_byte( + fn seal_instantiate( t: Linear<0, 1>, i: Linear<0, { (code::max_pages::() - 1) * 64 * 1024 }>, s: Linear<0, { (code::max_pages::() - 1) * 64 * 1024 }>, ) -> Result<(), BenchmarkError> { - let callee_code = WasmModule::::dummy(); - let hash_bytes = callee_code.hash.encode(); - let hash_len = hash_bytes.len(); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(callee_code.code, caller)?; + let hash = Contract::::with_index(1, WasmModule::dummy(), vec![])?.info()?.code_hash; + let hash_bytes = hash.encode(); + let hash_len = hash_bytes.len() as u32; + let value: BalanceOf = t.into(); let value_bytes = value.encode(); + let value_len = value_bytes.len() as u32; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal1", - name: "seal_instantiate", - params: vec![ - ValueType::I32, - ValueType::I64, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: hash_bytes }, - DataSegment { offset: hash_len as u32, value: value_bytes }, - ], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0 as i32), // code_hash_ptr - Instruction::I64Const(0), // gas - Instruction::I32Const(hash_len as i32), // value_ptr - Instruction::I32Const(0 as i32), // input_data_ptr - Instruction::I32Const(i as i32), // input_data_len - Instruction::I32Const(SENTINEL as i32), // address_ptr - Instruction::I32Const(0), // address_len_ptr - Instruction::I32Const(SENTINEL as i32), // output_ptr - Instruction::I32Const(0), // output_len_ptr - Instruction::I32Const(0 as i32), // salt_ptr - Instruction::I32Const(s as i32), // salt_len - Instruction::Call(0), - Instruction::I32Eqz, - Instruction::If(BlockType::NoResult), - Instruction::Nop, - Instruction::Else, - Instruction::Unreachable, - Instruction::End, - Instruction::End, - ])), - ..Default::default() - }); - let mut setup = CallSetup::::new(code); + let deposit: BalanceOf = 0u32.into(); + let deposit_bytes = deposit.encode(); + let deposit_len = deposit_bytes.len() as u32; + + let mut setup = CallSetup::::default(); + setup.set_origin(Origin::from_account_id(setup.contract().account_id.clone())); setup.set_balance(value + (Pallet::::min_balance() * 2u32.into())); - call_builder!(func, setup: setup); - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) - } + let account_id = &setup.contract().account_id.clone(); + let (mut ext, _) = setup.ext(); + let mut runtime = crate::wasm::Runtime::new(&mut ext, vec![]); - // Only the overhead of calling the function itself with minimal arguments. - #[benchmark(pov_mode = Measured)] - fn seal_hash_sha2_256(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::hasher("seal_hash_sha2_256", r, 0)); + let input = vec![42u8; i as _]; + let salt = vec![42u8; s as _]; + let addr = Contracts::::contract_address(&account_id, &hash, &input, &salt); + let mut memory = memory!(hash_bytes, deposit_bytes, value_bytes, input, salt,); - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - } - - // `n`: Input to hash in bytes - #[benchmark(pov_mode = Measured)] - fn seal_hash_sha2_256_per_byte(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { - call_builder!(func, WasmModule::hasher("seal_hash_sha2_256", 1, n)); - - let res; - #[block] - { - res = func.call(); + let mut offset = { + let mut current = 0u32; + move |after: u32| { + current += after; + current + } + }; + + assert!(ContractInfoOf::::get(&addr).is_none()); + + let result; + #[block] + { + result = BenchEnv::seal2_instantiate( + &mut runtime, + &mut memory, + 0, // code_hash_ptr + 0, // ref_time_limit + 0, // proof_size_limit + offset(hash_len), // deposit_ptr + offset(deposit_len), // value_ptr + offset(value_len), // input_data_ptr + i, // input_data_len + SENTINEL, // address_ptr + 0, // address_len_ptr + SENTINEL, // output_ptr + 0, // output_len_ptr + offset(i), // salt_ptr + s, // salt_len + ); } - assert_eq!(res.did_revert(), false); - } - // Only the overhead of calling the function itself with minimal arguments. - #[benchmark(pov_mode = Measured)] - fn seal_hash_keccak_256(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::hasher("seal_hash_keccak_256", r, 0)); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); + assert_ok!(result); + assert!(ContractInfoOf::::get(&addr).is_some()); + Ok(()) } // `n`: Input to hash in bytes #[benchmark(pov_mode = Measured)] - fn seal_hash_keccak_256_per_byte(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { - call_builder!(func, WasmModule::hasher("seal_hash_keccak_256", 1, n)); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - } - - // Only the overhead of calling the function itself with minimal arguments. - #[benchmark(pov_mode = Measured)] - fn seal_hash_blake2_256(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::hasher("seal_hash_blake2_256", r, 0)); + fn seal_hash_sha2_256(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { + build_runtime!(runtime, memory: [[0u8; 32], vec![0u8; n as usize], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_hash_sha2_256(&mut runtime, &mut memory, 32, n, 0); } - assert_eq!(res.did_revert(), false); + assert_eq!(sp_io::hashing::sha2_256(&memory[32..]), &memory[0..32]); + assert_ok!(result); } // `n`: Input to hash in bytes #[benchmark(pov_mode = Measured)] - fn seal_hash_blake2_256_per_byte(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { - call_builder!(func, WasmModule::hasher("seal_hash_blake2_256", 1, n)); + fn seal_hash_keccak_256(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { + build_runtime!(runtime, memory: [[0u8; 32], vec![0u8; n as usize], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_hash_keccak_256(&mut runtime, &mut memory, 32, n, 0); } - assert_eq!(res.did_revert(), false); + assert_eq!(sp_io::hashing::keccak_256(&memory[32..]), &memory[0..32]); + assert_ok!(result); } - // Only the overhead of calling the function itself with minimal arguments. + // `n`: Input to hash in bytes #[benchmark(pov_mode = Measured)] - fn seal_hash_blake2_128(r: Linear<0, API_BENCHMARK_RUNS>) { - call_builder!(func, WasmModule::hasher("seal_hash_blake2_128", r, 0)); + fn seal_hash_blake2_256(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { + build_runtime!(runtime, memory: [[0u8; 32], vec![0u8; n as usize], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_hash_blake2_256(&mut runtime, &mut memory, 32, n, 0); } - assert_eq!(res.did_revert(), false); + assert_eq!(sp_io::hashing::blake2_256(&memory[32..]), &memory[0..32]); + assert_ok!(result); } // `n`: Input to hash in bytes #[benchmark(pov_mode = Measured)] - fn seal_hash_blake2_128_per_byte(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { - call_builder!(func, WasmModule::hasher("seal_hash_blake2_128", 1, n)); + fn seal_hash_blake2_128(n: Linear<0, { code::max_pages::() * 64 * 1024 }>) { + build_runtime!(runtime, memory: [[0u8; 16], vec![0u8; n as usize], ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_hash_blake2_128(&mut runtime, &mut memory, 16, n, 0); } - assert_eq!(res.did_revert(), false); + assert_eq!(sp_io::hashing::blake2_128(&memory[16..]), &memory[0..16]); + assert_ok!(result); } // `n`: Message input length to verify in bytes. // need some buffer so the code size does not exceed the max code size. #[benchmark(pov_mode = Measured)] - fn seal_sr25519_verify_per_byte( - n: Linear<0, { T::MaxCodeLen::get() - 255 }>, - ) -> Result<(), BenchmarkError> { + fn seal_sr25519_verify(n: Linear<0, { T::MaxCodeLen::get() - 255 }>) { let message = (0..n).zip((32u8..127u8).cycle()).map(|(_, c)| c).collect::>(); - let message_len = message.len() as i32; + let message_len = message.len() as u32; let key_type = sp_core::crypto::KeyTypeId(*b"code"); let pub_key = sp_io::crypto::sr25519_generate(key_type, None); let sig = sp_io::crypto::sr25519_sign(key_type, &pub_key, &message).expect("Generates signature"); let sig = AsRef::<[u8; 64]>::as_ref(&sig).to_vec(); + let sig_len = sig.len() as u32; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "sr25519_verify", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: sig }, - DataSegment { offset: 64, value: pub_key.to_vec() }, - DataSegment { offset: 96, value: message }, - ], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // signature_ptr - Instruction::I32Const(64), // pub_key_ptr - Instruction::I32Const(message_len), // message_len - Instruction::I32Const(96), // message_ptr - Instruction::Call(0), - Instruction::Drop, - Instruction::End, - ])), - ..Default::default() - }); - - call_builder!(func, code); + build_runtime!(runtime, memory: [sig, pub_key.to_vec(), message, ]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_sr25519_verify( + &mut runtime, + &mut memory, + 0, // signature_ptr + sig_len, // pub_key_ptr + message_len, // message_len + sig_len + pub_key.len() as u32, // message_ptr + ); } - assert_eq!(res.did_revert(), false); - Ok(()) - } - // Only calling the function itself with valid arguments. - // It generates different private keys and signatures for the message "Hello world". - // This is a slow call: We reduce the number of runs. - #[benchmark(pov_mode = Measured)] - fn seal_sr25519_verify( - r: Linear<0, { API_BENCHMARK_RUNS / 10 }>, - ) -> Result<(), BenchmarkError> { - let message = b"Hello world".to_vec(); - let message_len = message.len() as i32; - let key_type = sp_core::crypto::KeyTypeId(*b"code"); - let sig_params = (0..r) - .flat_map(|_| { - let pub_key = sp_io::crypto::sr25519_generate(key_type, None); - let sig = sp_io::crypto::sr25519_sign(key_type, &pub_key, &message) - .expect("Generates signature"); - let data: [u8; 96] = [AsRef::<[u8]>::as_ref(&sig), AsRef::<[u8]>::as_ref(&pub_key)] - .concat() - .try_into() - .unwrap(); - data - }) - .collect::>(); - let sig_params_len = sig_params.len() as i32; - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "sr25519_verify", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: sig_params }, - DataSegment { offset: sig_params_len as u32, value: message }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, 96), // signature_ptr - Counter(64, 96), // pub_key_ptr - Regular(Instruction::I32Const(message_len)), // message_len - Regular(Instruction::I32Const(sig_params_len)), // message_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); - - let res; - #[block] - { - res = func.call(); - } - assert_eq!(res.did_revert(), false); - Ok(()) + assert_eq!(result.unwrap(), ReturnErrorCode::Success); } - // Only calling the function itself with valid arguments. - // It generates different private keys and signatures for the message "Hello world". - // This is a slow call: We reduce the number of runs. #[benchmark(pov_mode = Measured)] - fn seal_ecdsa_recover(r: Linear<0, { API_BENCHMARK_RUNS / 10 }>) -> Result<(), BenchmarkError> { + fn seal_ecdsa_recover() { let message_hash = sp_io::hashing::blake2_256("Hello world".as_bytes()); let key_type = sp_core::crypto::KeyTypeId(*b"code"); - let signatures = (0..r) - .map(|_| { - let pub_key = sp_io::crypto::ecdsa_generate(key_type, None); - let sig = sp_io::crypto::ecdsa_sign_prehashed(key_type, &pub_key, &message_hash) - .expect("Generates signature"); - AsRef::<[u8; 65]>::as_ref(&sig).to_vec() - }) - .collect::>(); - let signatures = signatures.iter().flatten().cloned().collect::>(); - let signatures_bytes_len = signatures.len() as i32; - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_ecdsa_recover", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { offset: 0, value: message_hash[..].to_vec() }, - DataSegment { offset: 32, value: signatures }, - ], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(32, 65), // signature_ptr - Regular(Instruction::I32Const(0)), // message_hash_ptr - Regular(Instruction::I32Const(signatures_bytes_len + 32)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + let signature = { + let pub_key = sp_io::crypto::ecdsa_generate(key_type, None); + let sig = sp_io::crypto::ecdsa_sign_prehashed(key_type, &pub_key, &message_hash) + .expect("Generates signature"); + AsRef::<[u8; 65]>::as_ref(&sig).to_vec() + }; - let res; + build_runtime!(runtime, memory: [signature, message_hash, [0u8; 33], ]); + + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_ecdsa_recover( + &mut runtime, + &mut memory, + 0, // signature_ptr + 65, // message_hash_ptr + 65 + 32, // output_ptr + ); } - assert_eq!(res.did_revert(), false); - Ok(()) + + assert_eq!(result.unwrap(), ReturnErrorCode::Success); } // Only calling the function itself for the list of // generated different ECDSA keys. // This is a slow call: We reduce the number of runs. #[benchmark(pov_mode = Measured)] - fn seal_ecdsa_to_eth_address( - r: Linear<0, { API_BENCHMARK_RUNS / 10 }>, - ) -> Result<(), BenchmarkError> { + fn seal_ecdsa_to_eth_address() { let key_type = sp_core::crypto::KeyTypeId(*b"code"); - let pub_keys_bytes = (0..r) - .flat_map(|_| sp_io::crypto::ecdsa_generate(key_type, None).0) - .collect::>(); - let pub_keys_bytes_len = pub_keys_bytes.len() as i32; - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_ecdsa_to_eth_address", - params: vec![ValueType::I32, ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: pub_keys_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, 33), // pub_key_ptr - Regular(Instruction::I32Const(pub_keys_bytes_len)), // out_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + let pub_key_bytes = sp_io::crypto::ecdsa_generate(key_type, None).0; + build_runtime!(runtime, memory: [[0u8; 20], pub_key_bytes,]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_ecdsa_to_eth_address( + &mut runtime, + &mut memory, + 20, // key_ptr + 0, // output_ptr + ); } - assert_eq!(res.did_revert(), false); - Ok(()) + + assert_ok!(result); + assert_eq!(&memory[..20], runtime.ext().ecdsa_to_eth_address(&pub_key_bytes).unwrap()); } #[benchmark(pov_mode = Measured)] - fn seal_set_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { - let code_hashes = (0..r) - .map(|i| { - let new_code = WasmModule::::dummy_with_bytes(i); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(new_code.code, caller)?; - Ok(new_code.hash) - }) - .collect::, &'static str>>()?; - let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_set_code_hash", - params: vec![ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + fn seal_set_code_hash() -> Result<(), BenchmarkError> { + let code_hash = + Contract::::with_index(1, WasmModule::dummy(), vec![])?.info()?.code_hash; + + build_runtime!(runtime, memory: [ code_hash.encode(),]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_set_code_hash(&mut runtime, &mut memory, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); Ok(()) } #[benchmark(pov_mode = Measured)] - fn lock_delegate_dependency( - r: Linear<0, { T::MaxDelegateDependencies::get() }>, - ) -> Result<(), BenchmarkError> { - let code_hashes = (0..r) - .map(|i| { - let new_code = WasmModule::::dummy_with_bytes(65 + i); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(new_code.code, caller)?; - Ok(new_code.hash) - }) - .collect::, &'static str>>()?; - let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "lock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None, - }], - data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + fn lock_delegate_dependency() -> Result<(), BenchmarkError> { + let code_hash = Contract::::with_index(1, WasmModule::dummy_with_bytes(1), vec![])? + .info()? + .code_hash; - let res; + build_runtime!(runtime, memory: [ code_hash.encode(),]); + + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_lock_delegate_dependency(&mut runtime, &mut memory, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); Ok(()) } #[benchmark] - fn unlock_delegate_dependency( - r: Linear<0, { T::MaxDelegateDependencies::get() }>, - ) -> Result<(), BenchmarkError> { - let code_hashes = (0..r) - .map(|i| { - let new_code = WasmModule::::dummy_with_bytes(65 + i); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::()); - Contracts::::store_code_raw(new_code.code, caller)?; - Ok(new_code.hash) - }) - .collect::, &'static str>>()?; + fn unlock_delegate_dependency() -> Result<(), BenchmarkError> { + let code_hash = Contract::::with_index(1, WasmModule::dummy_with_bytes(1), vec![])? + .info()? + .code_hash; - let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); - let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); - - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ - ImportedFunction { - module: "seal0", - name: "unlock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None, - }, - ImportedFunction { - module: "seal0", - name: "lock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None, - }, - ], - data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], - deploy_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(1)), - ], - )), - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + build_runtime!(runtime, memory: [ code_hash.encode(),]); + BenchEnv::seal0_lock_delegate_dependency(&mut runtime, &mut memory, 0).unwrap(); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_unlock_delegate_dependency(&mut runtime, &mut memory, 0); } - assert_eq!(res.did_revert(), false); + + assert_ok!(result); Ok(()) } #[benchmark(pov_mode = Measured)] - fn seal_reentrance_count(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "reentrance_count", - params: vec![], - return_type: Some(ValueType::I32), - }], - call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), - ..Default::default() - }); - let instance = Contract::::new(code, vec![])?; - let origin = RawOrigin::Signed(instance.caller.clone()); - #[extrinsic_call] - call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); - Ok(()) + fn seal_reentrance_count() { + build_runtime!(runtime, memory: []); + let result; + #[block] + { + result = BenchEnv::seal0_reentrance_count(&mut runtime, &mut memory) + } + + assert_eq!(result.unwrap(), 0); } #[benchmark(pov_mode = Measured)] - fn seal_account_reentrance_count( - r: Linear<0, API_BENCHMARK_RUNS>, - ) -> Result<(), BenchmarkError> { - let dummy_code = WasmModule::::dummy_with_bytes(0); - let accounts = (0..r) - .map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![])) - .collect::, _>>()?; - let account_id_len = accounts.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0); - let account_id_bytes = accounts.iter().flat_map(|x| x.account_id.encode()).collect(); - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "account_reentrance_count", - params: vec![ValueType::I32], - return_type: Some(ValueType::I32), - }], - data_segments: vec![DataSegment { offset: 0, value: account_id_bytes }], - call_body: Some(body::repeated_dyn( - r, - vec![ - Counter(0, account_id_len as u32), // account_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ], - )), - ..Default::default() - }); - call_builder!(func, code); + fn seal_account_reentrance_count() { + let Contract { account_id, .. } = + Contract::::with_index(1, WasmModule::dummy(), vec![]).unwrap(); + build_runtime!(runtime, memory: [account_id.encode(),]); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_account_reentrance_count(&mut runtime, &mut memory, 0); } - assert_eq!(res.did_revert(), false); - Ok(()) + + assert_eq!(result.unwrap(), 0); } #[benchmark(pov_mode = Measured)] - fn seal_instantiation_nonce(r: Linear<0, API_BENCHMARK_RUNS>) { - let code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "instantiation_nonce", - params: vec![], - return_type: Some(ValueType::I64), - }], - call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), - ..Default::default() - }); - call_builder!(func, code); + fn seal_instantiation_nonce() { + build_runtime!(runtime, memory: []); - let res; + let result; #[block] { - res = func.call(); + result = BenchEnv::seal0_instantiation_nonce(&mut runtime, &mut memory); } - assert_eq!(res.did_revert(), false); + + assert_eq!(result.unwrap(), 1); } // We load `i64` values from random linear memory locations and store the loaded diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs index 31cdadb4bb4373baee420b48cecfdd2b82862c42..992f7aaace312b69d21f40ff754124912eeba290 100644 --- a/substrate/frame/contracts/src/exec.rs +++ b/substrate/frame/contracts/src/exec.rs @@ -46,7 +46,7 @@ use sp_core::{ }; use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256}; use sp_runtime::{ - traits::{Convert, Dispatchable, Hash, Zero}, + traits::{Convert, Dispatchable, Zero}, DispatchError, }; use sp_std::{fmt::Debug, marker::PhantomData, mem, prelude::*, vec::Vec}; @@ -303,7 +303,7 @@ pub trait Ext: sealing::Sealed { fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()>; /// Tests sometimes need to modify and inspect the contract info directly. - #[cfg(test)] + #[cfg(any(test, feature = "runtime-benchmarks"))] fn contract_info(&mut self) -> &mut ContractInfo; /// Sets new code hash for existing contract. @@ -365,6 +365,11 @@ pub trait Ext: sealing::Sealed { &mut self, code_hash: &CodeHash, ) -> Result<(), DispatchError>; + + /// Returns the number of locked delegate dependencies. + /// + /// Note: Requires &mut self to access the contract info. + fn locked_delegate_dependencies_count(&mut self) -> usize; } /// Describes the different functions that can be exported by an [`Executable`]. @@ -983,16 +988,16 @@ where let caller = self.caller().account_id()?.clone(); // Deposit an instantiation event. - Contracts::::deposit_event( - vec![T::Hashing::hash_of(&caller), T::Hashing::hash_of(account_id)], - Event::Instantiated { deployer: caller, contract: account_id.clone() }, - ); + Contracts::::deposit_event(Event::Instantiated { + deployer: caller, + contract: account_id.clone(), + }); }, (ExportedFunction::Call, Some(code_hash)) => { - Contracts::::deposit_event( - vec![T::Hashing::hash_of(account_id), T::Hashing::hash_of(&code_hash)], - Event::DelegateCalled { contract: account_id.clone(), code_hash }, - ); + Contracts::::deposit_event(Event::DelegateCalled { + contract: account_id.clone(), + code_hash, + }); }, (ExportedFunction::Call, None) => { // If a special limit was set for the sub-call, we enforce it here. @@ -1002,10 +1007,10 @@ where frame.nested_storage.enforce_subcall_limit(contract)?; let caller = self.caller(); - Contracts::::deposit_event( - vec![T::Hashing::hash_of(&caller), T::Hashing::hash_of(&account_id)], - Event::Called { caller: caller.clone(), contract: account_id.clone() }, - ); + Contracts::::deposit_event(Event::Called { + caller: caller.clone(), + contract: account_id.clone(), + }); }, } @@ -1324,13 +1329,10 @@ where .charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(*deposit)); } - Contracts::::deposit_event( - vec![T::Hashing::hash_of(&frame.account_id), T::Hashing::hash_of(&beneficiary)], - Event::Terminated { - contract: frame.account_id.clone(), - beneficiary: beneficiary.clone(), - }, - ); + Contracts::::deposit_event(Event::Terminated { + contract: frame.account_id.clone(), + beneficiary: beneficiary.clone(), + }); Ok(()) } @@ -1422,7 +1424,7 @@ where } fn deposit_event(&mut self, topics: Vec, data: Vec) { - Contracts::::deposit_event( + Contracts::::deposit_indexed_event( topics, Event::ContractEmitted { contract: self.top_frame().account_id.clone(), data }, ); @@ -1500,7 +1502,7 @@ where ECDSAPublic::from(*pk).to_eth_address() } - #[cfg(test)] + #[cfg(any(test, feature = "runtime-benchmarks"))] fn contract_info(&mut self) -> &mut ContractInfo { self.top_frame_mut().contract_info() } @@ -1527,14 +1529,11 @@ where Self::increment_refcount(hash)?; Self::decrement_refcount(prev_hash); - Contracts::::deposit_event( - vec![T::Hashing::hash_of(&frame.account_id), hash, prev_hash], - Event::ContractCodeUpdated { - contract: frame.account_id.clone(), - new_code_hash: hash, - old_code_hash: prev_hash, - }, - ); + Contracts::::deposit_event(Event::ContractCodeUpdated { + contract: frame.account_id.clone(), + new_code_hash: hash, + old_code_hash: prev_hash, + }); Ok(()) } @@ -1611,6 +1610,10 @@ where .charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(deposit)); Ok(()) } + + fn locked_delegate_dependencies_count(&mut self) -> usize { + self.top_frame_mut().contract_info().delegate_dependencies_count() + } } mod sealing { @@ -1639,7 +1642,7 @@ mod tests { exec::ExportedFunction::*, gas::GasMeter, tests::{ - test_utils::{get_balance, hash, place_contract, set_balance}, + test_utils::{get_balance, place_contract, set_balance}, ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter, ALICE, BOB, CHARLIE, GAS_LIMIT, }, @@ -3164,7 +3167,7 @@ mod tests { caller: Origin::from_account_id(ALICE), contract: BOB, }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&BOB)], + topics: vec![], }, ] ); @@ -3264,7 +3267,7 @@ mod tests { caller: Origin::from_account_id(ALICE), contract: BOB, }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&BOB)], + topics: vec![], }, ] ); diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index 3e87eb9f37ea7fc023a76d8ac7dc048f7bed9f7d..6fab1a44ecb9c499f9d627810b75523041fdd096 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -135,7 +135,7 @@ use frame_system::{ use scale_info::TypeInfo; use smallvec::Array; use sp_runtime::{ - traits::{Convert, Dispatchable, Hash, Saturating, StaticLookup, Zero}, + traits::{Convert, Dispatchable, Saturating, StaticLookup, Zero}, DispatchError, RuntimeDebug, }; use sp_std::{fmt::Debug, prelude::*}; @@ -146,7 +146,7 @@ pub use crate::{ exec::Frame, migration::{MigrateSequence, Migration, NoopMigration}, pallet::*, - schedule::{HostFnWeights, InstructionWeights, Limits, Schedule}, + schedule::{InstructionWeights, Limits, Schedule}, wasm::Determinism, }; pub use weights::WeightInfo; @@ -833,14 +833,11 @@ pub mod pallet { }; >>::increment_refcount(code_hash)?; >>::decrement_refcount(contract.code_hash); - Self::deposit_event( - vec![T::Hashing::hash_of(&dest), code_hash, contract.code_hash], - Event::ContractCodeUpdated { - contract: dest.clone(), - new_code_hash: code_hash, - old_code_hash: contract.code_hash, - }, - ); + Self::deposit_event(Event::ContractCodeUpdated { + contract: dest.clone(), + new_code_hash: code_hash, + old_code_hash: contract.code_hash, + }); contract.code_hash = code_hash; Ok(()) }) @@ -1827,8 +1824,13 @@ impl Pallet { Ok(()) } - /// Deposit a pallet contracts event. Handles the conversion to the overarching event type. - fn deposit_event(topics: Vec, event: Event) { + /// Deposit a pallet contracts event. + fn deposit_event(event: Event) { + >::deposit_event(::RuntimeEvent::from(event)) + } + + /// Deposit a pallet contracts indexed event. + fn deposit_indexed_event(topics: Vec, event: Event) { >::deposit_event_indexed( &topics, ::RuntimeEvent::from(event).into(), diff --git a/substrate/frame/contracts/src/schedule.rs b/substrate/frame/contracts/src/schedule.rs index 06a7c2005aa5e46e814d6eff192775ca63881fae..a1fbdea4228bfe3238c6458db4f5d5425563fc56 100644 --- a/substrate/frame/contracts/src/schedule.rs +++ b/substrate/frame/contracts/src/schedule.rs @@ -22,7 +22,7 @@ use crate::{weights::WeightInfo, Config}; use codec::{Decode, Encode}; use core::marker::PhantomData; -use frame_support::{weights::Weight, DefaultNoBound}; +use frame_support::DefaultNoBound; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -60,9 +60,6 @@ pub struct Schedule { /// The weights for individual wasm instructions. pub instruction_weights: InstructionWeights, - - /// The weights for each imported function a contract is allowed to call. - pub host_fn_weights: HostFnWeights, } /// Describes the upper limits on various metrics. @@ -109,230 +106,6 @@ pub struct InstructionWeights { pub _phantom: PhantomData, } -/// Describes the weight for each imported function that a contract is allowed to call. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "runtime-benchmarks", derive(pallet_contracts_proc_macro::WeightDebug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -#[scale_info(skip_type_params(T))] -pub struct HostFnWeights { - /// Weight of calling `seal_caller`. - pub caller: Weight, - - /// Weight of calling `seal_is_contract`. - pub is_contract: Weight, - - /// Weight of calling `seal_code_hash`. - pub code_hash: Weight, - - /// Weight of calling `seal_own_code_hash`. - pub own_code_hash: Weight, - - /// Weight of calling `seal_caller_is_origin`. - pub caller_is_origin: Weight, - - /// Weight of calling `seal_caller_is_root`. - pub caller_is_root: Weight, - - /// Weight of calling `seal_address`. - pub address: Weight, - - /// Weight of calling `seal_gas_left`. - pub gas_left: Weight, - - /// Weight of calling `seal_balance`. - pub balance: Weight, - - /// Weight of calling `seal_value_transferred`. - pub value_transferred: Weight, - - /// Weight of calling `seal_minimum_balance`. - pub minimum_balance: Weight, - - /// Weight of calling `seal_block_number`. - pub block_number: Weight, - - /// Weight of calling `seal_now`. - pub now: Weight, - - /// Weight of calling `seal_weight_to_fee`. - pub weight_to_fee: Weight, - - /// Weight of calling `seal_input`. - pub input: Weight, - - /// Weight per input byte copied to contract memory by `seal_input`. - pub input_per_byte: Weight, - - /// Weight of calling `seal_return`. - pub r#return: Weight, - - /// Weight per byte returned through `seal_return`. - pub return_per_byte: Weight, - - /// Weight of calling `seal_terminate`. - pub terminate: Weight, - - /// Weight of calling `seal_random`. - pub random: Weight, - - /// Weight of calling `seal_reposit_event`. - pub deposit_event: Weight, - - /// Weight per topic supplied to `seal_deposit_event`. - pub deposit_event_per_topic: Weight, - - /// Weight per byte of an event deposited through `seal_deposit_event`. - pub deposit_event_per_byte: Weight, - - /// Weight of calling `seal_debug_message`. - pub debug_message: Weight, - - /// Weight of calling `seal_debug_message` per byte of the message. - pub debug_message_per_byte: Weight, - - /// Weight of calling `seal_set_storage`. - pub set_storage: Weight, - - /// Weight per written byte of an item stored with `seal_set_storage`. - pub set_storage_per_new_byte: Weight, - - /// Weight per overwritten byte of an item stored with `seal_set_storage`. - pub set_storage_per_old_byte: Weight, - - /// Weight of calling `seal_set_code_hash`. - pub set_code_hash: Weight, - - /// Weight of calling `seal_clear_storage`. - pub clear_storage: Weight, - - /// Weight of calling `seal_clear_storage` per byte of the stored item. - pub clear_storage_per_byte: Weight, - - /// Weight of calling `seal_contains_storage`. - pub contains_storage: Weight, - - /// Weight of calling `seal_contains_storage` per byte of the stored item. - pub contains_storage_per_byte: Weight, - - /// Weight of calling `seal_get_storage`. - pub get_storage: Weight, - - /// Weight per byte of an item received via `seal_get_storage`. - pub get_storage_per_byte: Weight, - - /// Weight of calling `seal_take_storage`. - pub take_storage: Weight, - - /// Weight per byte of an item received via `seal_take_storage`. - pub take_storage_per_byte: Weight, - - /// Weight of calling `seal_transfer`. - pub transfer: Weight, - - /// Weight of calling `seal_call`. - pub call: Weight, - - /// Weight of calling `seal_delegate_call`. - pub delegate_call: Weight, - - /// Weight surcharge that is claimed if `seal_call` does a balance transfer. - pub call_transfer_surcharge: Weight, - - /// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag. - pub call_per_cloned_byte: Weight, - - /// Weight of calling `seal_instantiate`. - pub instantiate: Weight, - - /// Weight surcharge that is claimed if `seal_instantiate` does a balance transfer. - pub instantiate_transfer_surcharge: Weight, - - /// Weight per input byte supplied to `seal_instantiate`. - pub instantiate_per_input_byte: Weight, - - /// Weight per salt byte supplied to `seal_instantiate`. - pub instantiate_per_salt_byte: Weight, - - /// Weight of calling `seal_hash_sha_256`. - pub hash_sha2_256: Weight, - - /// Weight per byte hashed by `seal_hash_sha_256`. - pub hash_sha2_256_per_byte: Weight, - - /// Weight of calling `seal_hash_keccak_256`. - pub hash_keccak_256: Weight, - - /// Weight per byte hashed by `seal_hash_keccak_256`. - pub hash_keccak_256_per_byte: Weight, - - /// Weight of calling `seal_hash_blake2_256`. - pub hash_blake2_256: Weight, - - /// Weight per byte hashed by `seal_hash_blake2_256`. - pub hash_blake2_256_per_byte: Weight, - - /// Weight of calling `seal_hash_blake2_128`. - pub hash_blake2_128: Weight, - - /// Weight per byte hashed by `seal_hash_blake2_128`. - pub hash_blake2_128_per_byte: Weight, - - /// Weight of calling `seal_ecdsa_recover`. - pub ecdsa_recover: Weight, - - /// Weight of calling `seal_ecdsa_to_eth_address`. - pub ecdsa_to_eth_address: Weight, - - /// Weight of calling `sr25519_verify`. - pub sr25519_verify: Weight, - - /// Weight per byte of calling `sr25519_verify`. - pub sr25519_verify_per_byte: Weight, - - /// Weight of calling `reentrance_count`. - pub reentrance_count: Weight, - - /// Weight of calling `account_reentrance_count`. - pub account_reentrance_count: Weight, - - /// Weight of calling `instantiation_nonce`. - pub instantiation_nonce: Weight, - - /// Weight of calling `lock_delegate_dependency`. - pub lock_delegate_dependency: Weight, - - /// Weight of calling `unlock_delegate_dependency`. - pub unlock_delegate_dependency: Weight, - - /// The type parameter is used in the default implementation. - #[codec(skip)] - pub _phantom: PhantomData, -} - -macro_rules! replace_token { - ($_in:tt $replacement:tt) => { - $replacement - }; -} - -macro_rules! call_zero { - ($name:ident, $( $arg:expr ),*) => { - T::WeightInfo::$name($( replace_token!($arg 0) ),*) - }; -} - -macro_rules! cost_args { - ($name:ident, $( $arg: expr ),+) => { - (T::WeightInfo::$name($( $arg ),+).saturating_sub(call_zero!($name, $( $arg ),+))) - } -} - -macro_rules! cost { - ($name:ident) => { - cost_args!($name, 1) - }; -} - impl Default for Limits { fn default() -> Self { Self { @@ -350,94 +123,10 @@ impl Default for InstructionWeights { /// computed gas costs by 6 to have a rough estimate as to how expensive each /// single executed instruction is going to be. fn default() -> Self { - let instr_cost = cost!(instr_i64_load_store).ref_time() as u32; + let instr_cost = T::WeightInfo::instr_i64_load_store(1) + .saturating_sub(T::WeightInfo::instr_i64_load_store(0)) + .ref_time() as u32; let base = instr_cost / 6; Self { base, _phantom: PhantomData } } } - -impl Default for HostFnWeights { - fn default() -> Self { - Self { - caller: cost!(seal_caller), - is_contract: cost!(seal_is_contract), - code_hash: cost!(seal_code_hash), - own_code_hash: cost!(seal_own_code_hash), - caller_is_origin: cost!(seal_caller_is_origin), - caller_is_root: cost!(seal_caller_is_root), - address: cost!(seal_address), - gas_left: cost!(seal_gas_left), - balance: cost!(seal_balance), - value_transferred: cost!(seal_value_transferred), - minimum_balance: cost!(seal_minimum_balance), - block_number: cost!(seal_block_number), - now: cost!(seal_now), - weight_to_fee: cost!(seal_weight_to_fee), - input: cost!(seal_input), - input_per_byte: cost!(seal_input_per_byte), - r#return: cost!(seal_return), - return_per_byte: cost!(seal_return_per_byte), - terminate: cost!(seal_terminate), - random: cost!(seal_random), - deposit_event: cost!(seal_deposit_event), - deposit_event_per_topic: cost_args!(seal_deposit_event_per_topic_and_byte, 1, 0), - deposit_event_per_byte: cost_args!(seal_deposit_event_per_topic_and_byte, 0, 1), - debug_message: cost!(seal_debug_message), - debug_message_per_byte: cost!(seal_debug_message_per_byte), - set_storage: cost!(seal_set_storage), - set_code_hash: cost!(seal_set_code_hash), - set_storage_per_new_byte: cost!(seal_set_storage_per_new_byte), - set_storage_per_old_byte: cost!(seal_set_storage_per_old_byte), - clear_storage: cost!(seal_clear_storage), - clear_storage_per_byte: cost!(seal_clear_storage_per_byte), - contains_storage: cost!(seal_contains_storage), - contains_storage_per_byte: cost!(seal_contains_storage_per_byte), - get_storage: cost!(seal_get_storage), - get_storage_per_byte: cost!(seal_get_storage_per_byte), - take_storage: cost!(seal_take_storage), - take_storage_per_byte: cost!(seal_take_storage_per_byte), - transfer: cost!(seal_transfer), - call: cost!(seal_call), - delegate_call: cost!(seal_delegate_call), - call_transfer_surcharge: cost_args!(seal_call_per_transfer_clone_byte, 1, 0), - call_per_cloned_byte: cost_args!(seal_call_per_transfer_clone_byte, 0, 1), - instantiate: cost!(seal_instantiate), - instantiate_transfer_surcharge: cost_args!( - seal_instantiate_per_transfer_input_salt_byte, - 1, - 0, - 0 - ), - instantiate_per_input_byte: cost_args!( - seal_instantiate_per_transfer_input_salt_byte, - 0, - 1, - 0 - ), - instantiate_per_salt_byte: cost_args!( - seal_instantiate_per_transfer_input_salt_byte, - 0, - 0, - 1 - ), - hash_sha2_256: cost!(seal_hash_sha2_256), - hash_sha2_256_per_byte: cost!(seal_hash_sha2_256_per_byte), - hash_keccak_256: cost!(seal_hash_keccak_256), - hash_keccak_256_per_byte: cost!(seal_hash_keccak_256_per_byte), - hash_blake2_256: cost!(seal_hash_blake2_256), - hash_blake2_256_per_byte: cost!(seal_hash_blake2_256_per_byte), - hash_blake2_128: cost!(seal_hash_blake2_128), - hash_blake2_128_per_byte: cost!(seal_hash_blake2_128_per_byte), - ecdsa_recover: cost!(seal_ecdsa_recover), - sr25519_verify: cost!(seal_sr25519_verify), - sr25519_verify_per_byte: cost!(seal_sr25519_verify_per_byte), - ecdsa_to_eth_address: cost!(seal_ecdsa_to_eth_address), - reentrance_count: cost!(seal_reentrance_count), - account_reentrance_count: cost!(seal_account_reentrance_count), - instantiation_nonce: cost!(seal_instantiation_nonce), - lock_delegate_dependency: cost!(lock_delegate_dependency), - unlock_delegate_dependency: cost!(unlock_delegate_dependency), - _phantom: PhantomData, - } - } -} diff --git a/substrate/frame/contracts/src/storage/meter.rs b/substrate/frame/contracts/src/storage/meter.rs index 5db9a772ad82155348383153de04ef31bdcfe4cf..7c55ce5d3f0c4acda7af2d35741a7b155933b11f 100644 --- a/substrate/frame/contracts/src/storage/meter.rs +++ b/substrate/frame/contracts/src/storage/meter.rs @@ -34,10 +34,10 @@ use frame_support::{ DefaultNoBound, RuntimeDebugNoBound, }; use sp_runtime::{ - traits::{Hash as HashT, Saturating, Zero}, + traits::{Saturating, Zero}, DispatchError, FixedPointNumber, FixedU128, }; -use sp_std::{fmt::Debug, marker::PhantomData, vec, vec::Vec}; +use sp_std::{fmt::Debug, marker::PhantomData, vec::Vec}; /// Deposit that uses the native fungible's balance type. pub type DepositOf = Deposit>; @@ -551,14 +551,11 @@ impl Ext for ReservingExt { Fortitude::Polite, )?; - Pallet::::deposit_event( - vec![T::Hashing::hash_of(&origin), T::Hashing::hash_of(&contract)], - Event::StorageDepositTransferredAndHeld { - from: origin.clone(), - to: contract.clone(), - amount: *amount, - }, - ); + Pallet::::deposit_event(Event::StorageDepositTransferredAndHeld { + from: origin.clone(), + to: contract.clone(), + amount: *amount, + }); }, Deposit::Refund(amount) => { let transferred = T::Currency::transfer_on_hold( @@ -571,14 +568,11 @@ impl Ext for ReservingExt { Fortitude::Polite, )?; - Pallet::::deposit_event( - vec![T::Hashing::hash_of(&contract), T::Hashing::hash_of(&origin)], - Event::StorageDepositTransferredAndReleased { - from: contract.clone(), - to: origin.clone(), - amount: transferred, - }, - ); + Pallet::::deposit_event(Event::StorageDepositTransferredAndReleased { + from: contract.clone(), + to: origin.clone(), + amount: transferred, + }); if transferred < *amount { // This should never happen, if it does it means that there is a bug in the diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 8fe845fcf0f83e8658e7638ea2536bee2794d73f..899b0144b072e56265f690881f8377678b102bc4 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -20,13 +20,13 @@ mod test_debug; use self::{ test_debug::TestDebug, - test_utils::{ensure_stored, expected_deposit, hash}, + test_utils::{ensure_stored, expected_deposit}, }; use crate::{ self as pallet_contracts, chain_extension::{ ChainExtension, Environment, Ext, InitState, RegisteredChainExtension, - Result as ExtensionResult, RetVal, ReturnFlags, SysConfig, + Result as ExtensionResult, RetVal, ReturnFlags, }, exec::{Frame, Key}, migration::codegen::LATEST_MIGRATION_VERSION, @@ -63,7 +63,7 @@ use sp_io::hashing::blake2_256; use sp_keystore::{testing::MemoryKeystore, KeystoreExt}; use sp_runtime::{ testing::H256, - traits::{BlakeTwo256, Convert, Hash, IdentityLookup}, + traits::{BlakeTwo256, Convert, IdentityLookup}, AccountId32, BuildStorage, DispatchError, Perbill, TokenError, }; @@ -97,7 +97,7 @@ macro_rules! assert_refcount { } pub mod test_utils { - use super::{Contracts, DepositPerByte, DepositPerItem, Hash, SysConfig, Test}; + use super::{Contracts, DepositPerByte, DepositPerItem, Test}; use crate::{ exec::AccountIdOf, BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, Nonce, PristineCode, @@ -145,9 +145,6 @@ pub mod test_utils { .saturating_mul(info_size) .saturating_add(DepositPerItem::get()) } - pub fn hash(s: &S) -> <::Hashing as Hash>::Output { - <::Hashing as Hash>::hash_of(s) - } pub fn expected_deposit(code_len: usize) -> u64 { // For code_info, the deposit for max_encoded_len is taken. let code_info_len = CodeInfo::::max_encoded_len() as u64; @@ -768,7 +765,7 @@ fn instantiate_and_call_and_deposit_event() { deployer: ALICE, contract: addr.clone() }), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -779,7 +776,7 @@ fn instantiate_and_call_and_deposit_event() { amount: test_utils::contract_info_storage_deposit(&addr), } ), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, ] ); @@ -874,8 +871,7 @@ fn gas_syncs_work() { let result = builder::bare_call(addr.clone()).data(1u32.encode()).build(); assert_ok!(result.result); let gas_consumed_once = result.gas_consumed.ref_time(); - let host_consumed_once = - ::Schedule::get().host_fn_weights.caller_is_origin.ref_time(); + let host_consumed_once = ::WeightInfo::seal_caller_is_origin().ref_time(); let engine_consumed_once = gas_consumed_once - host_consumed_once - engine_consumed_noop; let result = builder::bare_call(addr).data(2u32.encode()).build(); @@ -1039,7 +1035,7 @@ fn deploy_and_call_other_contract() { deployer: caller_addr.clone(), contract: callee_addr.clone(), }), - topics: vec![hash(&caller_addr), hash(&callee_addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -1056,10 +1052,7 @@ fn deploy_and_call_other_contract() { caller: Origin::from_account_id(caller_addr.clone()), contract: callee_addr.clone(), }), - topics: vec![ - hash(&Origin::::from_account_id(caller_addr.clone())), - hash(&callee_addr) - ], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -1067,7 +1060,7 @@ fn deploy_and_call_other_contract() { caller: Origin::from_account_id(ALICE), contract: caller_addr.clone(), }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&caller_addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -1078,7 +1071,7 @@ fn deploy_and_call_other_contract() { amount: test_utils::contract_info_storage_deposit(&callee_addr), } ), - topics: vec![hash(&ALICE), hash(&callee_addr)], + topics: vec![], }, ] ); @@ -1304,7 +1297,7 @@ fn self_destruct_works() { contract: addr.clone(), beneficiary: DJANGO }), - topics: vec![hash(&addr), hash(&DJANGO)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -1312,7 +1305,7 @@ fn self_destruct_works() { caller: Origin::from_account_id(ALICE), contract: addr.clone(), }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -1323,7 +1316,7 @@ fn self_destruct_works() { amount: info_deposit, } ), - topics: vec![hash(&addr), hash(&ALICE)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2511,7 +2504,7 @@ fn upload_code_works() { deposit_held: deposit_expected, uploader: ALICE }), - topics: vec![code_hash], + topics: vec![], },] ); }); @@ -2599,7 +2592,7 @@ fn remove_code_works() { deposit_held: deposit_expected, uploader: ALICE }), - topics: vec![code_hash], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2608,7 +2601,7 @@ fn remove_code_works() { deposit_released: deposit_expected, remover: ALICE }), - topics: vec![code_hash], + topics: vec![], }, ] ); @@ -2648,7 +2641,7 @@ fn remove_code_wrong_origin() { deposit_held: deposit_expected, uploader: ALICE }), - topics: vec![code_hash], + topics: vec![], },] ); }); @@ -2727,7 +2720,7 @@ fn instantiate_with_zero_balance_works() { deposit_held: deposit_expected, uploader: ALICE }), - topics: vec![code_hash], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2759,7 +2752,7 @@ fn instantiate_with_zero_balance_works() { deployer: ALICE, contract: addr.clone(), }), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2770,7 +2763,7 @@ fn instantiate_with_zero_balance_works() { amount: test_utils::contract_info_storage_deposit(&addr), } ), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, ] ); @@ -2812,7 +2805,7 @@ fn instantiate_with_below_existential_deposit_works() { deposit_held: deposit_expected, uploader: ALICE }), - topics: vec![code_hash], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2853,7 +2846,7 @@ fn instantiate_with_below_existential_deposit_works() { deployer: ALICE, contract: addr.clone(), }), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2864,7 +2857,7 @@ fn instantiate_with_below_existential_deposit_works() { amount: test_utils::contract_info_storage_deposit(&addr), } ), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, ] ); @@ -2925,7 +2918,7 @@ fn storage_deposit_works() { caller: Origin::from_account_id(ALICE), contract: addr.clone(), }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2936,7 +2929,7 @@ fn storage_deposit_works() { amount: charged0, } ), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2944,7 +2937,7 @@ fn storage_deposit_works() { caller: Origin::from_account_id(ALICE), contract: addr.clone(), }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2955,7 +2948,7 @@ fn storage_deposit_works() { amount: charged1, } ), - topics: vec![hash(&ALICE), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2963,7 +2956,7 @@ fn storage_deposit_works() { caller: Origin::from_account_id(ALICE), contract: addr.clone(), }), - topics: vec![hash(&Origin::::from_account_id(ALICE)), hash(&addr)], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -2974,7 +2967,7 @@ fn storage_deposit_works() { amount: refunded0, } ), - topics: vec![hash(&addr.clone()), hash(&ALICE)], + topics: vec![], }, ] ); @@ -3078,7 +3071,7 @@ fn set_code_extrinsic() { new_code_hash, old_code_hash: code_hash, }), - topics: vec![hash(&addr), new_code_hash, code_hash], + topics: vec![], },] ); }); @@ -3230,7 +3223,7 @@ fn set_code_hash() { new_code_hash, old_code_hash: code_hash, }), - topics: vec![hash(&contract_addr), new_code_hash, code_hash], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -3238,10 +3231,7 @@ fn set_code_hash() { caller: Origin::from_account_id(ALICE), contract: contract_addr.clone(), }), - topics: vec![ - hash(&Origin::::from_account_id(ALICE)), - hash(&contract_addr) - ], + topics: vec![], }, EventRecord { phase: Phase::Initialization, @@ -3249,10 +3239,7 @@ fn set_code_hash() { caller: Origin::from_account_id(ALICE), contract: contract_addr.clone(), }), - topics: vec![ - hash(&Origin::::from_account_id(ALICE)), - hash(&contract_addr) - ], + topics: vec![], }, ], ); diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 8d7f928dba33d3cb3f221820d2b825e32997db75..e5497b143b8b44073493db391d60bc670ade45a5 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -31,6 +31,9 @@ pub use { tests::MockExt, }; +#[cfg(feature = "runtime-benchmarks")] +pub use crate::wasm::runtime::{BenchEnv, ReturnData, TrapReason}; + pub use crate::wasm::{ prepare::{LoadedModule, LoadingMode}, runtime::{ @@ -184,10 +187,11 @@ impl WasmBlob { *existing = None; >::remove(&code_hash); - >::deposit_event( - vec![code_hash], - Event::CodeRemoved { code_hash, deposit_released, remover }, - ); + >::deposit_event(Event::CodeRemoved { + code_hash, + deposit_released, + remover, + }); Ok(()) } else { Err(>::CodeNotFound.into()) @@ -271,14 +275,11 @@ impl WasmBlob { self.code_info.refcount = 0; >::insert(code_hash, &self.code); *stored_code_info = Some(self.code_info.clone()); - >::deposit_event( - vec![code_hash], - Event::CodeStored { - code_hash, - deposit_held: deposit, - uploader: self.code_info.owner.clone(), - }, - ); + >::deposit_event(Event::CodeStored { + code_hash, + deposit_held: deposit, + uploader: self.code_info.owner.clone(), + }); Ok(deposit) }, } @@ -804,6 +805,9 @@ mod tests { self.delegate_dependencies.borrow_mut().remove(code); Ok(()) } + fn locked_delegate_dependencies_count(&mut self) -> usize { + self.delegate_dependencies.borrow().len() + } } /// Execute the supplied code. diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 3212aff31269a91d66ce0043f60c8130b2d4bc9a..39b15c867c6ab4d8c0287535974565c92f1b0b92 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -21,6 +21,7 @@ use crate::{ exec::{ExecError, ExecResult, Ext, Key, TopicOf}, gas::{ChargedAmount, Token}, primitives::ExecReturnValue, + weights::WeightInfo, BalanceOf, CodeHash, Config, DebugBufferVec, Error, SENTINEL, }; use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; @@ -145,6 +146,8 @@ impl HostError for TrapReason {} #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Copy, Clone)] pub enum RuntimeCosts { + /// Base Weight of calling a host function. + HostFn, /// Weight charged for copying data from the sandbox. CopyFromContract(u32), /// Weight charged for copying data to the sandbox. @@ -177,12 +180,8 @@ pub enum RuntimeCosts { Now, /// Weight of calling `seal_weight_to_fee`. WeightToFee, - /// Weight of calling `seal_input` without the weight of copying the input. - InputBase, - /// Weight of calling `seal_return` for the given output size. - Return(u32), - /// Weight of calling `seal_terminate`. - Terminate, + /// Weight of calling `seal_terminate`, passing the number of locked dependencies. + Terminate(u32), /// Weight of calling `seal_random`. It includes the weight for copying the subject. Random, /// Weight of calling `seal_deposit_event` with the given number of topics and event size. @@ -206,13 +205,13 @@ pub enum RuntimeCosts { /// Weight of calling `seal_delegate_call` for the given input size. DelegateCallBase, /// Weight of the transfer performed during a call. - CallSurchargeTransfer, + CallTransferSurcharge, /// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag. CallInputCloned(u32), /// Weight of calling `seal_instantiate` for the given input length and salt. InstantiateBase { input_data_len: u32, salt_len: u32 }, /// Weight of the transfer performed during an instantiate. - InstantiateSurchargeTransfer, + InstantiateTransferSurcharge, /// Weight of calling `seal_hash_sha_256` for the given input size. HashSha256(u32), /// Weight of calling `seal_hash_keccak_256` for the given input size. @@ -236,9 +235,9 @@ pub enum RuntimeCosts { /// Weight of calling `ecdsa_to_eth_address` EcdsaToEthAddress, /// Weight of calling `reentrance_count` - ReentrantCount, + ReentranceCount, /// Weight of calling `account_reentrance_count` - AccountEntranceCount, + AccountReentranceCount, /// Weight of calling `instantiation_nonce` InstantiationNonce, /// Weight of calling `lock_delegate_dependency` @@ -247,6 +246,19 @@ pub enum RuntimeCosts { UnlockDelegateDependency, } +macro_rules! cost_args { + // cost_args!(name, a, b, c) -> T::WeightInfo::name(a, b, c).saturating_sub(T::WeightInfo::name(0, 0, 0)) + ($name:ident, $( $arg: expr ),+) => { + (T::WeightInfo::$name($( $arg ),+).saturating_sub(cost_args!(@call_zero $name, $( $arg ),+))) + }; + // Transform T::WeightInfo::name(a, b, c) into T::WeightInfo::name(0, 0, 0) + (@call_zero $name:ident, $( $arg:expr ),*) => { + T::WeightInfo::$name($( cost_args!(@replace_token $arg) ),*) + }; + // Replace the token with 0. + (@replace_token $_in:tt) => { 0 }; +} + impl Token for RuntimeCosts { fn influence_lowest_gas_limit(&self) -> bool { match self { @@ -256,85 +268,57 @@ impl Token for RuntimeCosts { } fn weight(&self) -> Weight { - let s = T::Schedule::get().host_fn_weights; use self::RuntimeCosts::*; match *self { - CopyFromContract(len) => s.return_per_byte.saturating_mul(len.into()), - CopyToContract(len) => s.input_per_byte.saturating_mul(len.into()), - Caller => s.caller, - IsContract => s.is_contract, - CodeHash => s.code_hash, - OwnCodeHash => s.own_code_hash, - CallerIsOrigin => s.caller_is_origin, - CallerIsRoot => s.caller_is_root, - Address => s.address, - GasLeft => s.gas_left, - Balance => s.balance, - ValueTransferred => s.value_transferred, - MinimumBalance => s.minimum_balance, - BlockNumber => s.block_number, - Now => s.now, - WeightToFee => s.weight_to_fee, - InputBase => s.input, - Return(len) => s.r#return.saturating_add(s.return_per_byte.saturating_mul(len.into())), - Terminate => s.terminate, - Random => s.random, - DepositEvent { num_topic, len } => s - .deposit_event - .saturating_add(s.deposit_event_per_topic.saturating_mul(num_topic.into())) - .saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())), - DebugMessage(len) => s - .debug_message - .saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())), - SetStorage { new_bytes, old_bytes } => s - .set_storage - .saturating_add(s.set_storage_per_new_byte.saturating_mul(new_bytes.into())) - .saturating_add(s.set_storage_per_old_byte.saturating_mul(old_bytes.into())), - ClearStorage(len) => s - .clear_storage - .saturating_add(s.clear_storage_per_byte.saturating_mul(len.into())), - ContainsStorage(len) => s - .contains_storage - .saturating_add(s.contains_storage_per_byte.saturating_mul(len.into())), - GetStorage(len) => - s.get_storage.saturating_add(s.get_storage_per_byte.saturating_mul(len.into())), - TakeStorage(len) => s - .take_storage - .saturating_add(s.take_storage_per_byte.saturating_mul(len.into())), - Transfer => s.transfer, - CallBase => s.call, - DelegateCallBase => s.delegate_call, - CallSurchargeTransfer => s.call_transfer_surcharge, - CallInputCloned(len) => s.call_per_cloned_byte.saturating_mul(len.into()), - InstantiateBase { input_data_len, salt_len } => s - .instantiate - .saturating_add(s.instantiate_per_input_byte.saturating_mul(input_data_len.into())) - .saturating_add(s.instantiate_per_salt_byte.saturating_mul(salt_len.into())), - InstantiateSurchargeTransfer => s.instantiate_transfer_surcharge, - HashSha256(len) => s - .hash_sha2_256 - .saturating_add(s.hash_sha2_256_per_byte.saturating_mul(len.into())), - HashKeccak256(len) => s - .hash_keccak_256 - .saturating_add(s.hash_keccak_256_per_byte.saturating_mul(len.into())), - HashBlake256(len) => s - .hash_blake2_256 - .saturating_add(s.hash_blake2_256_per_byte.saturating_mul(len.into())), - HashBlake128(len) => s - .hash_blake2_128 - .saturating_add(s.hash_blake2_128_per_byte.saturating_mul(len.into())), - EcdsaRecovery => s.ecdsa_recover, - Sr25519Verify(len) => s - .sr25519_verify - .saturating_add(s.sr25519_verify_per_byte.saturating_mul(len.into())), + HostFn => cost_args!(noop_host_fn, 1), + CopyToContract(len) => T::WeightInfo::seal_input(len), + CopyFromContract(len) => T::WeightInfo::seal_return(len), + Caller => T::WeightInfo::seal_caller(), + IsContract => T::WeightInfo::seal_is_contract(), + CodeHash => T::WeightInfo::seal_code_hash(), + OwnCodeHash => T::WeightInfo::seal_own_code_hash(), + CallerIsOrigin => T::WeightInfo::seal_caller_is_origin(), + CallerIsRoot => T::WeightInfo::seal_caller_is_root(), + Address => T::WeightInfo::seal_address(), + GasLeft => T::WeightInfo::seal_gas_left(), + Balance => T::WeightInfo::seal_balance(), + ValueTransferred => T::WeightInfo::seal_value_transferred(), + MinimumBalance => T::WeightInfo::seal_minimum_balance(), + BlockNumber => T::WeightInfo::seal_block_number(), + Now => T::WeightInfo::seal_now(), + WeightToFee => T::WeightInfo::seal_weight_to_fee(), + Terminate(locked_dependencies) => T::WeightInfo::seal_terminate(locked_dependencies), + Random => T::WeightInfo::seal_random(), + DepositEvent { num_topic, len } => T::WeightInfo::seal_deposit_event(num_topic, len), + DebugMessage(len) => T::WeightInfo::seal_debug_message(len), + SetStorage { new_bytes, old_bytes } => + T::WeightInfo::seal_set_storage(new_bytes, old_bytes), + ClearStorage(len) => T::WeightInfo::seal_clear_storage(len), + ContainsStorage(len) => T::WeightInfo::seal_contains_storage(len), + GetStorage(len) => T::WeightInfo::seal_get_storage(len), + TakeStorage(len) => T::WeightInfo::seal_take_storage(len), + Transfer => T::WeightInfo::seal_transfer(), + CallBase => T::WeightInfo::seal_call(0, 0), + DelegateCallBase => T::WeightInfo::seal_delegate_call(), + CallTransferSurcharge => cost_args!(seal_call, 1, 0), + CallInputCloned(len) => cost_args!(seal_call, 0, len), + InstantiateBase { input_data_len, salt_len } => + T::WeightInfo::seal_instantiate(0, input_data_len, salt_len), + InstantiateTransferSurcharge => cost_args!(seal_instantiate, 1, 0, 0), + HashSha256(len) => T::WeightInfo::seal_hash_sha2_256(len), + HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len), + HashBlake256(len) => T::WeightInfo::seal_hash_blake2_256(len), + HashBlake128(len) => T::WeightInfo::seal_hash_blake2_128(len), + EcdsaRecovery => T::WeightInfo::seal_ecdsa_recover(), + Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len), ChainExtension(weight) | CallRuntime(weight) | CallXcmExecute(weight) => weight, - SetCodeHash => s.set_code_hash, - EcdsaToEthAddress => s.ecdsa_to_eth_address, - ReentrantCount => s.reentrance_count, - AccountEntranceCount => s.account_reentrance_count, - InstantiationNonce => s.instantiation_nonce, - LockDelegateDependency => s.lock_delegate_dependency, - UnlockDelegateDependency => s.unlock_delegate_dependency, + SetCodeHash => T::WeightInfo::seal_set_code_hash(), + EcdsaToEthAddress => T::WeightInfo::seal_ecdsa_to_eth_address(), + ReentranceCount => T::WeightInfo::seal_reentrance_count(), + AccountReentranceCount => T::WeightInfo::seal_account_reentrance_count(), + InstantiationNonce => T::WeightInfo::seal_instantiation_nonce(), + LockDelegateDependency => T::WeightInfo::lock_delegate_dependency(), + UnlockDelegateDependency => T::WeightInfo::unlock_delegate_dependency(), } } } @@ -819,6 +803,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { output_len_ptr: u32, ) -> Result { self.charge_gas(call_type.cost())?; + let input_data = if flags.contains(CallFlags::CLONE_INPUT) { let input = self.input_data.as_ref().ok_or(Error::::InputForwarded)?; charge_gas!(self, RuntimeCosts::CallInputCloned(input.len() as u32))?; @@ -842,7 +827,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { let value: BalanceOf<::T> = self.read_sandbox_memory_as(memory, value_ptr)?; if value > 0u32.into() { - self.charge_gas(RuntimeCosts::CallSurchargeTransfer)?; + self.charge_gas(RuntimeCosts::CallTransferSurcharge)?; } self.ext.call( weight, @@ -910,7 +895,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { }; let value: BalanceOf<::T> = self.read_sandbox_memory_as(memory, value_ptr)?; if value > 0u32.into() { - self.charge_gas(RuntimeCosts::InstantiateSurchargeTransfer)?; + self.charge_gas(RuntimeCosts::InstantiateTransferSurcharge)?; } let code_hash: CodeHash<::T> = self.read_sandbox_memory_as(memory, code_hash_ptr)?; @@ -942,7 +927,9 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { } fn terminate(&mut self, memory: &[u8], beneficiary_ptr: u32) -> Result<(), TrapReason> { - self.charge_gas(RuntimeCosts::Terminate)?; + let count = self.ext.locked_delegate_dependencies_count() as _; + self.charge_gas(RuntimeCosts::Terminate(count))?; + let beneficiary: <::T as frame_system::Config>::AccountId = self.read_sandbox_memory_as(memory, beneficiary_ptr)?; self.ext.terminate(&beneficiary)?; @@ -959,6 +946,14 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { // for every function. #[define_env(doc)] pub mod env { + + /// Noop function used to benchmark the time it takes to execute an empty function. + #[cfg(feature = "runtime-benchmarks")] + #[unstable] + fn noop(ctx: _, memory: _) -> Result<(), TrapReason> { + Ok(()) + } + /// Set the value at the given key in the contract storage. /// See [`pallet_contracts_uapi::HostFn::set_storage`] #[prefixed_alias] @@ -1387,7 +1382,6 @@ pub mod env { /// See [`pallet_contracts_uapi::HostFn::input`]. #[prefixed_alias] fn input(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> { - ctx.charge_gas(RuntimeCosts::InputBase)?; if let Some(input) = ctx.input_data.take() { ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &input, false, |len| { Some(RuntimeCosts::CopyToContract(len)) @@ -1408,7 +1402,7 @@ pub mod env { data_ptr: u32, data_len: u32, ) -> Result<(), TrapReason> { - ctx.charge_gas(RuntimeCosts::Return(data_len))?; + ctx.charge_gas(RuntimeCosts::CopyFromContract(data_len))?; Err(TrapReason::Return(ReturnData { flags, data: ctx.read_sandbox_memory(memory, data_ptr, data_len)?, @@ -2249,7 +2243,7 @@ pub mod env { /// See [`pallet_contracts_uapi::HostFn::reentrance_count`]. #[unstable] fn reentrance_count(ctx: _, memory: _) -> Result { - ctx.charge_gas(RuntimeCosts::ReentrantCount)?; + ctx.charge_gas(RuntimeCosts::ReentranceCount)?; Ok(ctx.ext.reentrance_count()) } @@ -2258,7 +2252,7 @@ pub mod env { /// See [`pallet_contracts_uapi::HostFn::account_reentrance_count`]. #[unstable] fn account_reentrance_count(ctx: _, memory: _, account_ptr: u32) -> Result { - ctx.charge_gas(RuntimeCosts::AccountEntranceCount)?; + ctx.charge_gas(RuntimeCosts::AccountReentranceCount)?; let account_id: <::T as frame_system::Config>::AccountId = ctx.read_sandbox_memory_as(memory, account_ptr)?; Ok(ctx.ext.account_reentrance_count(&account_id)) diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index b95b1d1a9a2e5ae47ca0d9fe1715031f47e43986..2e9c2cd15af8408baabccfaadf42ce1406d92f17 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -18,9 +18,9 @@ //! Autogenerated weights for `pallet_contracts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-vicqj8em-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: @@ -72,65 +72,49 @@ pub trait WeightInfo { fn upload_code_determinism_relaxed(c: u32, ) -> Weight; fn remove_code() -> Weight; fn set_code() -> Weight; - fn seal_caller(r: u32, ) -> Weight; - fn seal_is_contract(r: u32, ) -> Weight; - fn seal_code_hash(r: u32, ) -> Weight; - fn seal_own_code_hash(r: u32, ) -> Weight; - fn seal_caller_is_origin(r: u32, ) -> Weight; - fn seal_caller_is_root(r: u32, ) -> Weight; - fn seal_address(r: u32, ) -> Weight; - fn seal_gas_left(r: u32, ) -> Weight; - fn seal_balance(r: u32, ) -> Weight; - fn seal_value_transferred(r: u32, ) -> Weight; - fn seal_minimum_balance(r: u32, ) -> Weight; - fn seal_block_number(r: u32, ) -> Weight; - fn seal_now(r: u32, ) -> Weight; - fn seal_weight_to_fee(r: u32, ) -> Weight; - fn seal_input(r: u32, ) -> Weight; - fn seal_input_per_byte(n: u32, ) -> Weight; - fn seal_return(r: u32, ) -> Weight; - fn seal_return_per_byte(n: u32, ) -> Weight; - fn seal_terminate(r: u32, ) -> Weight; - fn seal_random(r: u32, ) -> Weight; - fn seal_deposit_event(r: u32, ) -> Weight; - fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight; - fn seal_debug_message(r: u32, ) -> Weight; - fn seal_debug_message_per_byte(i: u32, ) -> Weight; - fn seal_set_storage(r: u32, ) -> Weight; - fn seal_set_storage_per_new_byte(n: u32, ) -> Weight; - fn seal_set_storage_per_old_byte(n: u32, ) -> Weight; - fn seal_clear_storage(r: u32, ) -> Weight; - fn seal_clear_storage_per_byte(n: u32, ) -> Weight; - fn seal_get_storage(r: u32, ) -> Weight; - fn seal_get_storage_per_byte(n: u32, ) -> Weight; - fn seal_contains_storage(r: u32, ) -> Weight; - fn seal_contains_storage_per_byte(n: u32, ) -> Weight; - fn seal_take_storage(r: u32, ) -> Weight; - fn seal_take_storage_per_byte(n: u32, ) -> Weight; - fn seal_transfer(r: u32, ) -> Weight; - fn seal_call(r: u32, ) -> Weight; - fn seal_delegate_call(r: u32, ) -> Weight; - fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight; - fn seal_instantiate(r: u32, ) -> Weight; - fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight; - fn seal_hash_sha2_256(r: u32, ) -> Weight; - fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight; - fn seal_hash_keccak_256(r: u32, ) -> Weight; - fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight; - fn seal_hash_blake2_256(r: u32, ) -> Weight; - fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight; - fn seal_hash_blake2_128(r: u32, ) -> Weight; - fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight; - fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight; - fn seal_sr25519_verify(r: u32, ) -> Weight; - fn seal_ecdsa_recover(r: u32, ) -> Weight; - fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight; - fn seal_set_code_hash(r: u32, ) -> Weight; - fn lock_delegate_dependency(r: u32, ) -> Weight; - fn unlock_delegate_dependency(r: u32, ) -> Weight; - fn seal_reentrance_count(r: u32, ) -> Weight; - fn seal_account_reentrance_count(r: u32, ) -> Weight; - fn seal_instantiation_nonce(r: u32, ) -> Weight; + fn noop_host_fn(r: u32, ) -> Weight; + fn seal_caller() -> Weight; + fn seal_is_contract() -> Weight; + fn seal_code_hash() -> Weight; + fn seal_own_code_hash() -> Weight; + fn seal_caller_is_origin() -> Weight; + fn seal_caller_is_root() -> Weight; + fn seal_address() -> Weight; + fn seal_gas_left() -> Weight; + fn seal_balance() -> Weight; + fn seal_value_transferred() -> Weight; + fn seal_minimum_balance() -> Weight; + fn seal_block_number() -> Weight; + fn seal_now() -> Weight; + fn seal_weight_to_fee() -> Weight; + fn seal_input(n: u32, ) -> Weight; + fn seal_return(n: u32, ) -> Weight; + fn seal_terminate(n: u32, ) -> Weight; + fn seal_random() -> Weight; + fn seal_deposit_event(t: u32, n: u32, ) -> Weight; + fn seal_debug_message(i: u32, ) -> Weight; + fn seal_set_storage(n: u32, o: u32, ) -> Weight; + fn seal_clear_storage(n: u32, ) -> Weight; + fn seal_get_storage(n: u32, ) -> Weight; + fn seal_contains_storage(n: u32, ) -> Weight; + fn seal_take_storage(n: u32, ) -> Weight; + fn seal_transfer() -> Weight; + fn seal_call(t: u32, i: u32, ) -> Weight; + fn seal_delegate_call() -> Weight; + fn seal_instantiate(t: u32, i: u32, s: u32, ) -> Weight; + fn seal_hash_sha2_256(n: u32, ) -> Weight; + fn seal_hash_keccak_256(n: u32, ) -> Weight; + fn seal_hash_blake2_256(n: u32, ) -> Weight; + fn seal_hash_blake2_128(n: u32, ) -> Weight; + fn seal_sr25519_verify(n: u32, ) -> Weight; + fn seal_ecdsa_recover() -> Weight; + fn seal_ecdsa_to_eth_address() -> Weight; + fn seal_set_code_hash() -> Weight; + fn lock_delegate_dependency() -> Weight; + fn unlock_delegate_dependency() -> Weight; + fn seal_reentrance_count() -> Weight; + fn seal_account_reentrance_count() -> Weight; + fn seal_instantiation_nonce() -> Weight; fn instr_i64_load_store(r: u32, ) -> Weight; } @@ -143,8 +127,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_149_000 picoseconds. - Weight::from_parts(2_274_000, 1627) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_142_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -154,10 +138,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_863_000 picoseconds. - Weight::from_parts(13_188_000, 442) - // Standard Error: 1_053 - .saturating_add(Weight::from_parts(1_105_325, 0).saturating_mul(k.into())) + // Minimum execution time: 12_095_000 picoseconds. + Weight::from_parts(12_699_000, 442) + // Standard Error: 891 + .saturating_add(Weight::from_parts(1_114_063, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -171,10 +155,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_432_000 picoseconds. - Weight::from_parts(9_203_290, 6149) + // Minimum execution time: 8_433_000 picoseconds. + Weight::from_parts(8_992_328, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_186, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_207, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -187,8 +171,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 17_177_000 picoseconds. - Weight::from_parts(17_663_000, 6450) + // Minimum execution time: 16_415_000 picoseconds. + Weight::from_parts(17_348_000, 6450) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -201,10 +185,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_636_000 picoseconds. - Weight::from_parts(3_774_000, 3635) - // Standard Error: 542 - .saturating_add(Weight::from_parts(1_260_058, 0).saturating_mul(k.into())) + // Minimum execution time: 3_433_000 picoseconds. + Weight::from_parts(3_490_000, 3635) + // Standard Error: 1_043 + .saturating_add(Weight::from_parts(1_225_953, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -214,8 +198,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -223,13 +205,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 125952]`. fn v12_migration_step(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `328 + c * (1 ±0)` - // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 21_585_000 picoseconds. - Weight::from_parts(22_069_944, 6266) - // Standard Error: 1 - .saturating_add(Weight::from_parts(404, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Measured: `325 + c * (1 ±0)` + // Estimated: `6263 + c * (1 ±0)` + // Minimum execution time: 16_421_000 picoseconds. + Weight::from_parts(16_822_963, 6263) + // Standard Error: 0 + .saturating_add(Weight::from_parts(456, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } @@ -239,8 +221,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 13_283_000 picoseconds. - Weight::from_parts(14_015_000, 6380) + // Minimum execution time: 12_569_000 picoseconds. + Weight::from_parts(13_277_000, 6380) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -254,8 +236,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 48_022_000 picoseconds. - Weight::from_parts(49_627_000, 6292) + // Minimum execution time: 46_777_000 picoseconds. + Weight::from_parts(47_690_000, 6292) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -267,8 +249,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 58_374_000 picoseconds. - Weight::from_parts(59_615_000, 6534) + // Minimum execution time: 55_280_000 picoseconds. + Weight::from_parts(57_081_000, 6534) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -278,8 +260,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `409` // Estimated: `6349` - // Minimum execution time: 12_559_000 picoseconds. - Weight::from_parts(12_947_000, 6349) + // Minimum execution time: 12_077_000 picoseconds. + Weight::from_parts(12_647_000, 6349) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -289,8 +271,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_480_000 picoseconds. - Weight::from_parts(2_680_000, 1627) + // Minimum execution time: 2_559_000 picoseconds. + Weight::from_parts(2_711_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -302,8 +284,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 12_625_000 picoseconds. - Weight::from_parts(13_094_000, 3631) + // Minimum execution time: 12_238_000 picoseconds. + Weight::from_parts(12_627_000, 3631) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -314,7 +296,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `142` // Estimated: `3607` // Minimum execution time: 4_836_000 picoseconds. - Weight::from_parts(5_182_000, 3607) + Weight::from_parts(5_086_000, 3607) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -325,8 +307,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_319_000 picoseconds. - Weight::from_parts(6_582_000, 3632) + // Minimum execution time: 6_147_000 picoseconds. + Weight::from_parts(6_380_000, 3632) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -337,15 +319,13 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_532_000 picoseconds. - Weight::from_parts(6_909_000, 3607) + // Minimum execution time: 6_140_000 picoseconds. + Weight::from_parts(6_670_000, 3607) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -356,31 +336,25 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `804 + c * (1 ±0)` - // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 305_778_000 picoseconds. - Weight::from_parts(282_321_249, 9217) - // Standard Error: 72 - .saturating_add(Weight::from_parts(33_456, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Measured: `801 + c * (1 ±0)` + // Estimated: `4264 + c * (1 ±0)` + // Minimum execution time: 354_459_000 picoseconds. + Weight::from_parts(332_397_871, 4264) + // Standard Error: 70 + .saturating_add(Weight::from_parts(33_775, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:3 w:3) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -396,18 +370,18 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `326` - // Estimated: `8740` - // Minimum execution time: 3_810_809_000 picoseconds. - Weight::from_parts(739_511_598, 8740) - // Standard Error: 140 - .saturating_add(Weight::from_parts(67_574, 0).saturating_mul(c.into())) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_488, 0).saturating_mul(i.into())) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_537, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(14_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Measured: `323` + // Estimated: `6262` + // Minimum execution time: 4_239_452_000 picoseconds. + Weight::from_parts(800_849_282, 6262) + // Standard Error: 117 + .saturating_add(Weight::from_parts(68_435, 0).saturating_mul(c.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(1_653, 0).saturating_mul(i.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(1_668, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -415,8 +389,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -425,29 +397,25 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563` - // Estimated: `8982` - // Minimum execution time: 1_986_789_000 picoseconds. - Weight::from_parts(2_017_466_000, 8982) + // Measured: `560` + // Estimated: `4029` + // Minimum execution time: 2_085_570_000 picoseconds. + Weight::from_parts(2_112_501_000, 4029) // Standard Error: 26 - .saturating_add(Weight::from_parts(827, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(888, 0).saturating_mul(i.into())) // Standard Error: 26 - .saturating_add(Weight::from_parts(781, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(13_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(795, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -458,64 +426,54 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `829` - // Estimated: `9244` - // Minimum execution time: 210_724_000 picoseconds. - Weight::from_parts(218_608_000, 9244) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Measured: `826` + // Estimated: `4291` + // Minimum execution time: 201_900_000 picoseconds. + Weight::from_parts(206_738_000, 4291) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn upload_code_determinism_enforced(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `6085` - // Minimum execution time: 271_259_000 picoseconds. - Weight::from_parts(298_852_854, 6085) - // Standard Error: 65 - .saturating_add(Weight::from_parts(33_547, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Measured: `142` + // Estimated: `3607` + // Minimum execution time: 330_704_000 picoseconds. + Weight::from_parts(345_129_342, 3607) + // Standard Error: 51 + .saturating_add(Weight::from_parts(33_126, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn upload_code_determinism_relaxed(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `6085` - // Minimum execution time: 278_167_000 picoseconds. - Weight::from_parts(311_888_941, 6085) - // Standard Error: 58 - .saturating_add(Weight::from_parts(33_595, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Measured: `142` + // Estimated: `3607` + // Minimum execution time: 343_339_000 picoseconds. + Weight::from_parts(356_479_729, 3607) + // Standard Error: 49 + .saturating_add(Weight::from_parts(33_404, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -523,18 +481,16 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 47_403_000 picoseconds. - Weight::from_parts(48_707_000, 3780) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 42_241_000 picoseconds. + Weight::from_parts(43_365_000, 3780) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -542,610 +498,331 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `System::EventTopics` (r:3 w:3) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: // Measured: `552` - // Estimated: `8967` - // Minimum execution time: 35_361_000 picoseconds. - Weight::from_parts(36_714_000, 8967) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Estimated: `6492` + // Minimum execution time: 26_318_000 picoseconds. + Weight::from_parts(27_840_000, 6492) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// The range of component `r` is `[0, 1600]`. - fn seal_caller(r: u32, ) -> Weight { + fn noop_host_fn(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 9_397_000 picoseconds. + Weight::from_parts(9_318_986, 0) + // Standard Error: 72 + .saturating_add(Weight::from_parts(72_994, 0).saturating_mul(r.into())) + } + fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_340_000 picoseconds. - Weight::from_parts(9_360_237, 0) - // Standard Error: 269 - .saturating_add(Weight::from_parts(249_611, 0).saturating_mul(r.into())) + // Minimum execution time: 644_000 picoseconds. + Weight::from_parts(687_000, 0) } - /// Storage: `Contracts::ContractInfoOf` (r:1600 w:0) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:0) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_is_contract(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `509 + r * (77 ±0)` - // Estimated: `1467 + r * (2552 ±0)` - // Minimum execution time: 9_059_000 picoseconds. - Weight::from_parts(9_201_000, 1467) - // Standard Error: 5_643 - .saturating_add(Weight::from_parts(3_343_859, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2552).saturating_mul(r.into())) - } - /// Storage: `Contracts::ContractInfoOf` (r:1600 w:0) + fn seal_is_contract() -> Weight { + // Proof Size summary in bytes: + // Measured: `354` + // Estimated: `3819` + // Minimum execution time: 6_465_000 picoseconds. + Weight::from_parts(6_850_000, 3819) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Contracts::ContractInfoOf` (r:1 w:0) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_code_hash(r: u32, ) -> Weight { + fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `517 + r * (170 ±0)` - // Estimated: `1468 + r * (2645 ±0)` - // Minimum execution time: 9_220_000 picoseconds. - Weight::from_parts(9_399_000, 1468) - // Standard Error: 6_194 - .saturating_add(Weight::from_parts(4_172_011, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2645).saturating_mul(r.into())) + // Measured: `447` + // Estimated: `3912` + // Minimum execution time: 7_735_000 picoseconds. + Weight::from_parts(8_115_000, 3912) + .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_own_code_hash(r: u32, ) -> Weight { + fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_707_000 picoseconds. - Weight::from_parts(10_100_456, 0) - // Standard Error: 234 - .saturating_add(Weight::from_parts(338_464, 0).saturating_mul(r.into())) + // Minimum execution time: 717_000 picoseconds. + Weight::from_parts(791_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_caller_is_origin(r: u32, ) -> Weight { + fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_524_000 picoseconds. - Weight::from_parts(10_813_389, 0) - // Standard Error: 76 - .saturating_add(Weight::from_parts(102_535, 0).saturating_mul(r.into())) + // Minimum execution time: 365_000 picoseconds. + Weight::from_parts(427_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_caller_is_root(r: u32, ) -> Weight { + fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_799_000 picoseconds. - Weight::from_parts(10_886_744, 0) - // Standard Error: 75 - .saturating_add(Weight::from_parts(80_901, 0).saturating_mul(r.into())) + // Minimum execution time: 331_000 picoseconds. + Weight::from_parts(363_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_address(r: u32, ) -> Weight { + fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_895_000 picoseconds. - Weight::from_parts(10_658_338, 0) - // Standard Error: 189 - .saturating_add(Weight::from_parts(249_694, 0).saturating_mul(r.into())) + // Minimum execution time: 586_000 picoseconds. + Weight::from_parts(625_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_gas_left(r: u32, ) -> Weight { + fn seal_gas_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_643_000 picoseconds. - Weight::from_parts(10_932_126, 0) - // Standard Error: 153 - .saturating_add(Weight::from_parts(280_924, 0).saturating_mul(r.into())) + // Minimum execution time: 680_000 picoseconds. + Weight::from_parts(734_000, 0) } - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_balance(r: u32, ) -> Weight { + fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `140` - // Estimated: `3599` - // Minimum execution time: 9_548_000 picoseconds. - Weight::from_parts(9_737_000, 3599) - // Standard Error: 971 - .saturating_add(Weight::from_parts(1_704_134, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Estimated: `0` + // Minimum execution time: 4_732_000 picoseconds. + Weight::from_parts(5_008_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_value_transferred(r: u32, ) -> Weight { + fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_172_000 picoseconds. - Weight::from_parts(18_255_933, 0) - // Standard Error: 540 - .saturating_add(Weight::from_parts(230_929, 0).saturating_mul(r.into())) + // Minimum execution time: 608_000 picoseconds. + Weight::from_parts(635_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_minimum_balance(r: u32, ) -> Weight { + fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_232_000 picoseconds. - Weight::from_parts(9_796_584, 0) - // Standard Error: 208 - .saturating_add(Weight::from_parts(239_962, 0).saturating_mul(r.into())) + // Minimum execution time: 571_000 picoseconds. + Weight::from_parts(606_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_block_number(r: u32, ) -> Weight { + fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_747_000 picoseconds. - Weight::from_parts(8_733_230, 0) - // Standard Error: 377 - .saturating_add(Weight::from_parts(253_801, 0).saturating_mul(r.into())) + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(584_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_now(r: u32, ) -> Weight { + fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_214_000 picoseconds. - Weight::from_parts(10_194_153, 0) - // Standard Error: 516 - .saturating_add(Weight::from_parts(247_621, 0).saturating_mul(r.into())) + // Minimum execution time: 552_000 picoseconds. + Weight::from_parts(612_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_weight_to_fee(r: u32, ) -> Weight { + fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 9_022_000 picoseconds. - Weight::from_parts(22_051_160, 1552) - // Standard Error: 697 - .saturating_add(Weight::from_parts(709_612, 0).saturating_mul(r.into())) + // Minimum execution time: 4_396_000 picoseconds. + Weight::from_parts(4_630_000, 1552) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_input(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_135_000 picoseconds. - Weight::from_parts(10_646_215, 0) - // Standard Error: 161 - .saturating_add(Weight::from_parts(170_336, 0).saturating_mul(r.into())) - } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 1048576]`. - fn seal_input_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `9287` - // Minimum execution time: 273_896_000 picoseconds. - Weight::from_parts(148_309_654, 9287) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_355, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// The range of component `r` is `[0, 1]`. - fn seal_return(r: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048572]`. + fn seal_input(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_906_000 picoseconds. - Weight::from_parts(9_264_446, 0) - // Standard Error: 19_760 - .saturating_add(Weight::from_parts(1_256_053, 0).saturating_mul(r.into())) + // Minimum execution time: 494_000 picoseconds. + Weight::from_parts(510_000, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(303, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 1048576]`. - fn seal_return_per_byte(n: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048572]`. + fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_266_000 picoseconds. - Weight::from_parts(10_602_261, 0) - // Standard Error: 0 - .saturating_add(Weight::from_parts(318, 0).saturating_mul(n.into())) + // Minimum execution time: 311_000 picoseconds. + Weight::from_parts(346_000, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(480, 0).saturating_mul(n.into())) } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:1 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::DeletionQueueCounter` (r:1 w:1) /// Proof: `Contracts::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:4 w:4) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) + /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) - /// The range of component `r` is `[0, 1]`. - fn seal_terminate(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `4805 + r * (2121 ±0)` - // Estimated: `13220 + r * (81321 ±0)` - // Minimum execution time: 295_922_000 picoseconds. - Weight::from_parts(322_472_877, 13220) - // Standard Error: 993_812 - .saturating_add(Weight::from_parts(259_075_422, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().reads((36_u64).saturating_mul(r.into()))) + /// The range of component `n` is `[0, 32]`. + fn seal_terminate(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `319 + n * (78 ±0)` + // Estimated: `3784 + n * (2553 ±0)` + // Minimum execution time: 14_403_000 picoseconds. + Weight::from_parts(16_478_113, 3784) + // Standard Error: 6_667 + .saturating_add(Weight::from_parts(3_641_603, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(T::DbWeight::get().writes((41_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 81321).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2553).saturating_mul(n.into())) } /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_random(r: u32, ) -> Weight { + fn seal_random() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1561` - // Minimum execution time: 9_427_000 picoseconds. - Weight::from_parts(12_996_213, 1561) - // Standard Error: 845 - .saturating_add(Weight::from_parts(1_182_642, 0).saturating_mul(r.into())) + // Minimum execution time: 3_639_000 picoseconds. + Weight::from_parts(3_801_000, 1561) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_deposit_event(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_304_000 picoseconds. - Weight::from_parts(25_678_842, 0) - // Standard Error: 1_855 - .saturating_add(Weight::from_parts(1_814_511, 0).saturating_mul(r.into())) - } /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[0, 4]`. /// The range of component `n` is `[0, 16384]`. - fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { + fn seal_deposit_event(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `990 + t * (2475 ±0)` - // Minimum execution time: 23_425_000 picoseconds. - Weight::from_parts(15_229_010, 990) - // Standard Error: 14_380 - .saturating_add(Weight::from_parts(2_545_653, 0).saturating_mul(t.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(594, 0).saturating_mul(n.into())) + // Minimum execution time: 4_102_000 picoseconds. + Weight::from_parts(4_256_984, 990) + // Standard Error: 6_777 + .saturating_add(Weight::from_parts(2_331_893, 0).saturating_mul(t.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) .saturating_add(Weight::from_parts(0, 2475).saturating_mul(t.into())) } - /// The range of component `r` is `[0, 1600]`. - fn seal_debug_message(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_117_000 picoseconds. - Weight::from_parts(12_887_533, 0) - // Standard Error: 83 - .saturating_add(Weight::from_parts(99_373, 0).saturating_mul(r.into())) - } /// The range of component `i` is `[0, 1048576]`. - fn seal_debug_message_per_byte(i: u32, ) -> Weight { + fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_982_000 picoseconds. - Weight::from_parts(11_176_000, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(983, 0).saturating_mul(i.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_set_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_150_000 picoseconds. - Weight::from_parts(9_269_000, 105) - // Standard Error: 8_147 - .saturating_add(Weight::from_parts(5_339_554, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 16384]`. - fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `245` - // Estimated: `245` - // Minimum execution time: 19_085_000 picoseconds. - Weight::from_parts(20_007_323, 245) - // Standard Error: 3 - .saturating_add(Weight::from_parts(291, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 385_000 picoseconds. + Weight::from_parts(427_000, 0) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_272, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { + /// The range of component `o` is `[0, 16384]`. + fn seal_set_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 19_127_000 picoseconds. - Weight::from_parts(21_152_987, 248) - // Standard Error: 3 - .saturating_add(Weight::from_parts(42, 0).saturating_mul(n.into())) + // Measured: `250 + o * (1 ±0)` + // Estimated: `249 + o * (1 ±0)` + // Minimum execution time: 10_128_000 picoseconds. + Weight::from_parts(9_963_519, 249) + // Standard Error: 1 + .saturating_add(Weight::from_parts(327, 0).saturating_mul(n.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(58, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_clear_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_264_000 picoseconds. - Weight::from_parts(9_449_000, 105) - // Standard Error: 8_196 - .saturating_add(Weight::from_parts(5_325_578, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_clear_storage_per_byte(n: u32, ) -> Weight { + fn seal_clear_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 18_489_000 picoseconds. - Weight::from_parts(19_916_153, 248) + // Minimum execution time: 7_921_000 picoseconds. + Weight::from_parts(9_290_526, 248) // Standard Error: 2 - .saturating_add(Weight::from_parts(97, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(77, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_get_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_299_000 picoseconds. - Weight::from_parts(9_464_000, 105) - // Standard Error: 6_827 - .saturating_add(Weight::from_parts(4_720_699, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_get_storage_per_byte(n: u32, ) -> Weight { + fn seal_get_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 17_981_000 picoseconds. - Weight::from_parts(19_802_353, 248) + // Minimum execution time: 7_403_000 picoseconds. + Weight::from_parts(8_815_037, 248) // Standard Error: 3 - .saturating_add(Weight::from_parts(617, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(701, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_contains_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_891_000 picoseconds. - Weight::from_parts(10_046_000, 105) - // Standard Error: 6_993 - .saturating_add(Weight::from_parts(4_601_167, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_contains_storage_per_byte(n: u32, ) -> Weight { + fn seal_contains_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 17_229_000 picoseconds. - Weight::from_parts(18_302_733, 248) + // Minimum execution time: 6_590_000 picoseconds. + Weight::from_parts(7_949_861, 248) // Standard Error: 2 - .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(76, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_take_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_323_000 picoseconds. - Weight::from_parts(9_462_000, 105) - // Standard Error: 8_031 - .saturating_add(Weight::from_parts(5_433_981, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_take_storage_per_byte(n: u32, ) -> Weight { + fn seal_take_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 18_711_000 picoseconds. - Weight::from_parts(20_495_670, 248) + // Minimum execution time: 7_900_000 picoseconds. + Weight::from_parts(9_988_151, 248) // Standard Error: 3 - .saturating_add(Weight::from_parts(640, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(703, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: `System::Account` (r:1601 w:1601) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_transfer(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `770` - // Estimated: `4221 + r * (2475 ±0)` - // Minimum execution time: 9_226_000 picoseconds. - Weight::from_parts(9_394_000, 4221) - // Standard Error: 14_741 - .saturating_add(Weight::from_parts(34_179_316, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2475).saturating_mul(r.into())) + fn seal_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `140` + // Estimated: `0` + // Minimum execution time: 9_023_000 picoseconds. + Weight::from_parts(9_375_000, 0) } - /// Storage: `Contracts::ContractInfoOf` (r:800 w:801) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::EventTopics` (r:801 w:801) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_call(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `520 + r * (170 ±0)` - // Estimated: `6463 + r * (2646 ±0)` - // Minimum execution time: 9_455_000 picoseconds. - Weight::from_parts(9_671_000, 6463) - // Standard Error: 126_080 - .saturating_add(Weight::from_parts(244_204_040, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2646).saturating_mul(r.into())) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// The range of component `t` is `[0, 1]`. + /// The range of component `i` is `[0, 1048576]`. + fn seal_call(t: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `620 + t * (280 ±0)` + // Estimated: `4085 + t * (2182 ±0)` + // Minimum execution time: 157_109_000 picoseconds. + Weight::from_parts(159_458_069, 4085) + // Standard Error: 339_702 + .saturating_add(Weight::from_parts(44_066_869, 0).saturating_mul(t.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(6, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(0, 2182).saturating_mul(t.into())) } - /// Storage: `Contracts::CodeInfoOf` (r:735 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:735 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::EventTopics` (r:736 w:736) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:0 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_delegate_call(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + r * (527 ±0)` - // Estimated: `6447 + r * (2583 ±10)` - // Minimum execution time: 9_274_000 picoseconds. - Weight::from_parts(9_437_000, 6447) - // Standard Error: 150_832 - .saturating_add(Weight::from_parts(244_196_269, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2583).saturating_mul(r.into())) - } - /// Storage: `Contracts::ContractInfoOf` (r:1 w:2) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// The range of component `t` is `[0, 1]`. - /// The range of component `c` is `[0, 1048576]`. - fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `699 + t * (277 ±0)` - // Estimated: `6639 + t * (3458 ±0)` - // Minimum execution time: 214_483_000 picoseconds. - Weight::from_parts(122_634_366, 6639) - // Standard Error: 2_499_235 - .saturating_add(Weight::from_parts(41_326_008, 0).saturating_mul(t.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) - .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 3458).saturating_mul(t.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:800 w:800) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:800 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Contracts::Nonce` (r:1 w:0) - /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:800 w:801) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `System::Account` (r:802 w:802) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:801 w:801) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[1, 800]`. - fn seal_instantiate(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1097 + r * (188 ±0)` - // Estimated: `6990 + r * (2664 ±0)` - // Minimum execution time: 341_569_000 picoseconds. - Weight::from_parts(360_574_000, 6990) - // Standard Error: 259_746 - .saturating_add(Weight::from_parts(337_944_674, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2664).saturating_mul(r.into())) + fn seal_delegate_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `430` + // Estimated: `3895` + // Minimum execution time: 143_384_000 picoseconds. + Weight::from_parts(147_554_000, 3895) + .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) @@ -1153,256 +830,149 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:0) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:2) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `System::Account` (r:3 w:3) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. - fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `760 + t * (104 ±0)` - // Estimated: `6719 + t * (2549 ±1)` - // Minimum execution time: 1_863_119_000 picoseconds. - Weight::from_parts(900_189_174, 6719) - // Standard Error: 13_040_979 - .saturating_add(Weight::from_parts(4_056_063, 0).saturating_mul(t.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(1_028, 0).saturating_mul(i.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(10_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) - .saturating_add(T::DbWeight::get().writes(7_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 2549).saturating_mul(t.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_sha2_256(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_211_000 picoseconds. - Weight::from_parts(11_696_412, 0) - // Standard Error: 388 - .saturating_add(Weight::from_parts(265_538, 0).saturating_mul(r.into())) + fn seal_instantiate(t: u32, i: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `676` + // Estimated: `4138` + // Minimum execution time: 1_798_243_000 picoseconds. + Weight::from_parts(82_642_573, 4138) + // Standard Error: 6_831_260 + .saturating_add(Weight::from_parts(159_867_027, 0).saturating_mul(t.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_534, 0).saturating_mul(i.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_809, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 10_296_000 picoseconds. - Weight::from_parts(572_494, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_067, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_keccak_256(r: u32, ) -> Weight { + fn seal_hash_sha2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_177_000 picoseconds. - Weight::from_parts(8_620_481, 0) - // Standard Error: 249 - .saturating_add(Weight::from_parts(674_502, 0).saturating_mul(r.into())) + // Minimum execution time: 875_000 picoseconds. + Weight::from_parts(904_000, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_145, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { + fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_240_000 picoseconds. - Weight::from_parts(8_696_186, 0) + // Minimum execution time: 1_475_000 picoseconds. + Weight::from_parts(1_551_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_328, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_blake2_256(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_889_000 picoseconds. - Weight::from_parts(16_103_170, 0) - // Standard Error: 343 - .saturating_add(Weight::from_parts(328_939, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(3_410, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { + fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_405_000 picoseconds. - Weight::from_parts(2_264_024, 0) + // Minimum execution time: 821_000 picoseconds. + Weight::from_parts(850_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_196, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_blake2_128(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_215_000 picoseconds. - Weight::from_parts(10_505_632, 0) - // Standard Error: 240 - .saturating_add(Weight::from_parts(324_854, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(1_279, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { + fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_440_000 picoseconds. - Weight::from_parts(2_575_889, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + // Minimum execution time: 747_000 picoseconds. + Weight::from_parts(773_000, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_276, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 125697]`. - fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 55_119_000 picoseconds. - Weight::from_parts(56_732_248, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(4_639, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 160]`. - fn seal_sr25519_verify(r: u32, ) -> Weight { + fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_176_000 picoseconds. - Weight::from_parts(9_861_102, 0) - // Standard Error: 6_029 - .saturating_add(Weight::from_parts(45_948_571, 0).saturating_mul(r.into())) + // Minimum execution time: 43_154_000 picoseconds. + Weight::from_parts(45_087_558, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(4_628, 0).saturating_mul(n.into())) } - /// The range of component `r` is `[0, 160]`. - fn seal_ecdsa_recover(r: u32, ) -> Weight { + fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_293_000 picoseconds. - Weight::from_parts(28_785_765, 0) - // Standard Error: 9_160 - .saturating_add(Weight::from_parts(45_566_150, 0).saturating_mul(r.into())) + // Minimum execution time: 47_193_000 picoseconds. + Weight::from_parts(48_514_000, 0) } - /// The range of component `r` is `[0, 160]`. - fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { + fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_206_000 picoseconds. - Weight::from_parts(12_420_664, 0) - // Standard Error: 3_489 - .saturating_add(Weight::from_parts(11_628_989, 0).saturating_mul(r.into())) + // Minimum execution time: 13_083_000 picoseconds. + Weight::from_parts(13_218_000, 0) } - /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1535 w:0) + /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1537 w:1537) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_set_code_hash(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + r * (926 ±0)` - // Estimated: `8969 + r * (3047 ±7)` - // Minimum execution time: 9_219_000 picoseconds. - Weight::from_parts(9_385_000, 8969) - // Standard Error: 45_562 - .saturating_add(Weight::from_parts(26_360_661, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 3047).saturating_mul(r.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:32 w:32) + fn seal_set_code_hash() -> Weight { + // Proof Size summary in bytes: + // Measured: `430` + // Estimated: `3895` + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_116_000, 3895) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// The range of component `r` is `[0, 32]`. - fn lock_delegate_dependency(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `274 + r * (78 ±0)` - // Estimated: `1265 + r * (2553 ±0)` - // Minimum execution time: 9_355_000 picoseconds. - Weight::from_parts(15_071_309, 1265) - // Standard Error: 9_722 - .saturating_add(Weight::from_parts(5_328_717, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2553).saturating_mul(r.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:32 w:32) + fn lock_delegate_dependency() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 9_271_000 picoseconds. + Weight::from_parts(9_640_000, 3820) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `MaxEncodedLen`) - /// The range of component `r` is `[0, 32]`. - fn unlock_delegate_dependency(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `275 + r * (78 ±0)` - // Estimated: `990 + r * (2568 ±0)` - // Minimum execution time: 8_979_000 picoseconds. - Weight::from_parts(14_362_224, 990) - // Standard Error: 9_137 - .saturating_add(Weight::from_parts(4_488_748, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2568).saturating_mul(r.into())) + fn unlock_delegate_dependency() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3558` + // Minimum execution time: 8_182_000 picoseconds. + Weight::from_parts(8_343_000, 3558) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_reentrance_count(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `861 + r * (3 ±0)` - // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 269_704_000 picoseconds. - Weight::from_parts(289_916_035, 9282) - // Standard Error: 408 - .saturating_add(Weight::from_parts(166_040, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) + fn seal_reentrance_count() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 320_000 picoseconds. + Weight::from_parts(347_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_account_reentrance_count(r: u32, ) -> Weight { + fn seal_account_reentrance_count() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_361_000 picoseconds. - Weight::from_parts(11_633_836, 0) - // Standard Error: 86 - .saturating_add(Weight::from_parts(83_083, 0).saturating_mul(r.into())) + // Minimum execution time: 345_000 picoseconds. + Weight::from_parts(370_000, 0) } /// Storage: `Contracts::Nonce` (r:1 w:0) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_instantiation_nonce(r: u32, ) -> Weight { + fn seal_instantiation_nonce() -> Weight { // Proof Size summary in bytes: // Measured: `219` // Estimated: `1704` - // Minimum execution time: 9_133_000 picoseconds. - Weight::from_parts(13_259_836, 1704) - // Standard Error: 121 - .saturating_add(Weight::from_parts(76_878, 0).saturating_mul(r.into())) + // Minimum execution time: 2_998_000 picoseconds. + Weight::from_parts(3_221_000, 1704) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// The range of component `r` is `[0, 5000]`. @@ -1410,10 +980,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 851_000 picoseconds. - Weight::from_parts(587_883, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(14_912, 0).saturating_mul(r.into())) + // Minimum execution time: 1_002_000 picoseconds. + Weight::from_parts(1_094_958, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(14_531, 0).saturating_mul(r.into())) } } @@ -1425,8 +995,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_149_000 picoseconds. - Weight::from_parts(2_274_000, 1627) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_142_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1436,10 +1006,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_863_000 picoseconds. - Weight::from_parts(13_188_000, 442) - // Standard Error: 1_053 - .saturating_add(Weight::from_parts(1_105_325, 0).saturating_mul(k.into())) + // Minimum execution time: 12_095_000 picoseconds. + Weight::from_parts(12_699_000, 442) + // Standard Error: 891 + .saturating_add(Weight::from_parts(1_114_063, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1453,10 +1023,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_432_000 picoseconds. - Weight::from_parts(9_203_290, 6149) + // Minimum execution time: 8_433_000 picoseconds. + Weight::from_parts(8_992_328, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_186, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_207, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -1469,8 +1039,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 17_177_000 picoseconds. - Weight::from_parts(17_663_000, 6450) + // Minimum execution time: 16_415_000 picoseconds. + Weight::from_parts(17_348_000, 6450) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1483,10 +1053,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_636_000 picoseconds. - Weight::from_parts(3_774_000, 3635) - // Standard Error: 542 - .saturating_add(Weight::from_parts(1_260_058, 0).saturating_mul(k.into())) + // Minimum execution time: 3_433_000 picoseconds. + Weight::from_parts(3_490_000, 3635) + // Standard Error: 1_043 + .saturating_add(Weight::from_parts(1_225_953, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -1496,8 +1066,6 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -1505,13 +1073,13 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 125952]`. fn v12_migration_step(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `328 + c * (1 ±0)` - // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 21_585_000 picoseconds. - Weight::from_parts(22_069_944, 6266) - // Standard Error: 1 - .saturating_add(Weight::from_parts(404, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Measured: `325 + c * (1 ±0)` + // Estimated: `6263 + c * (1 ±0)` + // Minimum execution time: 16_421_000 picoseconds. + Weight::from_parts(16_822_963, 6263) + // Standard Error: 0 + .saturating_add(Weight::from_parts(456, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } @@ -1521,8 +1089,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 13_283_000 picoseconds. - Weight::from_parts(14_015_000, 6380) + // Minimum execution time: 12_569_000 picoseconds. + Weight::from_parts(13_277_000, 6380) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1536,8 +1104,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 48_022_000 picoseconds. - Weight::from_parts(49_627_000, 6292) + // Minimum execution time: 46_777_000 picoseconds. + Weight::from_parts(47_690_000, 6292) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1549,8 +1117,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 58_374_000 picoseconds. - Weight::from_parts(59_615_000, 6534) + // Minimum execution time: 55_280_000 picoseconds. + Weight::from_parts(57_081_000, 6534) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1560,8 +1128,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `409` // Estimated: `6349` - // Minimum execution time: 12_559_000 picoseconds. - Weight::from_parts(12_947_000, 6349) + // Minimum execution time: 12_077_000 picoseconds. + Weight::from_parts(12_647_000, 6349) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1571,8 +1139,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_480_000 picoseconds. - Weight::from_parts(2_680_000, 1627) + // Minimum execution time: 2_559_000 picoseconds. + Weight::from_parts(2_711_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1584,8 +1152,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 12_625_000 picoseconds. - Weight::from_parts(13_094_000, 3631) + // Minimum execution time: 12_238_000 picoseconds. + Weight::from_parts(12_627_000, 3631) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1596,7 +1164,7 @@ impl WeightInfo for () { // Measured: `142` // Estimated: `3607` // Minimum execution time: 4_836_000 picoseconds. - Weight::from_parts(5_182_000, 3607) + Weight::from_parts(5_086_000, 3607) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -1607,8 +1175,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_319_000 picoseconds. - Weight::from_parts(6_582_000, 3632) + // Minimum execution time: 6_147_000 picoseconds. + Weight::from_parts(6_380_000, 3632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -1619,15 +1187,13 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_532_000 picoseconds. - Weight::from_parts(6_909_000, 3607) + // Minimum execution time: 6_140_000 picoseconds. + Weight::from_parts(6_670_000, 3607) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1638,31 +1204,25 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `804 + c * (1 ±0)` - // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 305_778_000 picoseconds. - Weight::from_parts(282_321_249, 9217) - // Standard Error: 72 - .saturating_add(Weight::from_parts(33_456, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Measured: `801 + c * (1 ±0)` + // Estimated: `4264 + c * (1 ±0)` + // Minimum execution time: 354_459_000 picoseconds. + Weight::from_parts(332_397_871, 4264) + // Standard Error: 70 + .saturating_add(Weight::from_parts(33_775, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:3 w:3) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -1678,18 +1238,18 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `326` - // Estimated: `8740` - // Minimum execution time: 3_810_809_000 picoseconds. - Weight::from_parts(739_511_598, 8740) - // Standard Error: 140 - .saturating_add(Weight::from_parts(67_574, 0).saturating_mul(c.into())) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_488, 0).saturating_mul(i.into())) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_537, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(14_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Measured: `323` + // Estimated: `6262` + // Minimum execution time: 4_239_452_000 picoseconds. + Weight::from_parts(800_849_282, 6262) + // Standard Error: 117 + .saturating_add(Weight::from_parts(68_435, 0).saturating_mul(c.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(1_653, 0).saturating_mul(i.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(1_668, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -1697,8 +1257,6 @@ impl WeightInfo for () { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -1707,29 +1265,25 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563` - // Estimated: `8982` - // Minimum execution time: 1_986_789_000 picoseconds. - Weight::from_parts(2_017_466_000, 8982) + // Measured: `560` + // Estimated: `4029` + // Minimum execution time: 2_085_570_000 picoseconds. + Weight::from_parts(2_112_501_000, 4029) // Standard Error: 26 - .saturating_add(Weight::from_parts(827, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(888, 0).saturating_mul(i.into())) // Standard Error: 26 - .saturating_add(Weight::from_parts(781, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(13_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(795, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1740,64 +1294,54 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `829` - // Estimated: `9244` - // Minimum execution time: 210_724_000 picoseconds. - Weight::from_parts(218_608_000, 9244) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Measured: `826` + // Estimated: `4291` + // Minimum execution time: 201_900_000 picoseconds. + Weight::from_parts(206_738_000, 4291) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn upload_code_determinism_enforced(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `6085` - // Minimum execution time: 271_259_000 picoseconds. - Weight::from_parts(298_852_854, 6085) - // Standard Error: 65 - .saturating_add(Weight::from_parts(33_547, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Measured: `142` + // Estimated: `3607` + // Minimum execution time: 330_704_000 picoseconds. + Weight::from_parts(345_129_342, 3607) + // Standard Error: 51 + .saturating_add(Weight::from_parts(33_126, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. fn upload_code_determinism_relaxed(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `6085` - // Minimum execution time: 278_167_000 picoseconds. - Weight::from_parts(311_888_941, 6085) - // Standard Error: 58 - .saturating_add(Weight::from_parts(33_595, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Measured: `142` + // Estimated: `3607` + // Minimum execution time: 343_339_000 picoseconds. + Weight::from_parts(356_479_729, 3607) + // Standard Error: 49 + .saturating_add(Weight::from_parts(33_404, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -1805,18 +1349,16 @@ impl WeightInfo for () { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1 w:1) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 47_403_000 picoseconds. - Weight::from_parts(48_707_000, 3780) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 42_241_000 picoseconds. + Weight::from_parts(43_365_000, 3780) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) @@ -1824,610 +1366,331 @@ impl WeightInfo for () { /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `System::EventTopics` (r:3 w:3) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: // Measured: `552` - // Estimated: `8967` - // Minimum execution time: 35_361_000 picoseconds. - Weight::from_parts(36_714_000, 8967) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Estimated: `6492` + // Minimum execution time: 26_318_000 picoseconds. + Weight::from_parts(27_840_000, 6492) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// The range of component `r` is `[0, 1600]`. - fn seal_caller(r: u32, ) -> Weight { + fn noop_host_fn(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 9_397_000 picoseconds. + Weight::from_parts(9_318_986, 0) + // Standard Error: 72 + .saturating_add(Weight::from_parts(72_994, 0).saturating_mul(r.into())) + } + fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_340_000 picoseconds. - Weight::from_parts(9_360_237, 0) - // Standard Error: 269 - .saturating_add(Weight::from_parts(249_611, 0).saturating_mul(r.into())) + // Minimum execution time: 644_000 picoseconds. + Weight::from_parts(687_000, 0) } - /// Storage: `Contracts::ContractInfoOf` (r:1600 w:0) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:0) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_is_contract(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `509 + r * (77 ±0)` - // Estimated: `1467 + r * (2552 ±0)` - // Minimum execution time: 9_059_000 picoseconds. - Weight::from_parts(9_201_000, 1467) - // Standard Error: 5_643 - .saturating_add(Weight::from_parts(3_343_859, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2552).saturating_mul(r.into())) - } - /// Storage: `Contracts::ContractInfoOf` (r:1600 w:0) + fn seal_is_contract() -> Weight { + // Proof Size summary in bytes: + // Measured: `354` + // Estimated: `3819` + // Minimum execution time: 6_465_000 picoseconds. + Weight::from_parts(6_850_000, 3819) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Contracts::ContractInfoOf` (r:1 w:0) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_code_hash(r: u32, ) -> Weight { + fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `517 + r * (170 ±0)` - // Estimated: `1468 + r * (2645 ±0)` - // Minimum execution time: 9_220_000 picoseconds. - Weight::from_parts(9_399_000, 1468) - // Standard Error: 6_194 - .saturating_add(Weight::from_parts(4_172_011, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2645).saturating_mul(r.into())) + // Measured: `447` + // Estimated: `3912` + // Minimum execution time: 7_735_000 picoseconds. + Weight::from_parts(8_115_000, 3912) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_own_code_hash(r: u32, ) -> Weight { + fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_707_000 picoseconds. - Weight::from_parts(10_100_456, 0) - // Standard Error: 234 - .saturating_add(Weight::from_parts(338_464, 0).saturating_mul(r.into())) + // Minimum execution time: 717_000 picoseconds. + Weight::from_parts(791_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_caller_is_origin(r: u32, ) -> Weight { + fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_524_000 picoseconds. - Weight::from_parts(10_813_389, 0) - // Standard Error: 76 - .saturating_add(Weight::from_parts(102_535, 0).saturating_mul(r.into())) + // Minimum execution time: 365_000 picoseconds. + Weight::from_parts(427_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_caller_is_root(r: u32, ) -> Weight { + fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_799_000 picoseconds. - Weight::from_parts(10_886_744, 0) - // Standard Error: 75 - .saturating_add(Weight::from_parts(80_901, 0).saturating_mul(r.into())) + // Minimum execution time: 331_000 picoseconds. + Weight::from_parts(363_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_address(r: u32, ) -> Weight { + fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_895_000 picoseconds. - Weight::from_parts(10_658_338, 0) - // Standard Error: 189 - .saturating_add(Weight::from_parts(249_694, 0).saturating_mul(r.into())) + // Minimum execution time: 586_000 picoseconds. + Weight::from_parts(625_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_gas_left(r: u32, ) -> Weight { + fn seal_gas_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_643_000 picoseconds. - Weight::from_parts(10_932_126, 0) - // Standard Error: 153 - .saturating_add(Weight::from_parts(280_924, 0).saturating_mul(r.into())) + // Minimum execution time: 680_000 picoseconds. + Weight::from_parts(734_000, 0) } - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_balance(r: u32, ) -> Weight { + fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `140` - // Estimated: `3599` - // Minimum execution time: 9_548_000 picoseconds. - Weight::from_parts(9_737_000, 3599) - // Standard Error: 971 - .saturating_add(Weight::from_parts(1_704_134, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Estimated: `0` + // Minimum execution time: 4_732_000 picoseconds. + Weight::from_parts(5_008_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_value_transferred(r: u32, ) -> Weight { + fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_172_000 picoseconds. - Weight::from_parts(18_255_933, 0) - // Standard Error: 540 - .saturating_add(Weight::from_parts(230_929, 0).saturating_mul(r.into())) + // Minimum execution time: 608_000 picoseconds. + Weight::from_parts(635_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_minimum_balance(r: u32, ) -> Weight { + fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_232_000 picoseconds. - Weight::from_parts(9_796_584, 0) - // Standard Error: 208 - .saturating_add(Weight::from_parts(239_962, 0).saturating_mul(r.into())) + // Minimum execution time: 571_000 picoseconds. + Weight::from_parts(606_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_block_number(r: u32, ) -> Weight { + fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_747_000 picoseconds. - Weight::from_parts(8_733_230, 0) - // Standard Error: 377 - .saturating_add(Weight::from_parts(253_801, 0).saturating_mul(r.into())) + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(584_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_now(r: u32, ) -> Weight { + fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_214_000 picoseconds. - Weight::from_parts(10_194_153, 0) - // Standard Error: 516 - .saturating_add(Weight::from_parts(247_621, 0).saturating_mul(r.into())) + // Minimum execution time: 552_000 picoseconds. + Weight::from_parts(612_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_weight_to_fee(r: u32, ) -> Weight { + fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 9_022_000 picoseconds. - Weight::from_parts(22_051_160, 1552) - // Standard Error: 697 - .saturating_add(Weight::from_parts(709_612, 0).saturating_mul(r.into())) + // Minimum execution time: 4_396_000 picoseconds. + Weight::from_parts(4_630_000, 1552) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_input(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_135_000 picoseconds. - Weight::from_parts(10_646_215, 0) - // Standard Error: 161 - .saturating_add(Weight::from_parts(170_336, 0).saturating_mul(r.into())) - } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 1048576]`. - fn seal_input_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `9287` - // Minimum execution time: 273_896_000 picoseconds. - Weight::from_parts(148_309_654, 9287) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_355, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// The range of component `r` is `[0, 1]`. - fn seal_return(r: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048572]`. + fn seal_input(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_906_000 picoseconds. - Weight::from_parts(9_264_446, 0) - // Standard Error: 19_760 - .saturating_add(Weight::from_parts(1_256_053, 0).saturating_mul(r.into())) + // Minimum execution time: 494_000 picoseconds. + Weight::from_parts(510_000, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(303, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 1048576]`. - fn seal_return_per_byte(n: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048572]`. + fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_266_000 picoseconds. - Weight::from_parts(10_602_261, 0) - // Standard Error: 0 - .saturating_add(Weight::from_parts(318, 0).saturating_mul(n.into())) + // Minimum execution time: 311_000 picoseconds. + Weight::from_parts(346_000, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(480, 0).saturating_mul(n.into())) } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:1 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::DeletionQueueCounter` (r:1 w:1) /// Proof: `Contracts::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:4 w:4) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) + /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) - /// The range of component `r` is `[0, 1]`. - fn seal_terminate(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `4805 + r * (2121 ±0)` - // Estimated: `13220 + r * (81321 ±0)` - // Minimum execution time: 295_922_000 picoseconds. - Weight::from_parts(322_472_877, 13220) - // Standard Error: 993_812 - .saturating_add(Weight::from_parts(259_075_422, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().reads((36_u64).saturating_mul(r.into()))) + /// The range of component `n` is `[0, 32]`. + fn seal_terminate(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `319 + n * (78 ±0)` + // Estimated: `3784 + n * (2553 ±0)` + // Minimum execution time: 14_403_000 picoseconds. + Weight::from_parts(16_478_113, 3784) + // Standard Error: 6_667 + .saturating_add(Weight::from_parts(3_641_603, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(RocksDbWeight::get().writes((41_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 81321).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2553).saturating_mul(n.into())) } /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_random(r: u32, ) -> Weight { + fn seal_random() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1561` - // Minimum execution time: 9_427_000 picoseconds. - Weight::from_parts(12_996_213, 1561) - // Standard Error: 845 - .saturating_add(Weight::from_parts(1_182_642, 0).saturating_mul(r.into())) + // Minimum execution time: 3_639_000 picoseconds. + Weight::from_parts(3_801_000, 1561) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// The range of component `r` is `[0, 1600]`. - fn seal_deposit_event(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_304_000 picoseconds. - Weight::from_parts(25_678_842, 0) - // Standard Error: 1_855 - .saturating_add(Weight::from_parts(1_814_511, 0).saturating_mul(r.into())) - } /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[0, 4]`. /// The range of component `n` is `[0, 16384]`. - fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { + fn seal_deposit_event(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `990 + t * (2475 ±0)` - // Minimum execution time: 23_425_000 picoseconds. - Weight::from_parts(15_229_010, 990) - // Standard Error: 14_380 - .saturating_add(Weight::from_parts(2_545_653, 0).saturating_mul(t.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(594, 0).saturating_mul(n.into())) + // Minimum execution time: 4_102_000 picoseconds. + Weight::from_parts(4_256_984, 990) + // Standard Error: 6_777 + .saturating_add(Weight::from_parts(2_331_893, 0).saturating_mul(t.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) .saturating_add(Weight::from_parts(0, 2475).saturating_mul(t.into())) } - /// The range of component `r` is `[0, 1600]`. - fn seal_debug_message(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 11_117_000 picoseconds. - Weight::from_parts(12_887_533, 0) - // Standard Error: 83 - .saturating_add(Weight::from_parts(99_373, 0).saturating_mul(r.into())) - } /// The range of component `i` is `[0, 1048576]`. - fn seal_debug_message_per_byte(i: u32, ) -> Weight { + fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_982_000 picoseconds. - Weight::from_parts(11_176_000, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(983, 0).saturating_mul(i.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_set_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_150_000 picoseconds. - Weight::from_parts(9_269_000, 105) - // Standard Error: 8_147 - .saturating_add(Weight::from_parts(5_339_554, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 16384]`. - fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `245` - // Estimated: `245` - // Minimum execution time: 19_085_000 picoseconds. - Weight::from_parts(20_007_323, 245) - // Standard Error: 3 - .saturating_add(Weight::from_parts(291, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 385_000 picoseconds. + Weight::from_parts(427_000, 0) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_272, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { + /// The range of component `o` is `[0, 16384]`. + fn seal_set_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 19_127_000 picoseconds. - Weight::from_parts(21_152_987, 248) - // Standard Error: 3 - .saturating_add(Weight::from_parts(42, 0).saturating_mul(n.into())) + // Measured: `250 + o * (1 ±0)` + // Estimated: `249 + o * (1 ±0)` + // Minimum execution time: 10_128_000 picoseconds. + Weight::from_parts(9_963_519, 249) + // Standard Error: 1 + .saturating_add(Weight::from_parts(327, 0).saturating_mul(n.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(58, 0).saturating_mul(o.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_clear_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_264_000 picoseconds. - Weight::from_parts(9_449_000, 105) - // Standard Error: 8_196 - .saturating_add(Weight::from_parts(5_325_578, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_clear_storage_per_byte(n: u32, ) -> Weight { + fn seal_clear_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 18_489_000 picoseconds. - Weight::from_parts(19_916_153, 248) + // Minimum execution time: 7_921_000 picoseconds. + Weight::from_parts(9_290_526, 248) // Standard Error: 2 - .saturating_add(Weight::from_parts(97, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(77, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_get_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_299_000 picoseconds. - Weight::from_parts(9_464_000, 105) - // Standard Error: 6_827 - .saturating_add(Weight::from_parts(4_720_699, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_get_storage_per_byte(n: u32, ) -> Weight { + fn seal_get_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 17_981_000 picoseconds. - Weight::from_parts(19_802_353, 248) + // Minimum execution time: 7_403_000 picoseconds. + Weight::from_parts(8_815_037, 248) // Standard Error: 3 - .saturating_add(Weight::from_parts(617, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(701, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_contains_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_891_000 picoseconds. - Weight::from_parts(10_046_000, 105) - // Standard Error: 6_993 - .saturating_add(Weight::from_parts(4_601_167, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_contains_storage_per_byte(n: u32, ) -> Weight { + fn seal_contains_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 17_229_000 picoseconds. - Weight::from_parts(18_302_733, 248) + // Minimum execution time: 6_590_000 picoseconds. + Weight::from_parts(7_949_861, 248) // Standard Error: 2 - .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(76, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_take_storage(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `108 + r * (150 ±0)` - // Estimated: `105 + r * (151 ±0)` - // Minimum execution time: 9_323_000 picoseconds. - Weight::from_parts(9_462_000, 105) - // Standard Error: 8_031 - .saturating_add(Weight::from_parts(5_433_981, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into())) - } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 16384]`. - fn seal_take_storage_per_byte(n: u32, ) -> Weight { + fn seal_take_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `248 + n * (1 ±0)` - // Minimum execution time: 18_711_000 picoseconds. - Weight::from_parts(20_495_670, 248) + // Minimum execution time: 7_900_000 picoseconds. + Weight::from_parts(9_988_151, 248) // Standard Error: 3 - .saturating_add(Weight::from_parts(640, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(703, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: `System::Account` (r:1601 w:1601) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_transfer(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `770` - // Estimated: `4221 + r * (2475 ±0)` - // Minimum execution time: 9_226_000 picoseconds. - Weight::from_parts(9_394_000, 4221) - // Standard Error: 14_741 - .saturating_add(Weight::from_parts(34_179_316, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2475).saturating_mul(r.into())) + fn seal_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `140` + // Estimated: `0` + // Minimum execution time: 9_023_000 picoseconds. + Weight::from_parts(9_375_000, 0) } - /// Storage: `Contracts::ContractInfoOf` (r:800 w:801) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::EventTopics` (r:801 w:801) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_call(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `520 + r * (170 ±0)` - // Estimated: `6463 + r * (2646 ±0)` - // Minimum execution time: 9_455_000 picoseconds. - Weight::from_parts(9_671_000, 6463) - // Standard Error: 126_080 - .saturating_add(Weight::from_parts(244_204_040, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2646).saturating_mul(r.into())) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// The range of component `t` is `[0, 1]`. + /// The range of component `i` is `[0, 1048576]`. + fn seal_call(t: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `620 + t * (280 ±0)` + // Estimated: `4085 + t * (2182 ±0)` + // Minimum execution time: 157_109_000 picoseconds. + Weight::from_parts(159_458_069, 4085) + // Standard Error: 339_702 + .saturating_add(Weight::from_parts(44_066_869, 0).saturating_mul(t.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(6, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(0, 2182).saturating_mul(t.into())) } - /// Storage: `Contracts::CodeInfoOf` (r:735 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:735 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::EventTopics` (r:736 w:736) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:0 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// The range of component `r` is `[0, 800]`. - fn seal_delegate_call(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + r * (527 ±0)` - // Estimated: `6447 + r * (2583 ±10)` - // Minimum execution time: 9_274_000 picoseconds. - Weight::from_parts(9_437_000, 6447) - // Standard Error: 150_832 - .saturating_add(Weight::from_parts(244_196_269, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2583).saturating_mul(r.into())) - } - /// Storage: `Contracts::ContractInfoOf` (r:1 w:2) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// The range of component `t` is `[0, 1]`. - /// The range of component `c` is `[0, 1048576]`. - fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `699 + t * (277 ±0)` - // Estimated: `6639 + t * (3458 ±0)` - // Minimum execution time: 214_483_000 picoseconds. - Weight::from_parts(122_634_366, 6639) - // Standard Error: 2_499_235 - .saturating_add(Weight::from_parts(41_326_008, 0).saturating_mul(t.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into()))) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 3458).saturating_mul(t.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:800 w:800) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:800 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Contracts::Nonce` (r:1 w:0) - /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:800 w:801) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `System::Account` (r:802 w:802) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:801 w:801) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[1, 800]`. - fn seal_instantiate(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1097 + r * (188 ±0)` - // Estimated: `6990 + r * (2664 ±0)` - // Minimum execution time: 341_569_000 picoseconds. - Weight::from_parts(360_574_000, 6990) - // Standard Error: 259_746 - .saturating_add(Weight::from_parts(337_944_674, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2664).saturating_mul(r.into())) + fn seal_delegate_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `430` + // Estimated: `3895` + // Minimum execution time: 143_384_000 picoseconds. + Weight::from_parts(147_554_000, 3895) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) @@ -2435,256 +1698,149 @@ impl WeightInfo for () { /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:0) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:2) + /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `System::Account` (r:3 w:3) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. - fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `760 + t * (104 ±0)` - // Estimated: `6719 + t * (2549 ±1)` - // Minimum execution time: 1_863_119_000 picoseconds. - Weight::from_parts(900_189_174, 6719) - // Standard Error: 13_040_979 - .saturating_add(Weight::from_parts(4_056_063, 0).saturating_mul(t.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(1_028, 0).saturating_mul(i.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(10_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 2549).saturating_mul(t.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_sha2_256(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_211_000 picoseconds. - Weight::from_parts(11_696_412, 0) - // Standard Error: 388 - .saturating_add(Weight::from_parts(265_538, 0).saturating_mul(r.into())) + fn seal_instantiate(t: u32, i: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `676` + // Estimated: `4138` + // Minimum execution time: 1_798_243_000 picoseconds. + Weight::from_parts(82_642_573, 4138) + // Standard Error: 6_831_260 + .saturating_add(Weight::from_parts(159_867_027, 0).saturating_mul(t.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_534, 0).saturating_mul(i.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_809, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 10_296_000 picoseconds. - Weight::from_parts(572_494, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_067, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_keccak_256(r: u32, ) -> Weight { + fn seal_hash_sha2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_177_000 picoseconds. - Weight::from_parts(8_620_481, 0) - // Standard Error: 249 - .saturating_add(Weight::from_parts(674_502, 0).saturating_mul(r.into())) + // Minimum execution time: 875_000 picoseconds. + Weight::from_parts(904_000, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_145, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { + fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_240_000 picoseconds. - Weight::from_parts(8_696_186, 0) + // Minimum execution time: 1_475_000 picoseconds. + Weight::from_parts(1_551_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_328, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_blake2_256(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_889_000 picoseconds. - Weight::from_parts(16_103_170, 0) - // Standard Error: 343 - .saturating_add(Weight::from_parts(328_939, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(3_410, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { + fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_405_000 picoseconds. - Weight::from_parts(2_264_024, 0) + // Minimum execution time: 821_000 picoseconds. + Weight::from_parts(850_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_196, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 1600]`. - fn seal_hash_blake2_128(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_215_000 picoseconds. - Weight::from_parts(10_505_632, 0) - // Standard Error: 240 - .saturating_add(Weight::from_parts(324_854, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(1_279, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. - fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { + fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_440_000 picoseconds. - Weight::from_parts(2_575_889, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + // Minimum execution time: 747_000 picoseconds. + Weight::from_parts(773_000, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_276, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 125697]`. - fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 55_119_000 picoseconds. - Weight::from_parts(56_732_248, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(4_639, 0).saturating_mul(n.into())) - } - /// The range of component `r` is `[0, 160]`. - fn seal_sr25519_verify(r: u32, ) -> Weight { + fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_176_000 picoseconds. - Weight::from_parts(9_861_102, 0) - // Standard Error: 6_029 - .saturating_add(Weight::from_parts(45_948_571, 0).saturating_mul(r.into())) + // Minimum execution time: 43_154_000 picoseconds. + Weight::from_parts(45_087_558, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(4_628, 0).saturating_mul(n.into())) } - /// The range of component `r` is `[0, 160]`. - fn seal_ecdsa_recover(r: u32, ) -> Weight { + fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_293_000 picoseconds. - Weight::from_parts(28_785_765, 0) - // Standard Error: 9_160 - .saturating_add(Weight::from_parts(45_566_150, 0).saturating_mul(r.into())) + // Minimum execution time: 47_193_000 picoseconds. + Weight::from_parts(48_514_000, 0) } - /// The range of component `r` is `[0, 160]`. - fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { + fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_206_000 picoseconds. - Weight::from_parts(12_420_664, 0) - // Standard Error: 3_489 - .saturating_add(Weight::from_parts(11_628_989, 0).saturating_mul(r.into())) + // Minimum execution time: 13_083_000 picoseconds. + Weight::from_parts(13_218_000, 0) } - /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1535 w:0) + /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `System::EventTopics` (r:1537 w:1537) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_set_code_hash(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + r * (926 ±0)` - // Estimated: `8969 + r * (3047 ±7)` - // Minimum execution time: 9_219_000 picoseconds. - Weight::from_parts(9_385_000, 8969) - // Standard Error: 45_562 - .saturating_add(Weight::from_parts(26_360_661, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 3047).saturating_mul(r.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:32 w:32) + fn seal_set_code_hash() -> Weight { + // Proof Size summary in bytes: + // Measured: `430` + // Estimated: `3895` + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_116_000, 3895) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// The range of component `r` is `[0, 32]`. - fn lock_delegate_dependency(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `274 + r * (78 ±0)` - // Estimated: `1265 + r * (2553 ±0)` - // Minimum execution time: 9_355_000 picoseconds. - Weight::from_parts(15_071_309, 1265) - // Standard Error: 9_722 - .saturating_add(Weight::from_parts(5_328_717, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2553).saturating_mul(r.into())) - } - /// Storage: `Contracts::CodeInfoOf` (r:32 w:32) + fn lock_delegate_dependency() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 9_271_000 picoseconds. + Weight::from_parts(9_640_000, 3820) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `MaxEncodedLen`) - /// The range of component `r` is `[0, 32]`. - fn unlock_delegate_dependency(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `275 + r * (78 ±0)` - // Estimated: `990 + r * (2568 ±0)` - // Minimum execution time: 8_979_000 picoseconds. - Weight::from_parts(14_362_224, 990) - // Standard Error: 9_137 - .saturating_add(Weight::from_parts(4_488_748, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2568).saturating_mul(r.into())) + fn unlock_delegate_dependency() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3558` + // Minimum execution time: 8_182_000 picoseconds. + Weight::from_parts(8_343_000, 3558) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) - /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) - /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) - /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) - /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) - /// Storage: `Contracts::PristineCode` (r:1 w:0) - /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `System::EventTopics` (r:2 w:2) - /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_reentrance_count(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `861 + r * (3 ±0)` - // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 269_704_000 picoseconds. - Weight::from_parts(289_916_035, 9282) - // Standard Error: 408 - .saturating_add(Weight::from_parts(166_040, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) + fn seal_reentrance_count() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 320_000 picoseconds. + Weight::from_parts(347_000, 0) } - /// The range of component `r` is `[0, 1600]`. - fn seal_account_reentrance_count(r: u32, ) -> Weight { + fn seal_account_reentrance_count() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_361_000 picoseconds. - Weight::from_parts(11_633_836, 0) - // Standard Error: 86 - .saturating_add(Weight::from_parts(83_083, 0).saturating_mul(r.into())) + // Minimum execution time: 345_000 picoseconds. + Weight::from_parts(370_000, 0) } /// Storage: `Contracts::Nonce` (r:1 w:0) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// The range of component `r` is `[0, 1600]`. - fn seal_instantiation_nonce(r: u32, ) -> Weight { + fn seal_instantiation_nonce() -> Weight { // Proof Size summary in bytes: // Measured: `219` // Estimated: `1704` - // Minimum execution time: 9_133_000 picoseconds. - Weight::from_parts(13_259_836, 1704) - // Standard Error: 121 - .saturating_add(Weight::from_parts(76_878, 0).saturating_mul(r.into())) + // Minimum execution time: 2_998_000 picoseconds. + Weight::from_parts(3_221_000, 1704) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// The range of component `r` is `[0, 5000]`. @@ -2692,9 +1848,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 851_000 picoseconds. - Weight::from_parts(587_883, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(14_912, 0).saturating_mul(r.into())) + // Minimum execution time: 1_002_000 picoseconds. + Weight::from_parts(1_094_958, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(14_531, 0).saturating_mul(r.into())) } } diff --git a/substrate/frame/contracts/uapi/Cargo.toml b/substrate/frame/contracts/uapi/Cargo.toml index d9a5ee14f0545a7481fcfd133887c74921659589..80de7a1d5d69077d91ec9e0b845128027aad55ca 100644 --- a/substrate/frame/contracts/uapi/Cargo.toml +++ b/substrate/frame/contracts/uapi/Cargo.toml @@ -15,7 +15,7 @@ workspace = true paste = { version = "1.0", default-features = false } bitflags = "1.0" scale-info = { version = "2.11.1", default-features = false, features = ["derive"], optional = true } -scale = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ], optional = true } diff --git a/substrate/frame/conviction-voting/Cargo.toml b/substrate/frame/conviction-voting/Cargo.toml index ffb5122ed7f980a547e2d299f0a687641f0d9161..20de4d858ad62e4e499e5c4ee6786b1f5ee2f6c4 100644 --- a/substrate/frame/conviction-voting/Cargo.toml +++ b/substrate/frame/conviction-voting/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] assert_matches = "1.3.0" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } diff --git a/substrate/frame/core-fellowship/Cargo.toml b/substrate/frame/core-fellowship/Cargo.toml index b4258281b7010855bb1f81aae4bce1cd64fb774e..8773a124cd02accb450daa2218c161563a68d8bf 100644 --- a/substrate/frame/core-fellowship/Cargo.toml +++ b/substrate/frame/core-fellowship/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/core-fellowship/src/benchmarking.rs b/substrate/frame/core-fellowship/src/benchmarking.rs index fd5453310be51a65dac808ee2f07737ca8915203..b3ee3ab7d165fd87710b207ab4668bba450e2189 100644 --- a/substrate/frame/core-fellowship/src/benchmarking.rs +++ b/substrate/frame/core-fellowship/src/benchmarking.rs @@ -54,11 +54,12 @@ mod benchmarks { } fn set_benchmark_params, I: 'static>() -> Result<(), BenchmarkError> { + let max_rank = T::MaxRank::get().try_into().unwrap(); let params = ParamsType { - active_salary: [100u32.into(); 9], - passive_salary: [10u32.into(); 9], - demotion_period: [100u32.into(); 9], - min_promotion_period: [100u32.into(); 9], + active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), + passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(), + demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), + min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), offboard_timeout: 1u32.into(), }; @@ -68,11 +69,12 @@ mod benchmarks { #[benchmark] fn set_params() -> Result<(), BenchmarkError> { + let max_rank = T::MaxRank::get().try_into().unwrap(); let params = ParamsType { - active_salary: [100u32.into(); 9], - passive_salary: [10u32.into(); 9], - demotion_period: [100u32.into(); 9], - min_promotion_period: [100u32.into(); 9], + active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), + passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(), + demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), + min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(), offboard_timeout: 1u32.into(), }; @@ -151,10 +153,14 @@ mod benchmarks { fn promote() -> Result<(), BenchmarkError> { // Ensure that the `min_promotion_period` wont get in our way. let mut params = Params::::get(); - params.min_promotion_period = [Zero::zero(); RANK_COUNT]; + let max_rank = T::MaxRank::get().try_into().unwrap(); + params.min_promotion_period = BoundedVec::try_from(vec![Zero::zero(); max_rank]).unwrap(); Params::::put(¶ms); let member = make_member::(1)?; + + // Set it to the max value to ensure that any possible auto-demotion period has passed. + frame_system::Pallet::::set_block_number(BlockNumberFor::::max_value()); ensure_evidence::(&member)?; #[extrinsic_call] diff --git a/substrate/frame/core-fellowship/src/lib.rs b/substrate/frame/core-fellowship/src/lib.rs index afb188261fd448c2617189e0db71050d3d45234e..94339b85d0524a297241248312e92b31e761149c 100644 --- a/substrate/frame/core-fellowship/src/lib.rs +++ b/substrate/frame/core-fellowship/src/lib.rs @@ -61,7 +61,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_arithmetic::traits::{Saturating, Zero}; use sp_runtime::RuntimeDebug; -use sp_std::{marker::PhantomData, prelude::*}; +use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; use frame_support::{ defensive, @@ -71,7 +71,7 @@ use frame_support::{ tokens::Balance as BalanceTrait, EnsureOrigin, EnsureOriginWithArg, Get, RankedMembers, RankedMembersSwapHandler, }, - BoundedVec, + BoundedVec, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; #[cfg(test)] @@ -79,10 +79,11 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +pub mod migration; pub mod weights; pub use pallet::*; -pub use weights::WeightInfo; +pub use weights::*; /// The desired outcome for which evidence is presented. #[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] @@ -100,29 +101,46 @@ pub enum Wish { pub type Evidence = BoundedVec>::EvidenceSize>; /// The status of the pallet instance. -#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] -pub struct ParamsType { +#[derive( + Encode, + Decode, + CloneNoBound, + EqNoBound, + PartialEqNoBound, + RuntimeDebugNoBound, + TypeInfo, + MaxEncodedLen, +)] +#[scale_info(skip_type_params(Ranks))] +pub struct ParamsType< + Balance: Clone + Eq + PartialEq + Debug, + BlockNumber: Clone + Eq + PartialEq + Debug, + Ranks: Get, +> { /// The amounts to be paid when a member of a given rank (-1) is active. - active_salary: [Balance; RANKS], + pub active_salary: BoundedVec, /// The amounts to be paid when a member of a given rank (-1) is passive. - passive_salary: [Balance; RANKS], + pub passive_salary: BoundedVec, /// The period between which unproven members become demoted. - demotion_period: [BlockNumber; RANKS], + pub demotion_period: BoundedVec, /// The period between which members must wait before they may proceed to this rank. - min_promotion_period: [BlockNumber; RANKS], + pub min_promotion_period: BoundedVec, /// Amount by which an account can remain at rank 0 (candidate before being offboard entirely). - offboard_timeout: BlockNumber, + pub offboard_timeout: BlockNumber, } -impl Default - for ParamsType +impl< + Balance: Default + Copy + Eq + Debug, + BlockNumber: Default + Copy + Eq + Debug, + Ranks: Get, + > Default for ParamsType { fn default() -> Self { Self { - active_salary: [Balance::default(); RANKS], - passive_salary: [Balance::default(); RANKS], - demotion_period: [BlockNumber::default(); RANKS], - min_promotion_period: [BlockNumber::default(); RANKS], + active_salary: Default::default(), + passive_salary: Default::default(), + demotion_period: Default::default(), + min_promotion_period: Default::default(), offboard_timeout: BlockNumber::default(), } } @@ -148,11 +166,11 @@ pub mod pallet { traits::{tokens::GetSalary, EnsureOrigin}, }; use frame_system::{ensure_root, pallet_prelude::*}; - - /// Number of available ranks. - pub(crate) const RANK_COUNT: usize = 9; + /// The in-code storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(PhantomData<(T, I)>); #[pallet::config] @@ -194,9 +212,16 @@ pub mod pallet { /// The maximum size in bytes submitted evidence is allowed to be. #[pallet::constant] type EvidenceSize: Get; + + /// Represents the highest possible rank in this pallet. + /// + /// Increasing this value is supported, but decreasing it may lead to a broken state. + #[pallet::constant] + type MaxRank: Get; } - pub type ParamsOf = ParamsType<>::Balance, BlockNumberFor, RANK_COUNT>; + pub type ParamsOf = + ParamsType<>::Balance, BlockNumberFor, >::MaxRank>; pub type MemberStatusOf = MemberStatus>; pub type RankOf = <>::Members as RankedMembers>::Rank; @@ -338,8 +363,10 @@ pub mod pallet { #[pallet::call_index(1)] pub fn set_params(origin: OriginFor, params: Box>) -> DispatchResult { T::ParamsOrigin::ensure_origin_or_root(origin)?; + Params::::put(params.as_ref()); Self::deposit_event(Event::::ParamsChanged { params: *params }); + Ok(()) } @@ -540,7 +567,7 @@ pub mod pallet { /// in the range `1..=RANK_COUNT` is `None`. pub(crate) fn rank_to_index(rank: RankOf) -> Option { match TryInto::::try_into(rank) { - Ok(r) if r <= RANK_COUNT && r > 0 => Some(r - 1), + Ok(r) if r as u32 <= >::MaxRank::get() && r > 0 => Some(r - 1), _ => return None, } } diff --git a/substrate/frame/core-fellowship/src/migration.rs b/substrate/frame/core-fellowship/src/migration.rs new file mode 100644 index 0000000000000000000000000000000000000000..b8b5540a4b475be0a5a40ec2324b94f71d0da9c8 --- /dev/null +++ b/substrate/frame/core-fellowship/src/migration.rs @@ -0,0 +1,111 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Storage migrations for the core-fellowship pallet. +use super::*; +use frame_support::{ + pallet_prelude::*, + storage_alias, + traits::{DefensiveTruncateFrom, UncheckedOnRuntimeUpgrade}, + BoundedVec, +}; + +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; + +mod v0 { + use frame_system::pallet_prelude::BlockNumberFor; + + use super::*; + + #[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] + pub struct ParamsType { + pub active_salary: [Balance; RANKS], + pub passive_salary: [Balance; RANKS], + pub demotion_period: [BlockNumber; RANKS], + pub min_promotion_period: [BlockNumber; RANKS], + pub offboard_timeout: BlockNumber, + } + + impl Default + for ParamsType + { + fn default() -> Self { + Self { + active_salary: [Balance::default(); RANKS], + passive_salary: [Balance::default(); RANKS], + demotion_period: [BlockNumber::default(); RANKS], + min_promotion_period: [BlockNumber::default(); RANKS], + offboard_timeout: BlockNumber::default(), + } + } + } + + /// Number of available ranks from old version. + pub(crate) const RANK_COUNT: usize = 9; + + pub type ParamsOf = ParamsType<>::Balance, BlockNumberFor, RANK_COUNT>; + + /// V0 type for [`crate::Params`]. + #[storage_alias] + pub type Params, I: 'static> = + StorageValue, ParamsOf, ValueQuery>; +} + +pub struct MigrateToV1(PhantomData<(T, I)>); +impl, I: 'static> UncheckedOnRuntimeUpgrade for MigrateToV1 { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + ensure!( + T::MaxRank::get() >= v0::RANK_COUNT as u32, + "pallet-core-fellowship: new bound should not truncate" + ); + Ok(Default::default()) + } + + fn on_runtime_upgrade() -> frame_support::weights::Weight { + // Read the old value from storage + let old_value = v0::Params::::take(); + // Write the new value to storage + let new = crate::ParamsType { + active_salary: BoundedVec::defensive_truncate_from(old_value.active_salary.to_vec()), + passive_salary: BoundedVec::defensive_truncate_from(old_value.passive_salary.to_vec()), + demotion_period: BoundedVec::defensive_truncate_from( + old_value.demotion_period.to_vec(), + ), + min_promotion_period: BoundedVec::defensive_truncate_from( + old_value.min_promotion_period.to_vec(), + ), + offboard_timeout: old_value.offboard_timeout, + }; + crate::Params::::put(new); + T::DbWeight::get().reads_writes(1, 1) + } +} + +/// [`UncheckedOnRuntimeUpgrade`] implementation [`MigrateToV1`] wrapped in a +/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that: +/// - The migration only runs once when the on-chain storage version is 0 +/// - The on-chain storage version is updated to `1` after the migration executes +/// - Reads/Writes from checking/settings the on-chain storage version are accounted for +pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< + 0, // The migration will only execute when the on-chain storage version is 0 + 1, // The on-chain storage version will be set to 1 after the migration is complete + MigrateToV1, + crate::pallet::Pallet, + ::DbWeight, +>; diff --git a/substrate/frame/core-fellowship/src/tests/integration.rs b/substrate/frame/core-fellowship/src/tests/integration.rs index d3bbac158056e7edbbf1e08b255d63450fa1c5c0..f3137316658576d91616428ee32d51b916189963 100644 --- a/substrate/frame/core-fellowship/src/tests/integration.rs +++ b/substrate/frame/core-fellowship/src/tests/integration.rs @@ -25,8 +25,9 @@ use frame_support::{ }; use frame_system::EnsureSignedBy; use pallet_ranked_collective::{EnsureRanked, Geometric, Rank, TallyOf, Votes}; -use sp_core::Get; +use sp_core::{ConstU32, Get}; use sp_runtime::{ + bounded_vec, traits::{Convert, ReduceBy, ReplaceWithDefault, TryMorphInto}, BuildStorage, DispatchError, }; @@ -78,6 +79,7 @@ impl Config for Test { type ApproveOrigin = TryMapSuccess, u64>, TryMorphInto>; type PromoteOrigin = TryMapSuccess, u64>, TryMorphInto>; type EvidenceSize = EvidenceSize; + type MaxRank = ConstU32<9>; } pub struct TestPolls; @@ -163,11 +165,13 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| { + assert_ok!(Club::add_member(RuntimeOrigin::root(), 100)); + promote_n_times(100, 9); let params = ParamsType { - active_salary: [10, 20, 30, 40, 50, 60, 70, 80, 90], - passive_salary: [1, 2, 3, 4, 5, 6, 7, 8, 9], - demotion_period: [2, 4, 6, 8, 10, 12, 14, 16, 18], - min_promotion_period: [3, 6, 9, 12, 15, 18, 21, 24, 27], + active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90], + passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9], + demotion_period: bounded_vec![2, 4, 6, 8, 10, 12, 14, 16, 18], + min_promotion_period: bounded_vec![3, 6, 9, 12, 15, 18, 21, 24, 27], offboard_timeout: 1, }; assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params))); diff --git a/substrate/frame/core-fellowship/src/tests/unit.rs b/substrate/frame/core-fellowship/src/tests/unit.rs index 669517d61a4a963d3e021191ed3f9e561021b908..9245e5159a901d47842339836ae3f0767a2b1b1f 100644 --- a/substrate/frame/core-fellowship/src/tests/unit.rs +++ b/substrate/frame/core-fellowship/src/tests/unit.rs @@ -27,7 +27,7 @@ use frame_support::{ traits::{tokens::GetSalary, ConstU32, IsInVec, TryMapSuccess}, }; use frame_system::EnsureSignedBy; -use sp_runtime::{traits::TryMorphInto, BuildStorage, DispatchError, DispatchResult}; +use sp_runtime::{bounded_vec, traits::TryMorphInto, BuildStorage, DispatchError, DispatchResult}; use crate as pallet_core_fellowship; use crate::*; @@ -116,19 +116,22 @@ impl Config for Test { type ApproveOrigin = TryMapSuccess, u64>, TryMorphInto>; type PromoteOrigin = TryMapSuccess, u64>, TryMorphInto>; type EvidenceSize = ConstU32<1024>; + type MaxRank = ConstU32<9>; } pub fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| { + set_rank(100, 9); let params = ParamsType { - active_salary: [10, 20, 30, 40, 50, 60, 70, 80, 90], - passive_salary: [1, 2, 3, 4, 5, 6, 7, 8, 9], - demotion_period: [2, 4, 6, 8, 10, 12, 14, 16, 18], - min_promotion_period: [3, 6, 9, 12, 15, 18, 21, 24, 27], + active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90], + passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9], + demotion_period: bounded_vec![2, 4, 6, 8, 10, 12, 14, 16, 18], + min_promotion_period: bounded_vec![3, 6, 9, 12, 15, 18, 21, 24, 27], offboard_timeout: 1, }; + assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params))); System::set_block_number(1); }); @@ -170,10 +173,10 @@ fn basic_stuff() { fn set_params_works() { new_test_ext().execute_with(|| { let params = ParamsType { - active_salary: [10, 20, 30, 40, 50, 60, 70, 80, 90], - passive_salary: [1, 2, 3, 4, 5, 6, 7, 8, 9], - demotion_period: [1, 2, 3, 4, 5, 6, 7, 8, 9], - min_promotion_period: [1, 2, 3, 4, 5, 10, 15, 20, 30], + active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90], + passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9], + demotion_period: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9], + min_promotion_period: bounded_vec![1, 2, 3, 4, 5, 10, 15, 20, 30], offboard_timeout: 1, }; assert_noop!( @@ -284,10 +287,10 @@ fn offboard_works() { fn infinite_demotion_period_works() { new_test_ext().execute_with(|| { let params = ParamsType { - active_salary: [10; 9], - passive_salary: [10; 9], - min_promotion_period: [10; 9], - demotion_period: [0; 9], + active_salary: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10], + passive_salary: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10], + min_promotion_period: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10], + demotion_period: bounded_vec![0, 0, 0, 0, 0, 0, 0, 0, 0], offboard_timeout: 0, }; assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params))); diff --git a/substrate/frame/core-fellowship/src/weights.rs b/substrate/frame/core-fellowship/src/weights.rs index 1e42335067a4a802942753940b2f5d6bbc5aef4f..8fad6f585c1129e9a6c4160ed396cea28158e990 100644 --- a/substrate/frame/core-fellowship/src/weights.rs +++ b/substrate/frame/core-fellowship/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_core_fellowship` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-04-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_core_fellowship -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/core-fellowship/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_core_fellowship +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/core-fellowship/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -67,13 +65,13 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// Storage: `CoreFellowship::Params` (r:0 w:1) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_836_000 picoseconds. - Weight::from_parts(7_057_000, 0) + // Minimum execution time: 7_633_000 picoseconds. + Weight::from_parts(8_018_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `CoreFellowship::Member` (r:1 w:1) @@ -81,7 +79,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `RankedCollective::Members` (r:1 w:1) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) @@ -92,10 +90,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `17274` + // Measured: `17278` // Estimated: `19894` - // Minimum execution time: 55_535_000 picoseconds. - Weight::from_parts(57_104_000, 19894) + // Minimum execution time: 57_597_000 picoseconds. + Weight::from_parts(58_825_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -104,7 +102,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `RankedCollective::Members` (r:1 w:1) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) @@ -115,10 +113,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `17384` + // Measured: `17388` // Estimated: `19894` - // Minimum execution time: 59_111_000 picoseconds. - Weight::from_parts(61_394_000, 19894) + // Minimum execution time: 61_387_000 picoseconds. + Weight::from_parts(63_408_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -130,8 +128,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 16_166_000 picoseconds. - Weight::from_parts(16_773_000, 3514) + // Minimum execution time: 15_941_000 picoseconds. + Weight::from_parts(16_547_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,8 +147,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 25_508_000 picoseconds. - Weight::from_parts(25_952_000, 3514) + // Minimum execution time: 24_963_000 picoseconds. + Weight::from_parts(25_873_000, 3514) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -159,7 +157,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `CoreFellowship::Member` (r:1 w:1) /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) @@ -170,10 +168,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn promote() -> Weight { // Proof Size summary in bytes: - // Measured: `17252` + // Measured: `16931` // Estimated: `19894` - // Minimum execution time: 51_102_000 picoseconds. - Weight::from_parts(53_302_000, 19894) + // Minimum execution time: 55_062_000 picoseconds. + Weight::from_parts(58_422_000, 19894) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -187,8 +185,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3514` - // Minimum execution time: 16_035_000 picoseconds. - Weight::from_parts(16_529_000, 3514) + // Minimum execution time: 15_901_000 picoseconds. + Weight::from_parts(16_746_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -200,8 +198,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 14_966_000 picoseconds. - Weight::from_parts(15_340_000, 3514) + // Minimum execution time: 14_768_000 picoseconds. + Weight::from_parts(15_421_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -215,8 +213,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 35_137_000 picoseconds. - Weight::from_parts(36_285_000, 19894) + // Minimum execution time: 36_925_000 picoseconds. + Weight::from_parts(38_330_000, 19894) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -228,8 +226,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 24_307_000 picoseconds. - Weight::from_parts(25_426_000, 19894) + // Minimum execution time: 25_210_000 picoseconds. + Weight::from_parts(26_247_000, 19894) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -238,13 +236,13 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests. impl WeightInfo for () { /// Storage: `CoreFellowship::Params` (r:0 w:1) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_836_000 picoseconds. - Weight::from_parts(7_057_000, 0) + // Minimum execution time: 7_633_000 picoseconds. + Weight::from_parts(8_018_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `CoreFellowship::Member` (r:1 w:1) @@ -252,7 +250,7 @@ impl WeightInfo for () { /// Storage: `RankedCollective::Members` (r:1 w:1) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) @@ -263,10 +261,10 @@ impl WeightInfo for () { /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `17274` + // Measured: `17278` // Estimated: `19894` - // Minimum execution time: 55_535_000 picoseconds. - Weight::from_parts(57_104_000, 19894) + // Minimum execution time: 57_597_000 picoseconds. + Weight::from_parts(58_825_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -275,7 +273,7 @@ impl WeightInfo for () { /// Storage: `RankedCollective::Members` (r:1 w:1) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) @@ -286,10 +284,10 @@ impl WeightInfo for () { /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `17384` + // Measured: `17388` // Estimated: `19894` - // Minimum execution time: 59_111_000 picoseconds. - Weight::from_parts(61_394_000, 19894) + // Minimum execution time: 61_387_000 picoseconds. + Weight::from_parts(63_408_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -301,8 +299,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 16_166_000 picoseconds. - Weight::from_parts(16_773_000, 3514) + // Minimum execution time: 15_941_000 picoseconds. + Weight::from_parts(16_547_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -320,8 +318,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 25_508_000 picoseconds. - Weight::from_parts(25_952_000, 3514) + // Minimum execution time: 24_963_000 picoseconds. + Weight::from_parts(25_873_000, 3514) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -330,7 +328,7 @@ impl WeightInfo for () { /// Storage: `CoreFellowship::Member` (r:1 w:1) /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:1 w:1) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) @@ -341,10 +339,10 @@ impl WeightInfo for () { /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn promote() -> Weight { // Proof Size summary in bytes: - // Measured: `17252` + // Measured: `16931` // Estimated: `19894` - // Minimum execution time: 51_102_000 picoseconds. - Weight::from_parts(53_302_000, 19894) + // Minimum execution time: 55_062_000 picoseconds. + Weight::from_parts(58_422_000, 19894) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -358,8 +356,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3514` - // Minimum execution time: 16_035_000 picoseconds. - Weight::from_parts(16_529_000, 3514) + // Minimum execution time: 15_901_000 picoseconds. + Weight::from_parts(16_746_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -371,8 +369,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 14_966_000 picoseconds. - Weight::from_parts(15_340_000, 3514) + // Minimum execution time: 14_768_000 picoseconds. + Weight::from_parts(15_421_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -386,8 +384,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 35_137_000 picoseconds. - Weight::from_parts(36_285_000, 19894) + // Minimum execution time: 36_925_000 picoseconds. + Weight::from_parts(38_330_000, 19894) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -399,8 +397,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 24_307_000 picoseconds. - Weight::from_parts(25_426_000, 19894) + // Minimum execution time: 25_210_000 picoseconds. + Weight::from_parts(26_247_000, 19894) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/delegated-staking/Cargo.toml b/substrate/frame/delegated-staking/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..3b122dc2e26c3c9d0f56f07427b037bd1cd388c0 --- /dev/null +++ b/substrate/frame/delegated-staking/Cargo.toml @@ -0,0 +1,73 @@ +[package] +name = "pallet-delegated-staking" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +homepage = "https://substrate.io" +repository.workspace = true +description = "FRAME delegated staking pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } +frame-support = { path = "../support", default-features = false } +frame-system = { path = "../system", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +sp-std = { path = "../../primitives/std", default-features = false } +sp-runtime = { path = "../../primitives/runtime", default-features = false } +sp-staking = { path = "../../primitives/staking", default-features = false } + +[dev-dependencies] +sp-core = { path = "../../primitives/core" } +sp-io = { path = "../../primitives/io" } +substrate-test-utils = { path = "../../test-utils" } +sp-tracing = { path = "../../primitives/tracing" } +pallet-staking = { path = "../staking" } +pallet-nomination-pools = { path = "../nomination-pools" } +pallet-balances = { path = "../balances" } +pallet-timestamp = { path = "../timestamp" } +pallet-staking-reward-curve = { path = "../staking/reward-curve" } +frame-election-provider-support = { path = "../election-provider-support", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-election-provider-support/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-nomination-pools/std", + "pallet-staking/std", + "pallet-timestamp/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-election-provider-support/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-nomination-pools/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", +] +try-runtime = [ + "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-nomination-pools/try-runtime", + "pallet-staking/try-runtime", + "pallet-timestamp/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/delegated-staking/src/impls.rs b/substrate/frame/delegated-staking/src/impls.rs new file mode 100644 index 0000000000000000000000000000000000000000..032f6120642852f04867861c053a97bddc942ac9 --- /dev/null +++ b/substrate/frame/delegated-staking/src/impls.rs @@ -0,0 +1,166 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Implementations of public traits, namely [`DelegationInterface`] and [`OnStakingUpdate`]. + +use super::*; +use sp_staking::{DelegationInterface, DelegationMigrator, OnStakingUpdate}; + +impl DelegationInterface for Pallet { + type Balance = BalanceOf; + type AccountId = T::AccountId; + + /// Effective balance of the `Agent` account. + fn agent_balance(who: &Self::AccountId) -> Self::Balance { + Agent::::get(who) + .map(|agent| agent.ledger.effective_balance()) + .unwrap_or_default() + } + + fn delegator_balance(delegator: &Self::AccountId) -> Self::Balance { + Delegation::::get(delegator).map(|d| d.amount).unwrap_or_default() + } + + /// Delegate funds to an `Agent`. + fn delegate( + who: &Self::AccountId, + agent: &Self::AccountId, + reward_account: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult { + Pallet::::register_agent( + RawOrigin::Signed(agent.clone()).into(), + reward_account.clone(), + )?; + + // Delegate the funds from who to the `Agent` account. + Pallet::::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount) + } + + /// Add more delegation to the `Agent` account. + fn delegate_extra( + who: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult { + Pallet::::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount) + } + + /// Withdraw delegation of `delegator` to `Agent`. + /// + /// If there are funds in `Agent` account that can be withdrawn, then those funds would be + /// unlocked/released in the delegator's account. + fn withdraw_delegation( + delegator: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + num_slashing_spans: u32, + ) -> DispatchResult { + Pallet::::release_delegation( + RawOrigin::Signed(agent.clone()).into(), + delegator.clone(), + amount, + num_slashing_spans, + ) + } + + /// Returns true if the `Agent` have any slash pending to be applied. + fn has_pending_slash(agent: &Self::AccountId) -> bool { + Agent::::get(agent) + .map(|d| !d.ledger.pending_slash.is_zero()) + .unwrap_or(false) + } + + fn delegator_slash( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + maybe_reporter: Option, + ) -> sp_runtime::DispatchResult { + Pallet::::do_slash(agent.clone(), delegator.clone(), value, maybe_reporter) + } +} + +impl DelegationMigrator for Pallet { + type Balance = BalanceOf; + type AccountId = T::AccountId; + + fn migrate_nominator_to_agent( + agent: &Self::AccountId, + reward_account: &Self::AccountId, + ) -> DispatchResult { + Pallet::::migrate_to_agent( + RawOrigin::Signed(agent.clone()).into(), + reward_account.clone(), + ) + } + fn migrate_delegation( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + ) -> DispatchResult { + Pallet::::migrate_delegation( + RawOrigin::Signed(agent.clone()).into(), + delegator.clone(), + value, + ) + } + + /// Only used for testing. + #[cfg(feature = "runtime-benchmarks")] + fn drop_agent(agent: &T::AccountId) { + >::remove(agent); + >::iter() + .filter(|(_, delegation)| delegation.agent == *agent) + .for_each(|(delegator, _)| { + let _ = T::Currency::release_all( + &HoldReason::StakingDelegation.into(), + &delegator, + Precision::BestEffort, + ); + >::remove(&delegator); + }); + + T::CoreStaking::migrate_to_direct_staker(agent); + } +} + +impl OnStakingUpdate> for Pallet { + fn on_slash( + who: &T::AccountId, + _slashed_active: BalanceOf, + _slashed_unlocking: &sp_std::collections::btree_map::BTreeMap>, + slashed_total: BalanceOf, + ) { + >::mutate(who, |maybe_register| match maybe_register { + // if existing agent, register the slashed amount as pending slash. + Some(register) => register.pending_slash.saturating_accrue(slashed_total), + None => { + // nothing to do + }, + }); + } + + fn on_withdraw(stash: &T::AccountId, amount: BalanceOf) { + // if there is a withdraw to the agent, then add it to the unclaimed withdrawals. + let _ = Agent::::get(stash) + // can't do anything if there is an overflow error. Just raise a defensive error. + .and_then(|agent| agent.add_unclaimed_withdraw(amount).defensive()) + .map(|agent| agent.save()); + } +} diff --git a/substrate/frame/delegated-staking/src/lib.rs b/substrate/frame/delegated-staking/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8581a4a981fe46af53d1b0708160bc6c69a95ec9 --- /dev/null +++ b/substrate/frame/delegated-staking/src/lib.rs @@ -0,0 +1,832 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Delegated Staking Pallet +//! +//! This pallet implements [`sp_staking::DelegationInterface`] that provides delegation +//! functionality to `delegators` and `agents`. It is designed to be used in conjunction with +//! [`StakingInterface`] and relies on [`Config::CoreStaking`] to provide primitive staking +//! functions. +//! +//! Currently, it does not expose any dispatchable calls but is written with a vision to expose them +//! in the future such that it can be utilised by any external account, off-chain entity or xcm +//! `MultiLocation` such as a parachain or a smart contract. +//! +//! ## Key Terminologies +//! - **Agent**: An account who accepts delegations from other accounts and act as an agent on their +//! behalf for staking these delegated funds. Also, sometimes referred as `Delegatee`. +//! - **Delegator**: An account who delegates their funds to an `agent` and authorises them to use +//! it for staking. +//! - **AgentLedger**: A data structure that holds important information about the `agent` such as +//! total delegations they have received, any slashes posted to them, etc. +//! - **Delegation**: A data structure that stores the amount of funds delegated to an `agent` by a +//! `delegator`. +//! +//! ## Goals +//! +//! Direct nomination on the Staking pallet does not scale well. Nominations pools were created to +//! address this by pooling delegator funds into one account and then staking it. This though had +//! a very critical limitation that the funds were moved from delegator account to pool account +//! and hence the delegator lost control over their funds for using it for other purposes such as +//! governance. This pallet aims to solve this by extending the staking pallet to support a new +//! primitive function: delegation of funds to an `agent` with the intent of staking. The agent can +//! then stake the delegated funds to [`Config::CoreStaking`] on behalf of the delegators. +//! +//! ### Withdrawal Management +//! Agent unbonding does not regulate ordering of consequent withdrawal for delegators. This is upto +//! the consumer of this pallet to implement in what order unbondable funds from +//! [`Config::CoreStaking`] can be withdrawn by the delegators. +//! +//! ### Reward and Slashing +//! This pallet does not enforce any specific strategy for how rewards or slashes are applied. It +//! is upto the `agent` account to decide how to apply the rewards and slashes. +//! +//! This importantly allows clients of this pallet to build their own strategies for reward/slashes. +//! For example, an `agent` account can choose to first slash the reward pot before slashing the +//! delegators. Or part of the reward can go to an insurance fund that can be used to cover any +//! potential future slashes. The goal is to eventually allow foreign MultiLocations +//! (smart contracts or pallets on another chain) to build their own pooled staking solutions +//! similar to `NominationPools`. + +//! ## Core functions +//! +//! - Allow an account to receive delegations. See [`Pallet::register_agent`]. +//! - Delegate funds to an `agent` account. See [`Pallet::delegate_to_agent`]. +//! - Release delegated funds from an `agent` account to the `delegator`. See +//! [`Pallet::release_delegation`]. +//! - Migrate a `Nominator` account to an `agent` account. See [`Pallet::migrate_to_agent`]. +//! Explained in more detail in the `Migration` section. +//! - Migrate unclaimed delegated funds from `agent` to delegator. When a nominator migrates to an +//! agent, the funds are held in a proxy account. This function allows the delegator to claim their +//! share of the funds from the proxy account. See [`Pallet::migrate_delegation`]. +//! +//! ## Lazy Slashing +//! One of the reasons why direct nominators on staking pallet cannot scale well is because all +//! nominators are slashed at the same time. This is expensive and needs to be bounded operation. +//! +//! This pallet implements a lazy slashing mechanism. Any slashes to the `agent` are posted in its +//! `AgentLedger` as a pending slash. Since the actual amount is held in the multiple +//! `delegator` accounts, this pallet has no way to know how to apply slash. It is the `agent`'s +//! responsibility to apply slashes for each delegator, one at a time. Staking pallet ensures the +//! pending slash never exceeds staked amount and would freeze further withdraws until all pending +//! slashes are cleared. +//! +//! The user of this pallet can apply slash using +//! [DelegationInterface::delegator_slash](sp_staking::DelegationInterface::delegator_slash). +//! +//! ## Migration from Nominator to Agent +//! More details [here](https://hackmd.io/@ak0n/454-np-governance). +//! +//! ## Nomination Pool vs Delegation Staking +//! This pallet is not a replacement for Nomination Pool but adds a new primitive in addition to +//! staking pallet that can be used by Nomination Pool to support delegation based staking. It can +//! be thought of as an extension to the Staking Pallet in relation to Nomination Pools. +//! Technically, these changes could be made in one of those pallets as well but that would have +//! meant significant refactoring and high chances of introducing a regression. With this approach, +//! we can keep the existing pallets with minimal changes and introduce a new pallet that can be +//! optionally used by Nomination Pool. The vision is to build this in a configurable way such that +//! runtime can choose whether to use this pallet or not. +//! +//! With that said, following is the main difference between +//! #### Nomination Pool without delegation support +//! 1) transfer fund from delegator to pool account, and +//! 2) stake from pool account as a direct nominator. +//! +//! #### Nomination Pool with delegation support +//! 1) delegate fund from delegator to pool account, and +//! 2) stake from pool account as an `Agent` account on the staking pallet. +//! +//! The difference being, in the second approach, the delegated funds will be locked in-place in +//! user's account enabling them to participate in use cases that allows use of `held` funds such +//! as participation in governance voting. +//! +//! Nomination pool still does all the heavy lifting around pool administration, reward +//! distribution, lazy slashing and as such, is not meant to be replaced with this pallet. +//! +//! ## Limitations +//! - Rewards can not be auto-compounded. +//! - Slashes are lazy and hence there could be a period of time when an account can use funds for +//! operations such as voting in governance even though they should be slashed. + +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(rustdoc::broken_intra_doc_links)] + +mod impls; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; +mod types; + +pub use pallet::*; + +use types::*; + +use frame_support::{ + pallet_prelude::*, + traits::{ + fungible::{ + hold::{ + Balanced as FunHoldBalanced, Inspect as FunHoldInspect, Mutate as FunHoldMutate, + }, + Balanced, Inspect as FunInspect, Mutate as FunMutate, + }, + tokens::{fungible::Credit, Fortitude, Precision, Preservation}, + Defensive, DefensiveOption, Imbalance, OnUnbalanced, + }, +}; +use sp_runtime::{ + traits::{AccountIdConversion, CheckedAdd, CheckedSub, Zero}, + ArithmeticError, DispatchResult, Perbill, RuntimeDebug, Saturating, +}; +use sp_staking::{EraIndex, StakingInterface, StakingUnchecked}; +use sp_std::{convert::TryInto, prelude::*}; + +pub type BalanceOf = + <::Currency as FunInspect<::AccountId>>::Balance; + +use frame_system::{ensure_signed, pallet_prelude::*, RawOrigin}; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + /// The in-code storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Injected identifier for the pallet. + #[pallet::constant] + type PalletId: Get; + + /// Currency type. + type Currency: FunHoldMutate + + FunMutate + + FunHoldBalanced; + + /// Handler for the unbalanced reduction when slashing a delegator. + type OnSlash: OnUnbalanced>; + + /// Fraction of the slash that is rewarded to the caller of pending slash to the agent. + #[pallet::constant] + type SlashRewardFraction: Get; + + /// Overarching hold reason. + type RuntimeHoldReason: From; + + /// Core staking implementation. + type CoreStaking: StakingUnchecked, AccountId = Self::AccountId>; + } + + #[pallet::error] + pub enum Error { + /// The account cannot perform this operation. + NotAllowed, + /// An existing staker cannot perform this action. + AlreadyStaking, + /// Reward Destination cannot be same as `Agent` account. + InvalidRewardDestination, + /// Delegation conditions are not met. + /// + /// Possible issues are + /// 1) Cannot delegate to self, + /// 2) Cannot delegate to multiple delegates. + InvalidDelegation, + /// The account does not have enough funds to perform the operation. + NotEnoughFunds, + /// Not an existing `Agent` account. + NotAgent, + /// Not a Delegator account. + NotDelegator, + /// Some corruption in internal state. + BadState, + /// Unapplied pending slash restricts operation on `Agent`. + UnappliedSlash, + /// `Agent` has no pending slash to be applied. + NothingToSlash, + /// Failed to withdraw amount from Core Staking. + WithdrawFailed, + /// Operation not supported by this pallet. + NotSupported, + } + + /// A reason for placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + /// Funds held for stake delegation to another account. + #[codec(index = 0)] + StakingDelegation, + } + + #[pallet::event] + #[pallet::generate_deposit(pub (super) fn deposit_event)] + pub enum Event { + /// Funds delegated by a delegator. + Delegated { agent: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + /// Funds released to a delegator. + Released { agent: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + /// Funds slashed from a delegator. + Slashed { agent: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + /// Unclaimed delegation funds migrated to delegator. + MigratedDelegation { agent: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + } + + /// Map of Delegators to their `Delegation`. + /// + /// Implementation note: We are not using a double map with `delegator` and `agent` account + /// as keys since we want to restrict delegators to delegate only to one account at a time. + #[pallet::storage] + pub(crate) type Delegators = + CountedStorageMap<_, Twox64Concat, T::AccountId, Delegation, OptionQuery>; + + /// Map of `Agent` to their `Ledger`. + #[pallet::storage] + pub(crate) type Agents = + CountedStorageMap<_, Twox64Concat, T::AccountId, AgentLedger, OptionQuery>; + + // This pallet is not currently written with the intention of exposing any calls. But the + // functions defined in the following impl block should act as a good reference for how the + // exposed calls would look like when exposed. + impl Pallet { + /// Register an account to become a stake `Agent`. Sometimes also called a `Delegatee`. + /// + /// Delegators can authorize `Agent`s to stake on their behalf by delegating their funds to + /// them. The `Agent` can then use the delegated funds to stake to [`Config::CoreStaking`]. + /// + /// An account that is directly staked to [`Config::CoreStaking`] cannot become an `Agent`. + /// However, they can migrate to become an agent using [`Self::migrate_to_agent`]. + /// + /// Implementation note: This function allows any account to become an agent. It is + /// important though that accounts that call [`StakingUnchecked::virtual_bond`] are keyless + /// accounts. This is not a problem for now since this is only used by other pallets in the + /// runtime which use keyless account as agents. If we later want to expose this as a + /// dispatchable call, we should derive a sub-account from the caller and use that as the + /// agent account. + pub fn register_agent( + origin: OriginFor, + reward_account: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + // Existing `agent` cannot register again and a delegator cannot become an `agent`. + ensure!(!Self::is_agent(&who) && !Self::is_delegator(&who), Error::::NotAllowed); + + // They cannot be already a direct staker in the staking pallet. + ensure!(!Self::is_direct_staker(&who), Error::::AlreadyStaking); + + // Reward account cannot be same as `agent` account. + ensure!(reward_account != who, Error::::InvalidRewardDestination); + + Self::do_register_agent(&who, &reward_account); + Ok(()) + } + + /// Migrate from a `Nominator` account to `Agent` account. + /// + /// The origin needs to + /// - be a `Nominator` with [`Config::CoreStaking`], + /// - not already an `Agent`, + /// + /// This function will create a proxy account to the agent called `proxy_delegator` and + /// transfer the directly staked amount by the agent to it. The `proxy_delegator` delegates + /// the funds to the origin making origin an `Agent` account. The real `delegator` + /// accounts of the origin can later migrate their funds using [Self::migrate_delegation] to + /// claim back their share of delegated funds from `proxy_delegator` to self. + /// + /// Any free fund in the agent's account will be marked as unclaimed withdrawal. + pub fn migrate_to_agent( + origin: OriginFor, + reward_account: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + // ensure who is a staker in `CoreStaking` but not already an agent or a delegator. + ensure!( + Self::is_direct_staker(&who) && !Self::is_agent(&who) && !Self::is_delegator(&who), + Error::::NotAllowed + ); + + // Reward account cannot be same as `agent` account. + ensure!(reward_account != who, Error::::InvalidRewardDestination); + + Self::do_migrate_to_agent(&who, &reward_account) + } + + /// Release previously delegated funds by delegator to origin. + /// + /// Only agents can call this. + /// + /// Tries to withdraw unbonded funds from `CoreStaking` if needed and release amount to + /// `delegator`. + pub fn release_delegation( + origin: OriginFor, + delegator: T::AccountId, + amount: BalanceOf, + num_slashing_spans: u32, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_release(&who, &delegator, amount, num_slashing_spans) + } + + /// Migrate delegated funds that are held in `proxy_delegator` to the claiming `delegator`'s + /// account. If successful, the specified funds will be moved and delegated from `delegator` + /// account to the agent. + /// + /// This can be called by `agent` accounts that were previously a direct `Nominator` with + /// [`Config::CoreStaking`] and has some remaining unclaimed delegations. + /// + /// Internally, it moves some delegations from `proxy_delegator` account to `delegator` + /// account and reapplying the holds. + pub fn migrate_delegation( + origin: OriginFor, + delegator: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let agent = ensure_signed(origin)?; + + // Ensure they have minimum delegation. + ensure!(amount >= T::Currency::minimum_balance(), Error::::NotEnoughFunds); + + // Ensure delegator is sane. + ensure!(!Self::is_agent(&delegator), Error::::NotAllowed); + ensure!(!Self::is_delegator(&delegator), Error::::NotAllowed); + ensure!(!Self::is_direct_staker(&delegator), Error::::AlreadyStaking); + + // ensure agent is sane. + ensure!(Self::is_agent(&agent), Error::::NotAgent); + + // and has enough delegated balance to migrate. + let proxy_delegator = Self::generate_proxy_delegator(agent); + let balance_remaining = Self::held_balance_of(&proxy_delegator); + ensure!(balance_remaining >= amount, Error::::NotEnoughFunds); + + Self::do_migrate_delegation(&proxy_delegator, &delegator, amount) + } + + /// Delegate given `amount` of tokens to an `Agent` account. + /// + /// If `origin` is the first time delegator, we add them to state. If they are already + /// delegating, we increase the delegation. + /// + /// Conditions: + /// - Delegators cannot delegate to more than one agent. + /// - The `agent` account should already be registered as such. See + /// [`Self::register_agent`]. + pub fn delegate_to_agent( + origin: OriginFor, + agent: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let delegator = ensure_signed(origin)?; + + // ensure delegator is sane. + ensure!( + Delegation::::can_delegate(&delegator, &agent), + Error::::InvalidDelegation + ); + ensure!(!Self::is_direct_staker(&delegator), Error::::AlreadyStaking); + + // ensure agent is sane. + ensure!(Self::is_agent(&agent), Error::::NotAgent); + + // add to delegation. + Self::do_delegate(&delegator, &agent, amount)?; + + // bond the newly delegated amount to `CoreStaking`. + Self::do_bond(&agent, amount) + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + #[cfg(feature = "try-runtime")] + fn try_state(_n: BlockNumberFor) -> Result<(), sp_runtime::TryRuntimeError> { + Self::do_try_state() + } + } +} + +impl Pallet { + /// Derive an account from the migrating agent account where the unclaimed delegation funds + /// are held. + pub fn generate_proxy_delegator(agent: T::AccountId) -> T::AccountId { + Self::sub_account(AccountType::ProxyDelegator, agent) + } + + /// Derive a (keyless) pot account from the given agent account and account type. + pub(crate) fn sub_account(account_type: AccountType, agent: T::AccountId) -> T::AccountId { + T::PalletId::get().into_sub_account_truncating((account_type, agent.clone())) + } + + /// Held balance of a delegator. + pub(crate) fn held_balance_of(who: &T::AccountId) -> BalanceOf { + T::Currency::balance_on_hold(&HoldReason::StakingDelegation.into(), who) + } + + /// Returns true if who is registered as an `Agent`. + fn is_agent(who: &T::AccountId) -> bool { + >::contains_key(who) + } + + /// Returns true if who is delegating to an `Agent` account. + fn is_delegator(who: &T::AccountId) -> bool { + >::contains_key(who) + } + + /// Returns true if who is already staking on [`Config::CoreStaking`]. + fn is_direct_staker(who: &T::AccountId) -> bool { + T::CoreStaking::status(who).is_ok() + } + + /// Registers a new agent in the system. + fn do_register_agent(who: &T::AccountId, reward_account: &T::AccountId) { + AgentLedger::::new(reward_account).update(who); + + // Agent does not hold balance of its own but this pallet will provide for this to exist. + // This is expected to be a keyless account and not created by any user directly so safe. + // TODO: Someday if we allow anyone to be an agent, we should take a deposit for + // being a delegator. + frame_system::Pallet::::inc_providers(who); + } + + /// Migrate existing staker account `who` to an `Agent` account. + fn do_migrate_to_agent(who: &T::AccountId, reward_account: &T::AccountId) -> DispatchResult { + Self::do_register_agent(who, reward_account); + + // We create a proxy delegator that will keep all the delegation funds until funds are + // transferred to actual delegator. + let proxy_delegator = Self::generate_proxy_delegator(who.clone()); + + // Keep proxy delegator alive until all funds are migrated. + frame_system::Pallet::::inc_providers(&proxy_delegator); + + // Get current stake + let stake = T::CoreStaking::stake(who)?; + + // release funds from core staking. + T::CoreStaking::migrate_to_virtual_staker(who); + + // transfer just released staked amount plus any free amount. + let amount_to_transfer = + T::Currency::reducible_balance(who, Preservation::Expendable, Fortitude::Polite); + + // This should never fail but if it does, it indicates bad state and we abort. + T::Currency::transfer(who, &proxy_delegator, amount_to_transfer, Preservation::Expendable)?; + + T::CoreStaking::update_payee(who, reward_account)?; + // delegate all transferred funds back to agent. + Self::do_delegate(&proxy_delegator, who, amount_to_transfer)?; + + // if the transferred/delegated amount was greater than the stake, mark the extra as + // unclaimed withdrawal. + let unclaimed_withdraws = amount_to_transfer + .checked_sub(&stake.total) + .defensive_ok_or(ArithmeticError::Underflow)?; + + if !unclaimed_withdraws.is_zero() { + let mut ledger = AgentLedger::::get(who).ok_or(Error::::NotAgent)?; + ledger.unclaimed_withdrawals = ledger + .unclaimed_withdrawals + .checked_add(&unclaimed_withdraws) + .defensive_ok_or(ArithmeticError::Overflow)?; + ledger.update(who); + } + + Ok(()) + } + + /// Bond `amount` to `agent_acc` in [`Config::CoreStaking`]. + fn do_bond(agent_acc: &T::AccountId, amount: BalanceOf) -> DispatchResult { + let agent = Agent::::get(agent_acc)?; + + let available_to_bond = agent.available_to_bond(); + defensive_assert!(amount == available_to_bond, "not expected value to bond"); + + if agent.is_bonded() { + T::CoreStaking::bond_extra(&agent.key, amount) + } else { + T::CoreStaking::virtual_bond(&agent.key, amount, agent.reward_account()) + } + } + + /// Delegate `amount` from `delegator` to `agent`. + fn do_delegate( + delegator: &T::AccountId, + agent: &T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let mut ledger = AgentLedger::::get(agent).ok_or(Error::::NotAgent)?; + // try to hold the funds. + T::Currency::hold(&HoldReason::StakingDelegation.into(), delegator, amount)?; + + let new_delegation_amount = + if let Some(existing_delegation) = Delegation::::get(delegator) { + ensure!(&existing_delegation.agent == agent, Error::::InvalidDelegation); + existing_delegation + .amount + .checked_add(&amount) + .ok_or(ArithmeticError::Overflow)? + } else { + amount + }; + + Delegation::::new(agent, new_delegation_amount).update_or_kill(delegator); + ledger.total_delegated = + ledger.total_delegated.checked_add(&amount).ok_or(ArithmeticError::Overflow)?; + ledger.update(agent); + + Self::deposit_event(Event::::Delegated { + agent: agent.clone(), + delegator: delegator.clone(), + amount, + }); + + Ok(()) + } + + /// Release `amount` of delegated funds from `agent` to `delegator`. + fn do_release( + who: &T::AccountId, + delegator: &T::AccountId, + amount: BalanceOf, + num_slashing_spans: u32, + ) -> DispatchResult { + let mut agent = Agent::::get(who)?; + let mut delegation = Delegation::::get(delegator).ok_or(Error::::NotDelegator)?; + + // make sure delegation to be released is sound. + ensure!(&delegation.agent == who, Error::::NotAgent); + ensure!(delegation.amount >= amount, Error::::NotEnoughFunds); + + // if we do not already have enough funds to be claimed, try withdraw some more. + // keep track if we killed the staker in the process. + let stash_killed = if agent.ledger.unclaimed_withdrawals < amount { + // withdraw account. + let killed = T::CoreStaking::withdraw_unbonded(who.clone(), num_slashing_spans) + .map_err(|_| Error::::WithdrawFailed)?; + // reload agent from storage since withdrawal might have changed the state. + agent = agent.refresh()?; + Some(killed) + } else { + None + }; + + // if we still do not have enough funds to release, abort. + ensure!(agent.ledger.unclaimed_withdrawals >= amount, Error::::NotEnoughFunds); + + // Claim withdraw from agent. Kill agent if no delegation left. + // TODO: Ideally if there is a register, there should be an unregister that should + // clean up the agent. Can be improved in future. + if agent.remove_unclaimed_withdraw(amount)?.update_or_kill()? { + match stash_killed { + Some(killed) => { + // this implies we did a `CoreStaking::withdraw` before release. Ensure + // we killed the staker as well. + ensure!(killed, Error::::BadState); + }, + None => { + // We did not do a `CoreStaking::withdraw` before release. Ensure staker is + // already killed in `CoreStaking`. + ensure!(T::CoreStaking::status(who).is_err(), Error::::BadState); + }, + } + + // Remove provider reference for `who`. + let _ = frame_system::Pallet::::dec_providers(who).defensive(); + } + + // book keep delegation + delegation.amount = delegation + .amount + .checked_sub(&amount) + .defensive_ok_or(ArithmeticError::Overflow)?; + + // remove delegator if nothing delegated anymore + delegation.update_or_kill(delegator); + + let released = T::Currency::release( + &HoldReason::StakingDelegation.into(), + delegator, + amount, + Precision::BestEffort, + )?; + + defensive_assert!(released == amount, "hold should have been released fully"); + + Self::deposit_event(Event::::Released { + agent: who.clone(), + delegator: delegator.clone(), + amount, + }); + + Ok(()) + } + + /// Migrates delegation of `amount` from `source` account to `destination` account. + fn do_migrate_delegation( + source_delegator: &T::AccountId, + destination_delegator: &T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let mut source_delegation = + Delegators::::get(source_delegator).defensive_ok_or(Error::::BadState)?; + + // some checks that must have already been checked before. + ensure!(source_delegation.amount >= amount, Error::::NotEnoughFunds); + debug_assert!( + !Self::is_delegator(destination_delegator) && !Self::is_agent(destination_delegator) + ); + + let agent = source_delegation.agent.clone(); + // update delegations + Delegation::::new(&agent, amount).update_or_kill(destination_delegator); + + source_delegation.amount = source_delegation + .amount + .checked_sub(&amount) + .defensive_ok_or(Error::::BadState)?; + + source_delegation.update_or_kill(source_delegator); + + // release funds from source + let released = T::Currency::release( + &HoldReason::StakingDelegation.into(), + source_delegator, + amount, + Precision::BestEffort, + )?; + + defensive_assert!(released == amount, "hold should have been released fully"); + + // transfer the released amount to `destination_delegator`. + let post_balance = T::Currency::transfer( + source_delegator, + destination_delegator, + amount, + Preservation::Expendable, + ) + .map_err(|_| Error::::BadState)?; + + // if balance is zero, clear provider for source (proxy) delegator. + if post_balance == Zero::zero() { + let _ = frame_system::Pallet::::dec_providers(source_delegator).defensive(); + } + + // hold the funds again in the new delegator account. + T::Currency::hold(&HoldReason::StakingDelegation.into(), destination_delegator, amount)?; + + Self::deposit_event(Event::::MigratedDelegation { + agent, + delegator: destination_delegator.clone(), + amount, + }); + + Ok(()) + } + + /// Take slash `amount` from agent's `pending_slash`counter and apply it to `delegator` account. + pub fn do_slash( + agent_acc: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + maybe_reporter: Option, + ) -> DispatchResult { + let agent = Agent::::get(&agent_acc)?; + // ensure there is something to slash + ensure!(agent.ledger.pending_slash > Zero::zero(), Error::::NothingToSlash); + + let mut delegation = >::get(&delegator).ok_or(Error::::NotDelegator)?; + ensure!(delegation.agent == agent_acc, Error::::NotAgent); + ensure!(delegation.amount >= amount, Error::::NotEnoughFunds); + + // slash delegator + let (mut credit, missing) = + T::Currency::slash(&HoldReason::StakingDelegation.into(), &delegator, amount); + + defensive_assert!(missing.is_zero(), "slash should have been fully applied"); + + let actual_slash = credit.peek(); + + // remove the applied slashed amount from agent. + agent.remove_slash(actual_slash).save(); + delegation.amount = + delegation.amount.checked_sub(&actual_slash).ok_or(ArithmeticError::Overflow)?; + delegation.update_or_kill(&delegator); + + if let Some(reporter) = maybe_reporter { + let reward_payout: BalanceOf = T::SlashRewardFraction::get() * actual_slash; + let (reporter_reward, rest) = credit.split(reward_payout); + + // credit is the amount that we provide to `T::OnSlash`. + credit = rest; + + // reward reporter or drop it. + let _ = T::Currency::resolve(&reporter, reporter_reward); + } + + T::OnSlash::on_unbalanced(credit); + + Self::deposit_event(Event::::Slashed { agent: agent_acc, delegator, amount }); + + Ok(()) + } + + /// Total balance that is available for stake. Includes already staked amount. + #[cfg(test)] + pub(crate) fn stakeable_balance(who: &T::AccountId) -> BalanceOf { + Agent::::get(who) + .map(|agent| agent.ledger.stakeable_balance()) + .unwrap_or_default() + } +} + +#[cfg(any(test, feature = "try-runtime"))] +use sp_std::collections::btree_map::BTreeMap; + +#[cfg(any(test, feature = "try-runtime"))] +impl Pallet { + pub(crate) fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> { + // build map to avoid reading storage multiple times. + let delegation_map = Delegators::::iter().collect::>(); + let ledger_map = Agents::::iter().collect::>(); + + Self::check_delegates(ledger_map.clone())?; + Self::check_delegators(delegation_map, ledger_map)?; + + Ok(()) + } + + fn check_delegates( + ledgers: BTreeMap>, + ) -> Result<(), sp_runtime::TryRuntimeError> { + for (agent, ledger) in ledgers { + ensure!( + matches!( + T::CoreStaking::status(&agent).expect("agent should be bonded"), + sp_staking::StakerStatus::Nominator(_) | sp_staking::StakerStatus::Idle + ), + "agent should be bonded and not validator" + ); + + ensure!( + ledger.stakeable_balance() >= + T::CoreStaking::total_stake(&agent) + .expect("agent should exist as a nominator"), + "Cannot stake more than balance" + ); + } + + Ok(()) + } + + fn check_delegators( + delegations: BTreeMap>, + ledger: BTreeMap>, + ) -> Result<(), sp_runtime::TryRuntimeError> { + let mut delegation_aggregation = BTreeMap::>::new(); + for (delegator, delegation) in delegations.iter() { + ensure!( + T::CoreStaking::status(delegator).is_err(), + "delegator should not be directly staked" + ); + ensure!(!Self::is_agent(delegator), "delegator cannot be an agent"); + + delegation_aggregation + .entry(delegation.agent.clone()) + .and_modify(|e| *e += delegation.amount) + .or_insert(delegation.amount); + } + + for (agent, total_delegated) in delegation_aggregation { + ensure!(!Self::is_delegator(&agent), "agent cannot be delegator"); + + let ledger = ledger.get(&agent).expect("ledger should exist"); + ensure!( + ledger.total_delegated == total_delegated, + "ledger total delegated should match delegations" + ); + } + + Ok(()) + } +} diff --git a/substrate/frame/delegated-staking/src/mock.rs b/substrate/frame/delegated-staking/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..b9eaffb970e13ab69853dc946ee3431370d892c9 --- /dev/null +++ b/substrate/frame/delegated-staking/src/mock.rs @@ -0,0 +1,349 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{self as delegated_staking, types::Agent}; +use frame_support::{ + assert_ok, derive_impl, + pallet_prelude::*, + parameter_types, + traits::{ConstU64, Currency}, + PalletId, +}; + +use sp_runtime::{traits::IdentityLookup, BuildStorage, Perbill}; + +use frame_election_provider_support::{ + bounds::{ElectionBounds, ElectionBoundsBuilder}, + onchain, SequentialPhragmen, +}; +use frame_support::dispatch::RawOrigin; +use pallet_staking::{ActiveEra, ActiveEraInfo, CurrentEra}; +use sp_core::U256; +use sp_runtime::traits::Convert; +use sp_staking::{Stake, StakingInterface}; + +pub type T = Runtime; +type Block = frame_system::mocking::MockBlock; +pub type AccountId = u128; + +pub const GENESIS_VALIDATOR: AccountId = 1; +pub const GENESIS_NOMINATOR_ONE: AccountId = 101; +pub const GENESIS_NOMINATOR_TWO: AccountId = 102; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; + type Lookup = IdentityLookup; +} + +impl pallet_timestamp::Config for Runtime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<5>; + type WeightInfo = (); +} + +pub type Balance = u128; + +parameter_types! { + pub static ExistentialDeposit: Balance = 1; +} +impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<128>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<1>; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; +} + +pallet_staking_reward_curve::build! { + const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + +parameter_types! { + pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; + pub static BondingDuration: u32 = 3; + pub static ElectionsBoundsOnChain: ElectionBounds = ElectionBoundsBuilder::default().build(); +} +pub struct OnChainSeqPhragmen; +impl onchain::Config for OnChainSeqPhragmen { + type System = Runtime; + type Solver = SequentialPhragmen; + type DataProvider = Staking; + type WeightInfo = (); + type MaxWinners = ConstU32<100>; + type Bounds = ElectionsBoundsOnChain; +} + +impl pallet_staking::Config for Runtime { + type Currency = Balances; + type CurrencyBalance = Balance; + type UnixTime = pallet_timestamp::Pallet; + type CurrencyToVote = (); + type RewardRemainder = (); + type RuntimeEvent = RuntimeEvent; + type Slash = (); + type Reward = (); + type SessionsPerEra = ConstU32<1>; + type SlashDeferDuration = (); + type AdminOrigin = frame_system::EnsureRoot; + type BondingDuration = BondingDuration; + type SessionInterface = (); + type EraPayout = pallet_staking::ConvertCurve; + type NextNewSession = (); + type HistoryDepth = ConstU32<84>; + type MaxExposurePageSize = ConstU32<64>; + type ElectionProvider = onchain::OnChainExecution; + type GenesisElectionProvider = Self::ElectionProvider; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; + type TargetList = pallet_staking::UseValidatorsMap; + type NominationsQuota = pallet_staking::FixedNominationsQuota<16>; + type MaxUnlockingChunks = ConstU32<10>; + type MaxControllersInDeprecationBatch = ConstU32<100>; + type EventListeners = (Pools, DelegatedStaking); + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; + type WeightInfo = (); + type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; +} + +parameter_types! { + pub const DelegatedStakingPalletId: PalletId = PalletId(*b"py/dlstk"); + pub const SlashRewardFraction: Perbill = Perbill::from_percent(10); +} +impl delegated_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = DelegatedStakingPalletId; + type Currency = Balances; + type OnSlash = (); + type SlashRewardFraction = SlashRewardFraction; + type RuntimeHoldReason = RuntimeHoldReason; + type CoreStaking = Staking; +} + +pub struct BalanceToU256; +impl Convert for BalanceToU256 { + fn convert(n: Balance) -> U256 { + n.into() + } +} +pub struct U256ToBalance; +impl Convert for U256ToBalance { + fn convert(n: U256) -> Balance { + n.try_into().unwrap() + } +} + +parameter_types! { + pub static MaxUnbonding: u32 = 8; + pub const PoolsPalletId: PalletId = PalletId(*b"py/nopls"); +} +impl pallet_nomination_pools::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; + type RewardCounter = sp_runtime::FixedU128; + type BalanceToU256 = BalanceToU256; + type U256ToBalance = U256ToBalance; + type PostUnbondingPoolsWindow = ConstU32<2>; + type PalletId = PoolsPalletId; + type MaxMetadataLen = ConstU32<256>; + type MaxUnbonding = MaxUnbonding; + type MaxPointsToBalance = frame_support::traits::ConstU8<10>; + type StakeAdapter = + pallet_nomination_pools::adapter::DelegateStake; + type AdminOrigin = frame_system::EnsureRoot; +} + +frame_support::construct_runtime!( + pub enum Runtime { + System: frame_system, + Timestamp: pallet_timestamp, + Balances: pallet_balances, + Staking: pallet_staking, + Pools: pallet_nomination_pools, + DelegatedStaking: delegated_staking, + } +); + +#[derive(Default)] +pub struct ExtBuilder {} + +impl ExtBuilder { + fn build(self) -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let mut storage = + frame_system::GenesisConfig::::default().build_storage().unwrap(); + + let _ = pallet_balances::GenesisConfig:: { + balances: vec![ + (GENESIS_VALIDATOR, 10000), + (GENESIS_NOMINATOR_ONE, 1000), + (GENESIS_NOMINATOR_TWO, 2000), + ], + } + .assimilate_storage(&mut storage); + + let stakers = vec![ + ( + GENESIS_VALIDATOR, + GENESIS_VALIDATOR, + 1000, + sp_staking::StakerStatus::::Validator, + ), + ( + GENESIS_NOMINATOR_ONE, + GENESIS_NOMINATOR_ONE, + 100, + sp_staking::StakerStatus::::Nominator(vec![1]), + ), + ( + GENESIS_NOMINATOR_TWO, + GENESIS_NOMINATOR_TWO, + 200, + sp_staking::StakerStatus::::Nominator(vec![1]), + ), + ]; + + let _ = pallet_staking::GenesisConfig:: { + stakers: stakers.clone(), + // ideal validator count + validator_count: 2, + minimum_validator_count: 1, + invulnerables: vec![], + slash_reward_fraction: Perbill::from_percent(10), + min_nominator_bond: ExistentialDeposit::get(), + min_validator_bond: ExistentialDeposit::get(), + ..Default::default() + } + .assimilate_storage(&mut storage); + + let mut ext = sp_io::TestExternalities::from(storage); + + ext.execute_with(|| { + // for events to be deposited. + frame_system::Pallet::::set_block_number(1); + // set era for staking. + start_era(0); + }); + + ext + } + pub fn build_and_execute(self, test: impl FnOnce()) { + sp_tracing::try_init_simple(); + let mut ext = self.build(); + ext.execute_with(test); + ext.execute_with(|| { + #[cfg(feature = "try-runtime")] + >::try_state( + frame_system::Pallet::::block_number(), + frame_support::traits::TryStateSelect::All, + ) + .unwrap(); + #[cfg(not(feature = "try-runtime"))] + DelegatedStaking::do_try_state().unwrap(); + }); + } +} + +/// fund and return who. +pub(crate) fn fund(who: &AccountId, amount: Balance) { + let _ = Balances::deposit_creating(who, amount); +} + +/// Sets up delegation for passed delegators, returns total delegated amount. +/// +/// `delegate_amount` is incremented by the amount `increment` starting with `base_delegate_amount` +/// from lower index to higher index of delegators. +pub(crate) fn setup_delegation_stake( + agent: AccountId, + reward_acc: AccountId, + delegators: Vec, + base_delegate_amount: Balance, + increment: Balance, +) -> Balance { + fund(&agent, 100); + assert_ok!(DelegatedStaking::register_agent(RawOrigin::Signed(agent).into(), reward_acc)); + let mut delegated_amount: Balance = 0; + for (index, delegator) in delegators.iter().enumerate() { + let amount_to_delegate = base_delegate_amount + increment * index as Balance; + delegated_amount += amount_to_delegate; + + fund(delegator, amount_to_delegate + ExistentialDeposit::get()); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(*delegator).into(), + agent, + amount_to_delegate + )); + } + + // sanity checks + assert_eq!(DelegatedStaking::stakeable_balance(&agent), delegated_amount); + assert_eq!(Agent::::get(&agent).unwrap().available_to_bond(), 0); + + delegated_amount +} + +pub(crate) fn start_era(era: sp_staking::EraIndex) { + CurrentEra::::set(Some(era)); + ActiveEra::::set(Some(ActiveEraInfo { index: era, start: None })); +} + +pub(crate) fn eq_stake(who: AccountId, total: Balance, active: Balance) -> bool { + Staking::stake(&who).unwrap() == Stake { total, active } && + get_agent(&who).ledger.stakeable_balance() == total +} + +pub(crate) fn get_agent(agent: &AccountId) -> Agent { + Agent::::get(agent).expect("delegate should exist") +} + +parameter_types! { + static ObservedEventsDelegatedStaking: usize = 0; + static ObservedEventsPools: usize = 0; +} + +pub(crate) fn pool_events_since_last_call() -> Vec> { + let events = System::read_events_for_pallet::>(); + let already_seen = ObservedEventsPools::get(); + ObservedEventsPools::set(events.len()); + events.into_iter().skip(already_seen).collect() +} + +pub(crate) fn events_since_last_call() -> Vec> { + let events = System::read_events_for_pallet::>(); + let already_seen = ObservedEventsDelegatedStaking::get(); + ObservedEventsDelegatedStaking::set(events.len()); + events.into_iter().skip(already_seen).collect() +} diff --git a/substrate/frame/delegated-staking/src/tests.rs b/substrate/frame/delegated-staking/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..6b68726b274cb0447fd26c11e4c2e6ad282f8e85 --- /dev/null +++ b/substrate/frame/delegated-staking/src/tests.rs @@ -0,0 +1,1184 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for pallet-delegated-staking. + +use super::*; +use crate::mock::*; +use frame_support::{assert_noop, assert_ok, traits::fungible::InspectHold}; +use pallet_nomination_pools::{Error as PoolsError, Event as PoolsEvent}; +use pallet_staking::Error as StakingError; +use sp_staking::{DelegationInterface, StakerStatus}; + +#[test] +fn create_an_agent_with_first_delegator() { + ExtBuilder::default().build_and_execute(|| { + let agent: AccountId = 200; + let reward_account: AccountId = 201; + let delegator: AccountId = 202; + + // set intention to accept delegation. + fund(&agent, 1000); + assert_ok!(DelegatedStaking::register_agent( + RawOrigin::Signed(agent).into(), + reward_account + )); + + // delegate to this account + fund(&delegator, 1000); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator).into(), + agent, + 100 + )); + + // verify + assert!(DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 100); + assert_eq!( + Balances::balance_on_hold(&HoldReason::StakingDelegation.into(), &delegator), + 100 + ); + assert_eq!(DelegatedStaking::held_balance_of(&delegator), 100); + }); +} + +#[test] +fn cannot_become_agent() { + ExtBuilder::default().build_and_execute(|| { + // cannot set reward account same as agent account + assert_noop!( + DelegatedStaking::register_agent(RawOrigin::Signed(100).into(), 100), + Error::::InvalidRewardDestination + ); + + // an existing validator cannot become agent + assert_noop!( + DelegatedStaking::register_agent( + RawOrigin::Signed(mock::GENESIS_VALIDATOR).into(), + 100 + ), + Error::::AlreadyStaking + ); + + // an existing direct staker to `CoreStaking` cannot become an agent. + assert_noop!( + DelegatedStaking::register_agent( + RawOrigin::Signed(mock::GENESIS_NOMINATOR_ONE).into(), + 100 + ), + Error::::AlreadyStaking + ); + assert_noop!( + DelegatedStaking::register_agent( + RawOrigin::Signed(mock::GENESIS_NOMINATOR_TWO).into(), + 100 + ), + Error::::AlreadyStaking + ); + }); +} + +#[test] +fn create_multiple_delegators() { + ExtBuilder::default().build_and_execute(|| { + let agent: AccountId = 200; + let reward_account: AccountId = 201; + + // stakeable balance is 0 for non agent + fund(&agent, 1000); + assert!(!DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 0); + + // set intention to accept delegation. + assert_ok!(DelegatedStaking::register_agent( + RawOrigin::Signed(agent).into(), + reward_account + )); + + // create 100 delegators + for i in 202..302 { + fund(&i, 100 + ExistentialDeposit::get()); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(i).into(), + agent, + 100 + )); + // Balance of 100 held on delegator account for delegating to the agent. + assert_eq!(Balances::balance_on_hold(&HoldReason::StakingDelegation.into(), &i), 100); + } + + // verify + assert!(DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 100 * 100); + }); +} + +#[test] +fn agent_restrictions() { + // Similar to creating a nomination pool + ExtBuilder::default().build_and_execute(|| { + let agent_one = 200; + let delegator_one = 210; + fund(&agent_one, 100); + assert_ok!(DelegatedStaking::register_agent( + RawOrigin::Signed(agent_one).into(), + agent_one + 1 + )); + fund(&delegator_one, 200); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_one).into(), + agent_one, + 100 + )); + + let agent_two = 300; + let delegator_two = 310; + fund(&agent_two, 100); + assert_ok!(DelegatedStaking::register_agent( + RawOrigin::Signed(agent_two).into(), + agent_two + 1 + )); + fund(&delegator_two, 200); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_two).into(), + agent_two, + 100 + )); + + // agent one tries to delegate to agent 2 + assert_noop!( + DelegatedStaking::delegate_to_agent(RawOrigin::Signed(agent_one).into(), agent_two, 10), + Error::::InvalidDelegation + ); + + // agent one tries to delegate to a delegator + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(agent_one).into(), + delegator_one, + 10 + ), + Error::::InvalidDelegation + ); + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(agent_one).into(), + delegator_two, + 10 + ), + Error::::InvalidDelegation + ); + + // delegator one tries to delegate to agent 2 as well (it already delegates to agent + // 1) + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_one).into(), + agent_two, + 10 + ), + Error::::InvalidDelegation + ); + + // cannot delegate to non agents. + let non_agent = 201; + // give it some funds + fund(&non_agent, 200); + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_one).into(), + non_agent, + 10 + ), + Error::::InvalidDelegation + ); + + // cannot delegate to a delegator + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_one).into(), + delegator_two, + 10 + ), + Error::::InvalidDelegation + ); + + // delegator cannot delegate to self + assert_noop!( + DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator_one).into(), + delegator_one, + 10 + ), + Error::::InvalidDelegation + ); + + // agent cannot delegate to self + assert_noop!( + DelegatedStaking::delegate_to_agent(RawOrigin::Signed(agent_one).into(), agent_one, 10), + Error::::InvalidDelegation + ); + }); +} + +#[test] +fn apply_pending_slash() { + ExtBuilder::default().build_and_execute(|| { + start_era(1); + let agent: AccountId = 200; + let reward_acc: AccountId = 201; + let delegators: Vec = (301..=350).collect(); + let reporter: AccountId = 400; + + let total_staked = setup_delegation_stake(agent, reward_acc, delegators.clone(), 10, 10); + + start_era(4); + // slash half of the stake + pallet_staking::slashing::do_slash::( + &agent, + total_staked / 2, + &mut Default::default(), + &mut Default::default(), + 3, + ); + + // agent cannot slash an account that is not its delegator. + setup_delegation_stake(210, 211, (351..=352).collect(), 100, 0); + assert_noop!( + ::delegator_slash(&agent, &351, 1, Some(400)), + Error::::NotAgent + ); + // or a non delegator account + fund(&353, 100); + assert_noop!( + ::delegator_slash(&agent, &353, 1, Some(400)), + Error::::NotDelegator + ); + + // ensure bookkept pending slash is correct. + assert_eq!(get_agent(&agent).ledger.pending_slash, total_staked / 2); + let mut old_reporter_balance = Balances::free_balance(reporter); + + // lets apply the pending slash on delegators. + for i in delegators { + // balance before slash + let initial_pending_slash = get_agent(&agent).ledger.pending_slash; + assert!(initial_pending_slash > 0); + let unslashed_balance = DelegatedStaking::held_balance_of(&i); + let slash = unslashed_balance / 2; + // slash half of delegator's delegation. + assert_ok!(::delegator_slash( + &agent, + &i, + slash, + Some(400) + )); + + // balance after slash. + assert_eq!(DelegatedStaking::held_balance_of(&i), unslashed_balance - slash); + // pending slash is reduced by the amount slashed. + assert_eq!(get_agent(&agent).ledger.pending_slash, initial_pending_slash - slash); + // reporter get 10% of the slash amount. + assert_eq!( + Balances::free_balance(reporter) - old_reporter_balance, + ::slash_reward_fraction() * slash, + ); + // update old balance + old_reporter_balance = Balances::free_balance(reporter); + } + + // nothing to slash anymore + assert_eq!(get_agent(&agent).ledger.pending_slash, 0); + + // cannot slash anymore + assert_noop!( + ::delegator_slash(&agent, &350, 1, None), + Error::::NothingToSlash + ); + }); +} + +/// Integration tests with pallet-staking. +mod staking_integration { + use super::*; + use pallet_staking::RewardDestination; + use sp_staking::Stake; + + #[test] + fn bond() { + ExtBuilder::default().build_and_execute(|| { + let agent: AccountId = 99; + let reward_acc: AccountId = 100; + assert_eq!(Staking::status(&agent), Err(StakingError::::NotStash.into())); + + // set intention to become an agent + fund(&agent, 100); + assert_ok!(DelegatedStaking::register_agent( + RawOrigin::Signed(agent).into(), + reward_acc + )); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 0); + + let mut delegated_balance: Balance = 0; + + // set some delegations + for delegator in 200..250 { + fund(&delegator, 200); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(delegator).into(), + agent, + 100 + )); + delegated_balance += 100; + assert_eq!( + Balances::balance_on_hold(&HoldReason::StakingDelegation.into(), &delegator), + 100 + ); + assert_eq!(DelegatedStaking::delegator_balance(&delegator), 100); + + let agent_obj = get_agent(&agent); + assert_eq!(agent_obj.ledger.stakeable_balance(), delegated_balance); + assert_eq!(agent_obj.available_to_bond(), 0); + assert_eq!(agent_obj.bonded_stake(), delegated_balance); + } + + assert_eq!(Staking::stake(&agent).unwrap(), Stake { total: 50 * 100, active: 50 * 100 }) + }); + } + + #[test] + fn withdraw_test() { + ExtBuilder::default().build_and_execute(|| { + // initial era + start_era(1); + let agent: AccountId = 200; + let reward_acc: AccountId = 201; + let delegators: Vec = (301..=350).collect(); + let total_staked = + setup_delegation_stake(agent, reward_acc, delegators.clone(), 10, 10); + + // lets go to a new era + start_era(2); + + assert!(eq_stake(agent, total_staked, total_staked)); + // Withdrawing without unbonding would fail. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 301, 50, 0), + Error::::NotEnoughFunds + ); + + // 305 wants to unbond 50 in era 2, withdrawable in era 5. + assert_ok!(Staking::unbond(RawOrigin::Signed(agent).into(), 50)); + + // 310 wants to unbond 100 in era 3, withdrawable in era 6. + start_era(3); + assert_ok!(Staking::unbond(RawOrigin::Signed(agent).into(), 100)); + + // 320 wants to unbond 200 in era 4, withdrawable in era 7. + start_era(4); + assert_ok!(Staking::unbond(RawOrigin::Signed(agent).into(), 200)); + + // active stake is now reduced.. + let expected_active = total_staked - (50 + 100 + 200); + assert!(eq_stake(agent, total_staked, expected_active)); + + // nothing to withdraw at era 4 + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 50, 0), + Error::::NotEnoughFunds + ); + + assert_eq!(get_agent(&agent).available_to_bond(), 0); + // full amount is still delegated + assert_eq!(get_agent(&agent).ledger.effective_balance(), total_staked); + + start_era(5); + // at era 5, 50 tokens are withdrawable, cannot withdraw more. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 51, 0), + Error::::NotEnoughFunds + ); + // less is possible + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 305, + 30, + 0 + )); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 305, + 20, + 0 + )); + + // Lets go to future era where everything is unbonded. Withdrawable amount: 100 + 200 + start_era(7); + // 305 has no more amount delegated so it cannot withdraw. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 5, 0), + Error::::NotDelegator + ); + // 309 is an active delegator but has total delegation of 90, so it cannot withdraw more + // than that. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 309, 91, 0), + Error::::NotEnoughFunds + ); + // 310 cannot withdraw more than delegated funds. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 310, 101, 0), + Error::::NotEnoughFunds + ); + // but can withdraw all its delegation amount. + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 310, + 100, + 0 + )); + // 320 can withdraw all its delegation amount. + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 320, + 200, + 0 + )); + + // cannot withdraw anything more.. + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 301, 1, 0), + Error::::NotEnoughFunds + ); + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 350, 1, 0), + Error::::NotEnoughFunds + ); + }); + } + + #[test] + fn withdraw_happens_with_unbonded_balance_first() { + ExtBuilder::default().build_and_execute(|| { + start_era(1); + let agent = 200; + setup_delegation_stake(agent, 201, (300..350).collect(), 100, 0); + + // verify withdraw not possible yet + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 300, 100, 0), + Error::::NotEnoughFunds + ); + + // fill up unlocking chunks in core staking. + // 10 is the max chunks + for i in 2..=11 { + start_era(i); + assert_ok!(Staking::unbond(RawOrigin::Signed(agent).into(), 10)); + // no withdrawals from core staking yet. + assert_eq!(get_agent(&agent).ledger.unclaimed_withdrawals, 0); + } + + // another unbond would trigger withdrawal + start_era(12); + assert_ok!(Staking::unbond(RawOrigin::Signed(agent).into(), 10)); + + // 8 previous unbonds would be withdrawn as they were already unlocked. Unlocking period + // is 3 eras. + assert_eq!(get_agent(&agent).ledger.unclaimed_withdrawals, 8 * 10); + + // release some delegation now. + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 300, + 40, + 0 + )); + assert_eq!(get_agent(&agent).ledger.unclaimed_withdrawals, 80 - 40); + + // cannot release more than available + assert_noop!( + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 300, 50, 0), + Error::::NotEnoughFunds + ); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 300, + 40, + 0 + )); + + assert_eq!(DelegatedStaking::held_balance_of(&300), 100 - 80); + }); + } + + #[test] + fn reward_destination_restrictions() { + ExtBuilder::default().build_and_execute(|| { + // give some funds to 200 + fund(&200, 1000); + let balance_200 = Balances::free_balance(200); + + // `Agent` account cannot be reward destination + assert_noop!( + DelegatedStaking::register_agent(RawOrigin::Signed(200).into(), 200), + Error::::InvalidRewardDestination + ); + + // different reward account works + assert_ok!(DelegatedStaking::register_agent(RawOrigin::Signed(200).into(), 201)); + // add some delegations to it + fund(&300, 1000); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(300).into(), + 200, + 100 + )); + + // update_payee to self fails. + assert_noop!( + ::update_payee(&200, &200), + StakingError::::RewardDestinationRestricted + ); + + // passing correct reward destination works + assert_ok!(::update_payee(&200, &201)); + + // amount is staked correctly + assert!(eq_stake(200, 100, 100)); + assert_eq!(get_agent(&200).available_to_bond(), 0); + assert_eq!(get_agent(&200).ledger.effective_balance(), 100); + + // free balance of delegate is untouched + assert_eq!(Balances::free_balance(200), balance_200); + }); + } + + #[test] + fn agent_restrictions() { + ExtBuilder::default().build_and_execute(|| { + setup_delegation_stake(200, 201, (202..203).collect(), 100, 0); + + // Registering again is noop + assert_noop!( + DelegatedStaking::register_agent(RawOrigin::Signed(200).into(), 201), + Error::::NotAllowed + ); + // a delegator cannot become delegate + assert_noop!( + DelegatedStaking::register_agent(RawOrigin::Signed(202).into(), 203), + Error::::NotAllowed + ); + // existing staker cannot become a delegate + assert_noop!( + DelegatedStaking::register_agent( + RawOrigin::Signed(GENESIS_NOMINATOR_ONE).into(), + 201 + ), + Error::::AlreadyStaking + ); + assert_noop!( + DelegatedStaking::register_agent(RawOrigin::Signed(GENESIS_VALIDATOR).into(), 201), + Error::::AlreadyStaking + ); + }); + } + + #[test] + fn migration_works() { + ExtBuilder::default().build_and_execute(|| { + // add a nominator + let staked_amount = 4000; + let agent_amount = 5000; + fund(&200, agent_amount); + + assert_ok!(Staking::bond( + RuntimeOrigin::signed(200), + staked_amount, + RewardDestination::Account(201) + )); + assert_ok!(Staking::nominate(RuntimeOrigin::signed(200), vec![GENESIS_VALIDATOR],)); + let init_stake = Staking::stake(&200).unwrap(); + + // scenario: 200 is a pool account, and the stake comes from its 4 delegators (300..304) + // in equal parts. lets try to migrate this nominator into delegate based stake. + + // all balance currently is in 200 + assert_eq!(Balances::free_balance(200), agent_amount); + + // to migrate, nominator needs to set an account as a proxy delegator where staked funds + // will be moved and delegated back to this old nominator account. This should be funded + // with at least ED. + let proxy_delegator = DelegatedStaking::generate_proxy_delegator(200); + + assert_ok!(DelegatedStaking::migrate_to_agent(RawOrigin::Signed(200).into(), 201)); + + // verify all went well + let mut expected_proxy_delegated_amount = agent_amount; + assert_eq!( + Balances::balance_on_hold(&HoldReason::StakingDelegation.into(), &proxy_delegator), + expected_proxy_delegated_amount + ); + // stake amount is transferred from delegate to proxy delegator account. + assert_eq!(Balances::free_balance(200), 0); + assert_eq!(Staking::stake(&200).unwrap(), init_stake); + assert_eq!(get_agent(&200).ledger.effective_balance(), agent_amount); + assert_eq!(get_agent(&200).available_to_bond(), 0); + assert_eq!(get_agent(&200).ledger.unclaimed_withdrawals, agent_amount - staked_amount); + + // now lets migrate the delegators + let delegator_share = agent_amount / 4; + for delegator in 300..304 { + assert_eq!(Balances::free_balance(delegator), 0); + // fund them with ED + fund(&delegator, ExistentialDeposit::get()); + // migrate 1/4th amount into each delegator + assert_ok!(DelegatedStaking::migrate_delegation( + RawOrigin::Signed(200).into(), + delegator, + delegator_share + )); + assert_eq!( + Balances::balance_on_hold(&HoldReason::StakingDelegation.into(), &delegator), + delegator_share + ); + expected_proxy_delegated_amount -= delegator_share; + assert_eq!( + Balances::balance_on_hold( + &HoldReason::StakingDelegation.into(), + &proxy_delegator + ), + expected_proxy_delegated_amount + ); + + // delegate stake is unchanged. + assert_eq!(Staking::stake(&200).unwrap(), init_stake); + assert_eq!(get_agent(&200).ledger.effective_balance(), agent_amount); + assert_eq!(get_agent(&200).available_to_bond(), 0); + assert_eq!( + get_agent(&200).ledger.unclaimed_withdrawals, + agent_amount - staked_amount + ); + } + + // cannot use migrate delegator anymore + assert_noop!( + DelegatedStaking::migrate_delegation(RawOrigin::Signed(200).into(), 305, 1), + Error::::NotEnoughFunds + ); + }); + } +} + +mod pool_integration { + use super::*; + use pallet_nomination_pools::{BondExtra, BondedPools, PoolState}; + + #[test] + fn create_pool_test() { + ExtBuilder::default().build_and_execute(|| { + let creator: AccountId = 100; + fund(&creator, 500); + let delegate_amount = 200; + + // nothing held initially + assert_eq!(DelegatedStaking::held_balance_of(&creator), 0); + + // create pool + assert_ok!(Pools::create( + RawOrigin::Signed(creator).into(), + delegate_amount, + creator, + creator, + creator + )); + + // correct amount is locked in depositor's account. + assert_eq!(DelegatedStaking::held_balance_of(&creator), delegate_amount); + + let pool_account = Pools::generate_bonded_account(1); + let agent = get_agent(&pool_account); + + // verify state + assert_eq!(agent.ledger.effective_balance(), delegate_amount); + assert_eq!(agent.available_to_bond(), 0); + assert_eq!(agent.total_unbonded(), 0); + }); + } + + #[test] + fn join_pool() { + ExtBuilder::default().build_and_execute(|| { + // create a pool + let pool_id = create_pool(100, 200); + // keep track of staked amount. + let mut staked_amount: Balance = 200; + + // fund delegator + let delegator: AccountId = 300; + fund(&delegator, 500); + // nothing held initially + assert_eq!(DelegatedStaking::held_balance_of(&delegator), 0); + + // delegator joins pool + assert_ok!(Pools::join(RawOrigin::Signed(delegator).into(), 100, pool_id)); + staked_amount += 100; + + // correct amount is locked in depositor's account. + assert_eq!(DelegatedStaking::held_balance_of(&delegator), 100); + + // delegator is not actively exposed to core staking. + assert_eq!(Staking::status(&delegator), Err(StakingError::::NotStash.into())); + + let pool_agent = get_agent(&Pools::generate_bonded_account(1)); + // verify state + assert_eq!(pool_agent.ledger.effective_balance(), staked_amount); + assert_eq!(pool_agent.bonded_stake(), staked_amount); + assert_eq!(pool_agent.available_to_bond(), 0); + assert_eq!(pool_agent.total_unbonded(), 0); + + // cannot reap agent in staking. + assert_noop!( + Staking::reap_stash(RuntimeOrigin::signed(100), pool_agent.key, 0), + StakingError::::VirtualStakerNotAllowed + ); + + // let a bunch of delegators join this pool + for i in 301..350 { + fund(&i, 500); + assert_ok!(Pools::join(RawOrigin::Signed(i).into(), 100 + i, pool_id)); + staked_amount += 100 + i; + assert_eq!(DelegatedStaking::held_balance_of(&i), 100 + i); + } + + let pool_agent = pool_agent.refresh().unwrap(); + assert_eq!(pool_agent.ledger.effective_balance(), staked_amount); + assert_eq!(pool_agent.bonded_stake(), staked_amount); + assert_eq!(pool_agent.available_to_bond(), 0); + assert_eq!(pool_agent.total_unbonded(), 0); + }); + } + + #[test] + fn bond_extra_to_pool() { + ExtBuilder::default().build_and_execute(|| { + let pool_id = create_pool(100, 200); + add_delegators_to_pool(pool_id, (300..310).collect(), 100); + let mut staked_amount = 200 + 100 * 10; + assert_eq!(get_pool_agent(pool_id).bonded_stake(), staked_amount); + + // bond extra to pool + for i in 300..310 { + assert_ok!(Pools::bond_extra( + RawOrigin::Signed(i).into(), + BondExtra::FreeBalance(50) + )); + staked_amount += 50; + assert_eq!(get_pool_agent(pool_id).bonded_stake(), staked_amount); + } + }); + } + + #[test] + fn claim_pool_rewards() { + ExtBuilder::default().build_and_execute(|| { + let creator = 100; + let creator_stake = 1000; + let pool_id = create_pool(creator, creator_stake); + add_delegators_to_pool(pool_id, (300..310).collect(), 100); + add_delegators_to_pool(pool_id, (310..320).collect(), 200); + let total_staked = creator_stake + 100 * 10 + 200 * 10; + + // give some rewards + let reward_acc = Pools::generate_reward_account(pool_id); + let reward_amount = 1000; + fund(&reward_acc, reward_amount); + + // claim rewards + for i in 300..320 { + let pre_balance = Balances::free_balance(i); + let delegator_staked_balance = DelegatedStaking::held_balance_of(&i); + // payout reward + assert_ok!(Pools::claim_payout(RawOrigin::Signed(i).into())); + + let reward = Balances::free_balance(i) - pre_balance; + assert_eq!(reward, delegator_staked_balance * reward_amount / total_staked); + } + + // payout creator + let pre_balance = Balances::free_balance(creator); + assert_ok!(Pools::claim_payout(RawOrigin::Signed(creator).into())); + // verify they are paid out correctly + let reward = Balances::free_balance(creator) - pre_balance; + assert_eq!(reward, creator_stake * reward_amount / total_staked); + + // reward account should only have left minimum balance after paying out everyone. + assert_eq!(Balances::free_balance(reward_acc), ExistentialDeposit::get()); + }); + } + + #[test] + fn withdraw_from_pool() { + ExtBuilder::default().build_and_execute(|| { + // initial era + start_era(1); + + let pool_id = create_pool(100, 1000); + let bond_amount = 200; + add_delegators_to_pool(pool_id, (300..310).collect(), bond_amount); + let total_staked = 1000 + bond_amount * 10; + let pool_acc = Pools::generate_bonded_account(pool_id); + + start_era(2); + // nothing to release yet. + assert_noop!( + Pools::withdraw_unbonded(RawOrigin::Signed(301).into(), 301, 0), + PoolsError::::SubPoolsNotFound + ); + + // 301 wants to unbond 50 in era 2, withdrawable in era 5. + assert_ok!(Pools::unbond(RawOrigin::Signed(301).into(), 301, 50)); + + // 302 wants to unbond 100 in era 3, withdrawable in era 6. + start_era(3); + assert_ok!(Pools::unbond(RawOrigin::Signed(302).into(), 302, 100)); + + // 303 wants to unbond 200 in era 4, withdrawable in era 7. + start_era(4); + assert_ok!(Pools::unbond(RawOrigin::Signed(303).into(), 303, 200)); + + // active stake is now reduced.. + let expected_active = total_staked - (50 + 100 + 200); + assert!(eq_stake(pool_acc, total_staked, expected_active)); + + // nothing to withdraw at era 4 + for i in 301..310 { + assert_noop!( + Pools::withdraw_unbonded(RawOrigin::Signed(i).into(), i, 0), + PoolsError::::CannotWithdrawAny + ); + } + + assert!(eq_stake(pool_acc, total_staked, expected_active)); + + start_era(5); + // at era 5, 301 can withdraw. + + System::reset_events(); + let held_301 = DelegatedStaking::held_balance_of(&301); + let free_301 = Balances::free_balance(301); + + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(301).into(), 301, 0)); + assert_eq!( + events_since_last_call(), + vec![Event::Released { agent: pool_acc, delegator: 301, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Withdrawn { member: 301, pool_id, balance: 50, points: 50 }] + ); + assert_eq!(DelegatedStaking::held_balance_of(&301), held_301 - 50); + assert_eq!(Balances::free_balance(301), free_301 + 50); + + start_era(7); + // era 7 both delegators can withdraw + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(302).into(), 302, 0)); + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(303).into(), 303, 0)); + + assert_eq!( + events_since_last_call(), + vec![ + Event::Released { agent: pool_acc, delegator: 302, amount: 100 }, + Event::Released { agent: pool_acc, delegator: 303, amount: 200 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 302, pool_id, balance: 100, points: 100 }, + PoolsEvent::Withdrawn { member: 303, pool_id, balance: 200, points: 200 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 303 }, + ] + ); + + // 303 is killed + assert!(!Delegators::::contains_key(303)); + }); + } + + #[test] + fn pool_withdraw_unbonded() { + ExtBuilder::default().build_and_execute(|| { + // initial era + start_era(1); + let pool_id = create_pool(100, 1000); + add_delegators_to_pool(pool_id, (300..310).collect(), 200); + + start_era(2); + // 1000 tokens to be unbonded in era 5. + for i in 300..310 { + assert_ok!(Pools::unbond(RawOrigin::Signed(i).into(), i, 100)); + } + + start_era(3); + // 500 tokens to be unbonded in era 6. + for i in 300..310 { + assert_ok!(Pools::unbond(RawOrigin::Signed(i).into(), i, 50)); + } + + start_era(5); + // withdraw pool should withdraw 1000 tokens + assert_ok!(Pools::pool_withdraw_unbonded(RawOrigin::Signed(100).into(), pool_id, 0)); + assert_eq!(get_pool_agent(pool_id).total_unbonded(), 1000); + + start_era(6); + // should withdraw 500 more + assert_ok!(Pools::pool_withdraw_unbonded(RawOrigin::Signed(100).into(), pool_id, 0)); + assert_eq!(get_pool_agent(pool_id).total_unbonded(), 1000 + 500); + + start_era(7); + // Nothing to withdraw, still at 1500. + assert_ok!(Pools::pool_withdraw_unbonded(RawOrigin::Signed(100).into(), pool_id, 0)); + assert_eq!(get_pool_agent(pool_id).total_unbonded(), 1500); + }); + } + + #[test] + fn update_nominations() { + ExtBuilder::default().build_and_execute(|| { + start_era(1); + // can't nominate for non-existent pool + assert_noop!( + Pools::nominate(RawOrigin::Signed(100).into(), 1, vec![99]), + PoolsError::::PoolNotFound + ); + + let pool_id = create_pool(100, 1000); + let pool_acc = Pools::generate_bonded_account(pool_id); + assert_ok!(Pools::nominate(RawOrigin::Signed(100).into(), 1, vec![20, 21, 22])); + assert!(Staking::status(&pool_acc) == Ok(StakerStatus::Nominator(vec![20, 21, 22]))); + + start_era(3); + assert_ok!(Pools::nominate(RawOrigin::Signed(100).into(), 1, vec![18, 19, 22])); + assert!(Staking::status(&pool_acc) == Ok(StakerStatus::Nominator(vec![18, 19, 22]))); + }); + } + + #[test] + fn destroy_pool() { + ExtBuilder::default().build_and_execute(|| { + start_era(1); + let creator = 100; + let creator_stake = 1000; + let pool_id = create_pool(creator, creator_stake); + add_delegators_to_pool(pool_id, (300..310).collect(), 200); + + start_era(3); + // lets destroy the pool + assert_ok!(Pools::set_state( + RawOrigin::Signed(creator).into(), + pool_id, + PoolState::Destroying + )); + assert_ok!(Pools::chill(RawOrigin::Signed(creator).into(), pool_id)); + + // unbond all members by the creator/admin + for i in 300..310 { + assert_ok!(Pools::unbond(RawOrigin::Signed(creator).into(), i, 200)); + } + + start_era(6); + // withdraw all members by the creator/admin + for i in 300..310 { + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(creator).into(), i, 0)); + } + + // unbond creator + assert_ok!(Pools::unbond(RawOrigin::Signed(creator).into(), creator, creator_stake)); + + start_era(9); + System::reset_events(); + // Withdraw self + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(creator).into(), creator, 0)); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { + member: creator, + pool_id, + balance: creator_stake, + points: creator_stake, + }, + PoolsEvent::MemberRemoved { pool_id, member: creator }, + PoolsEvent::Destroyed { pool_id }, + ] + ); + + // Make sure all data is cleaned up. + assert!(!Agents::::contains_key(Pools::generate_bonded_account(pool_id))); + assert!(!System::account_exists(&Pools::generate_bonded_account(pool_id))); + assert!(!Delegators::::contains_key(creator)); + for i in 300..310 { + assert!(!Delegators::::contains_key(i)); + } + }); + } + + #[test] + fn pool_partially_slashed() { + ExtBuilder::default().build_and_execute(|| { + start_era(1); + let creator = 100; + let creator_stake = 500; + let pool_id = create_pool(creator, creator_stake); + let delegator_stake = 100; + add_delegators_to_pool(pool_id, (300..306).collect(), delegator_stake); + let pool_acc = Pools::generate_bonded_account(pool_id); + + let total_staked = creator_stake + delegator_stake * 6; + assert_eq!(Staking::stake(&pool_acc).unwrap().total, total_staked); + + // lets unbond a delegator each in next eras (2, 3, 4). + start_era(2); + assert_ok!(Pools::unbond(RawOrigin::Signed(300).into(), 300, delegator_stake)); + + start_era(3); + assert_ok!(Pools::unbond(RawOrigin::Signed(301).into(), 301, delegator_stake)); + + start_era(4); + assert_ok!(Pools::unbond(RawOrigin::Signed(302).into(), 302, delegator_stake)); + System::reset_events(); + + // slash the pool at era 3 + assert_eq!( + BondedPools::::get(1).unwrap().points, + creator_stake + delegator_stake * 6 - delegator_stake * 3 + ); + pallet_staking::slashing::do_slash::( + &pool_acc, + 500, + &mut Default::default(), + &mut Default::default(), + 3, + ); + + assert_eq!( + pool_events_since_last_call(), + vec![ + // 300 did not get slashed as all as it unbonded in an era before slash. + // 301 got slashed 50% of 100 = 50. + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 6, balance: 50 }, + // 302 got slashed 50% of 100 = 50. + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 7, balance: 50 }, + // Rest of the pool slashed 50% of 800 = 400. + PoolsEvent::PoolSlashed { pool_id: 1, balance: 400 }, + ] + ); + + // slash is lazy and balance is still locked in user's accounts. + assert_eq!(DelegatedStaking::held_balance_of(&creator), creator_stake); + for i in 300..306 { + assert_eq!(DelegatedStaking::held_balance_of(&i), delegator_stake); + } + assert_eq!( + get_pool_agent(pool_id).ledger.effective_balance(), + Staking::total_stake(&pool_acc).unwrap() + ); + + // pending slash is book kept. + assert_eq!(get_pool_agent(pool_id).ledger.pending_slash, 500); + + // go in some distant future era. + start_era(10); + System::reset_events(); + + // 300 is not slashed and can withdraw all balance. + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(300).into(), 300, 1)); + assert_eq!( + events_since_last_call(), + vec![Event::Released { agent: pool_acc, delegator: 300, amount: 100 }] + ); + assert_eq!(get_pool_agent(pool_id).ledger.pending_slash, 500); + + // withdraw the other two delegators (301 and 302) who were unbonding. + for i in 301..=302 { + let pre_balance = Balances::free_balance(i); + let pre_pending_slash = get_pool_agent(pool_id).ledger.pending_slash; + assert_ok!(Pools::withdraw_unbonded(RawOrigin::Signed(i).into(), i, 0)); + assert_eq!( + events_since_last_call(), + vec![ + Event::Slashed { agent: pool_acc, delegator: i, amount: 50 }, + Event::Released { agent: pool_acc, delegator: i, amount: 50 }, + ] + ); + assert_eq!(get_pool_agent(pool_id).ledger.pending_slash, pre_pending_slash - 50); + assert_eq!(DelegatedStaking::held_balance_of(&i), 0); + assert_eq!(Balances::free_balance(i) - pre_balance, 50); + } + + // let's update all the slash + let slash_reporter = 99; + // give our reporter some balance. + fund(&slash_reporter, 100); + + for i in 303..306 { + let pre_pending_slash = get_pool_agent(pool_id).ledger.pending_slash; + assert_ok!(Pools::apply_slash(RawOrigin::Signed(slash_reporter).into(), i)); + + // each member is slashed 50% of 100 = 50. + assert_eq!(get_pool_agent(pool_id).ledger.pending_slash, pre_pending_slash - 50); + // left with 50. + assert_eq!(DelegatedStaking::held_balance_of(&i), 50); + } + // reporter is paid SlashRewardFraction of the slash, i.e. 10% of 50 = 5 + assert_eq!(Balances::free_balance(slash_reporter), 100 + 5 * 3); + // slash creator + assert_ok!(Pools::apply_slash(RawOrigin::Signed(slash_reporter).into(), creator)); + // all slash should be applied now. + assert_eq!(get_pool_agent(pool_id).ledger.pending_slash, 0); + // for creator, 50% of stake should be slashed (250), 10% of which should go to reporter + // (25). + assert_eq!(Balances::free_balance(slash_reporter), 115 + 25); + }); + } + + fn create_pool(creator: AccountId, amount: Balance) -> u32 { + fund(&creator, amount * 2); + assert_ok!(Pools::create( + RawOrigin::Signed(creator).into(), + amount, + creator, + creator, + creator + )); + + pallet_nomination_pools::LastPoolId::::get() + } + + fn add_delegators_to_pool(pool_id: u32, delegators: Vec, amount: Balance) { + for delegator in delegators { + fund(&delegator, amount * 2); + assert_ok!(Pools::join(RawOrigin::Signed(delegator).into(), amount, pool_id)); + } + } + + fn get_pool_agent(pool_id: u32) -> Agent { + get_agent(&Pools::generate_bonded_account(pool_id)) + } +} diff --git a/substrate/frame/delegated-staking/src/types.rs b/substrate/frame/delegated-staking/src/types.rs new file mode 100644 index 0000000000000000000000000000000000000000..958d81c294aa914858601f51a6adaf5cc978d5da --- /dev/null +++ b/substrate/frame/delegated-staking/src/types.rs @@ -0,0 +1,291 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Basic types used in delegated staking. + +use super::*; +use frame_support::traits::DefensiveSaturating; + +/// The type of pot account being created. +#[derive(Encode, Decode)] +pub(crate) enum AccountType { + /// A proxy delegator account created for a nominator who migrated to an `Agent` account. + /// + /// Funds for unmigrated `delegator` accounts of the `Agent` are kept here. + ProxyDelegator, +} + +/// Information about delegation of a `delegator`. +#[derive(Default, Encode, Clone, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct Delegation { + /// The target of delegation. + pub agent: T::AccountId, + /// The amount delegated. + pub amount: BalanceOf, +} + +impl Delegation { + /// Get delegation of a `delegator`. + pub(crate) fn get(delegator: &T::AccountId) -> Option { + >::get(delegator) + } + + /// Create and return a new delegation instance. + pub(crate) fn new(agent: &T::AccountId, amount: BalanceOf) -> Self { + Delegation { agent: agent.clone(), amount } + } + + /// Ensure the delegator is either a new delegator or they are adding more delegation to the + /// existing agent. + /// + /// Delegators are prevented from delegating to multiple agents at the same time. + pub(crate) fn can_delegate(delegator: &T::AccountId, agent: &T::AccountId) -> bool { + Delegation::::get(delegator) + .map(|delegation| delegation.agent == *agent) + .unwrap_or( + // all good if it is a new delegator except it should not be an existing agent. + !>::contains_key(delegator), + ) + } + + /// Save self to storage. If the delegation amount is zero, remove the delegation. + pub(crate) fn update_or_kill(self, key: &T::AccountId) { + // Clean up if no delegation left. + if self.amount == Zero::zero() { + >::remove(key); + return + } + + >::insert(key, self) + } +} + +/// Ledger of all delegations to an `Agent`. +/// +/// This keeps track of the active balance of the `Agent` that is made up from the funds that +/// are currently delegated to this `Agent`. It also tracks the pending slashes yet to be +/// applied among other things. +#[derive(Default, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +pub struct AgentLedger { + /// Where the reward should be paid out. + pub payee: T::AccountId, + /// Sum of all delegated funds to this `Agent`. + #[codec(compact)] + pub total_delegated: BalanceOf, + /// Funds that are withdrawn from core staking but not released to delegator/s. It is a subset + /// of `total_delegated` and can never be greater than it. + /// + /// We need this register to ensure that the `Agent` does not bond funds from delegated + /// funds that are withdrawn and should be claimed by delegators. + #[codec(compact)] + pub unclaimed_withdrawals: BalanceOf, + /// Slashes that are not yet applied. This affects the effective balance of the `Agent`. + #[codec(compact)] + pub pending_slash: BalanceOf, +} + +impl AgentLedger { + /// Create a new instance of `AgentLedger`. + pub(crate) fn new(reward_destination: &T::AccountId) -> Self { + AgentLedger { + payee: reward_destination.clone(), + total_delegated: Zero::zero(), + unclaimed_withdrawals: Zero::zero(), + pending_slash: Zero::zero(), + } + } + + /// Get `AgentLedger` from storage. + pub(crate) fn get(key: &T::AccountId) -> Option { + >::get(key) + } + + /// Save self to storage with the given key. + pub(crate) fn update(self, key: &T::AccountId) { + >::insert(key, self) + } + + /// Effective total balance of the `Agent`. + /// + /// This takes into account any slashes reported to `Agent` but unapplied. + pub(crate) fn effective_balance(&self) -> BalanceOf { + defensive_assert!( + self.total_delegated >= self.pending_slash, + "slash cannot be higher than actual balance of delegator" + ); + + // pending slash needs to be burned and cannot be used for stake. + self.total_delegated.saturating_sub(self.pending_slash) + } + + /// Agent balance that can be staked/bonded in [`T::CoreStaking`]. + pub(crate) fn stakeable_balance(&self) -> BalanceOf { + self.effective_balance().saturating_sub(self.unclaimed_withdrawals) + } +} + +/// Wrapper around `AgentLedger` to provide some helper functions to mutate the ledger. +#[derive(Clone)] +pub struct Agent { + /// storage key + pub key: T::AccountId, + /// storage value + pub ledger: AgentLedger, +} + +impl Agent { + /// Get `Agent` from storage if it exists or return an error. + pub(crate) fn get(agent: &T::AccountId) -> Result, DispatchError> { + let ledger = AgentLedger::::get(agent).ok_or(Error::::NotAgent)?; + Ok(Agent { key: agent.clone(), ledger }) + } + + /// Remove funds that are withdrawn from [Config::CoreStaking] but not claimed by a delegator. + /// + /// Checked decrease of delegation amount from `total_delegated` and `unclaimed_withdrawals` + /// registers. Consumes self and returns a new instance of self if success. + pub(crate) fn remove_unclaimed_withdraw( + self, + amount: BalanceOf, + ) -> Result { + let new_total_delegated = self + .ledger + .total_delegated + .checked_sub(&amount) + .defensive_ok_or(ArithmeticError::Overflow)?; + let new_unclaimed_withdrawals = self + .ledger + .unclaimed_withdrawals + .checked_sub(&amount) + .defensive_ok_or(ArithmeticError::Overflow)?; + + Ok(Agent { + ledger: AgentLedger { + total_delegated: new_total_delegated, + unclaimed_withdrawals: new_unclaimed_withdrawals, + ..self.ledger + }, + ..self + }) + } + + /// Add funds that are withdrawn from [Config::CoreStaking] to be claimed by delegators later. + pub(crate) fn add_unclaimed_withdraw( + self, + amount: BalanceOf, + ) -> Result { + let new_unclaimed_withdrawals = self + .ledger + .unclaimed_withdrawals + .checked_add(&amount) + .defensive_ok_or(ArithmeticError::Overflow)?; + + Ok(Agent { + ledger: AgentLedger { unclaimed_withdrawals: new_unclaimed_withdrawals, ..self.ledger }, + ..self + }) + } + + /// Amount that is delegated but not bonded yet. + /// + /// This importantly does not include `unclaimed_withdrawals` as those should not be bonded + /// again unless explicitly requested. + pub(crate) fn available_to_bond(&self) -> BalanceOf { + let bonded_stake = self.bonded_stake(); + let stakeable = self.ledger.stakeable_balance(); + + defensive_assert!( + stakeable >= bonded_stake, + "cannot be bonded with more than total amount delegated to agent" + ); + + stakeable.saturating_sub(bonded_stake) + } + + /// Remove slashes from the `AgentLedger`. + pub(crate) fn remove_slash(self, amount: BalanceOf) -> Self { + let pending_slash = self.ledger.pending_slash.defensive_saturating_sub(amount); + let total_delegated = self.ledger.total_delegated.defensive_saturating_sub(amount); + + Agent { ledger: AgentLedger { pending_slash, total_delegated, ..self.ledger }, ..self } + } + + /// Get the total stake of agent bonded in [`Config::CoreStaking`]. + pub(crate) fn bonded_stake(&self) -> BalanceOf { + T::CoreStaking::total_stake(&self.key).unwrap_or(Zero::zero()) + } + + /// Returns true if the agent is bonded in [`Config::CoreStaking`]. + pub(crate) fn is_bonded(&self) -> bool { + T::CoreStaking::stake(&self.key).is_ok() + } + + /// Returns the reward account registered by the agent. + pub(crate) fn reward_account(&self) -> &T::AccountId { + &self.ledger.payee + } + + /// Save self to storage. + pub(crate) fn save(self) { + let key = self.key; + self.ledger.update(&key) + } + + /// Save self and remove if no delegation left. + /// + /// Returns: + /// - true if agent killed. + /// - error if the delegate is in an unexpected state. + pub(crate) fn update_or_kill(self) -> Result { + let key = self.key; + // see if delegate can be killed + if self.ledger.total_delegated == Zero::zero() { + ensure!( + self.ledger.unclaimed_withdrawals == Zero::zero() && + self.ledger.pending_slash == Zero::zero(), + Error::::BadState + ); + >::remove(key); + return Ok(true) + } + self.ledger.update(&key); + Ok(false) + } + + /// Reloads self from storage. + pub(crate) fn refresh(self) -> Result, DispatchError> { + Self::get(&self.key) + } + + /// Balance of `Agent` that is not bonded. + /// + /// This is similar to [Self::available_to_bond] except it also includes `unclaimed_withdrawals` + /// of `Agent`. + #[cfg(test)] + pub(crate) fn total_unbonded(&self) -> BalanceOf { + let bonded_stake = self.bonded_stake(); + + let net_balance = self.ledger.effective_balance(); + + assert!(net_balance >= bonded_stake, "cannot be bonded with more than the agent balance"); + + net_balance.saturating_sub(bonded_stake) + } +} diff --git a/substrate/frame/democracy/Cargo.toml b/substrate/frame/democracy/Cargo.toml index edd2d742b5069a73212a291aaf440de40e96fd24..7f182447ead61a0b694b7dc21a888fd4480e1197 100644 --- a/substrate/frame/democracy/Cargo.toml +++ b/substrate/frame/democracy/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/democracy/src/benchmarking.rs b/substrate/frame/democracy/src/benchmarking.rs index aa66137ad880403a3a3934e121e358bc193d0826..799d614c37f4a87a147c1d1e0c21febc1ad68cd3 100644 --- a/substrate/frame/democracy/src/benchmarking.rs +++ b/substrate/frame/democracy/src/benchmarking.rs @@ -108,7 +108,7 @@ benchmarks! { whitelist_account!(caller); }: _(RawOrigin::Signed(caller), proposal, value) verify { - assert_eq!(Democracy::::public_props().len(), p as usize, "Proposals not created."); + assert_eq!(PublicProps::::get().len(), p as usize, "Proposals not created."); } second { @@ -122,12 +122,12 @@ benchmarks! { Democracy::::second(RawOrigin::Signed(seconder).into(), 0)?; } - let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; + let deposits = DepositOf::::get(0).ok_or("Proposal not created")?; assert_eq!(deposits.0.len(), (T::MaxDeposits::get() - 1) as usize, "Seconds not recorded"); whitelist_account!(caller); }: _(RawOrigin::Signed(caller), 0) verify { - let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; + let deposits = DepositOf::::get(0).ok_or("Proposal not created")?; assert_eq!(deposits.0.len(), (T::MaxDeposits::get()) as usize, "`second` benchmark did not work"); } @@ -175,7 +175,7 @@ benchmarks! { // Change vote from aye to nay let nay = Vote { aye: false, conviction: Conviction::Locked1x }; let new_vote = AccountVote::Standard { vote: nay, balance: 1000u32.into() }; - let ref_index = Democracy::::referendum_count() - 1; + let ref_index = ReferendumCount::::get() - 1; // This tests when a user changes a vote whitelist_account!(caller); @@ -186,7 +186,7 @@ benchmarks! { _ => return Err("Votes are not direct".into()), }; assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Vote was incorrectly added"); - let referendum_info = Democracy::::referendum_info(ref_index) + let referendum_info = ReferendumInfoOf::::get(ref_index) .ok_or("referendum doesn't exist")?; let tally = match referendum_info { ReferendumInfo::Ongoing(r) => r.tally, @@ -261,7 +261,7 @@ benchmarks! { }: _(origin, proposal) verify { // External proposal created - ensure!(>::exists(), "External proposal didn't work"); + ensure!(NextExternal::::exists(), "External proposal didn't work"); } external_propose_majority { @@ -271,7 +271,7 @@ benchmarks! { }: _(origin, proposal) verify { // External proposal created - ensure!(>::exists(), "External proposal didn't work"); + ensure!(NextExternal::::exists(), "External proposal didn't work"); } external_propose_default { @@ -281,7 +281,7 @@ benchmarks! { }: _(origin, proposal) verify { // External proposal created - ensure!(>::exists(), "External proposal didn't work"); + ensure!(NextExternal::::exists(), "External proposal didn't work"); } fast_track { @@ -303,7 +303,7 @@ benchmarks! { let delay = 0u32; }: _(origin_fast_track, proposal_hash, voting_period, delay.into()) verify { - assert_eq!(Democracy::::referendum_count(), 1, "referendum not created"); + assert_eq!(ReferendumCount::::get(), 1, "referendum not created"); assert_last_event::(crate::Event::MetadataTransferred { prev_owner: MetadataOwner::External, owner: MetadataOwner::Referendum(0), @@ -338,7 +338,7 @@ benchmarks! { }: _(origin, proposal_hash) verify { assert!(NextExternal::::get().is_none()); - let (_, new_vetoers) = >::get(&proposal_hash).ok_or("no blacklist")?; + let (_, new_vetoers) = Blacklist::::get(&proposal_hash).ok_or("no blacklist")?; assert_eq!(new_vetoers.len(), T::MaxBlacklisted::get() as usize, "vetoers not added"); } @@ -382,7 +382,7 @@ benchmarks! { add_referendum::(i); } - assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); + assert_eq!(ReferendumCount::::get(), r, "referenda not created"); // Launch external LastTabledWasExternal::::put(false); @@ -393,15 +393,15 @@ benchmarks! { let call = Call::::external_propose_majority { proposal }; call.dispatch_bypass_filter(origin)?; // External proposal created - ensure!(>::exists(), "External proposal didn't work"); + ensure!(NextExternal::::exists(), "External proposal didn't work"); let block_number = T::LaunchPeriod::get(); }: { Democracy::::on_initialize(block_number) } verify { // One extra because of next external - assert_eq!(Democracy::::referendum_count(), r + 1, "referenda not created"); - ensure!(!>::exists(), "External wasn't taken"); + assert_eq!(ReferendumCount::::get(), r + 1, "referenda not created"); + ensure!(!NextExternal::::exists(), "External wasn't taken"); // All but the new next external should be finished for i in 0 .. r { @@ -422,7 +422,7 @@ benchmarks! { add_referendum::(i); } - assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); + assert_eq!(ReferendumCount::::get(), r, "referenda not created"); // Launch public assert!(add_proposal::(r).is_ok(), "proposal not created"); @@ -433,7 +433,7 @@ benchmarks! { }: { Democracy::::on_initialize(block_number) } verify { // One extra because of next public - assert_eq!(Democracy::::referendum_count(), r + 1, "proposal not accepted"); + assert_eq!(ReferendumCount::::get(), r + 1, "proposal not accepted"); // All should be finished for i in 0 .. r { @@ -461,8 +461,8 @@ benchmarks! { ReferendumInfoOf::::insert(key, info); } - assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); - assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); + assert_eq!(ReferendumCount::::get(), r, "referenda not created"); + assert_eq!(LowestUnbaked::::get(), 0, "invalid referenda init"); }: { Democracy::::on_initialize(1u32.into()) } verify { @@ -491,8 +491,8 @@ benchmarks! { ReferendumInfoOf::::insert(key, info); } - assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); - assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); + assert_eq!(ReferendumCount::::get(), r, "referenda not created"); + assert_eq!(LowestUnbaked::::get(), 0, "invalid referenda init"); let block_number = T::LaunchPeriod::get(); diff --git a/substrate/frame/democracy/src/lib.rs b/substrate/frame/democracy/src/lib.rs index f3d33a72f3ad1a088d4dc050d1e637acd162db7d..19cdc754659d34b08b3c149e5766ea7bb6c01219 100644 --- a/substrate/frame/democracy/src/lib.rs +++ b/substrate/frame/democracy/src/lib.rs @@ -346,12 +346,10 @@ pub mod pallet { /// The number of (public) proposals that have been made so far. #[pallet::storage] - #[pallet::getter(fn public_prop_count)] pub type PublicPropCount = StorageValue<_, PropIndex, ValueQuery>; /// The public proposals. Unsorted. The second item is the proposal. #[pallet::storage] - #[pallet::getter(fn public_props)] pub type PublicProps = StorageValue< _, BoundedVec<(PropIndex, BoundedCallOf, T::AccountId), T::MaxProposals>, @@ -362,7 +360,6 @@ pub mod pallet { /// /// TWOX-NOTE: Safe, as increasing integer keys are safe. #[pallet::storage] - #[pallet::getter(fn deposit_of)] pub type DepositOf = StorageMap< _, Twox64Concat, @@ -372,20 +369,17 @@ pub mod pallet { /// The next free referendum index, aka the number of referenda started so far. #[pallet::storage] - #[pallet::getter(fn referendum_count)] pub type ReferendumCount = StorageValue<_, ReferendumIndex, ValueQuery>; /// The lowest referendum index representing an unbaked referendum. Equal to /// `ReferendumCount` if there isn't a unbaked referendum. #[pallet::storage] - #[pallet::getter(fn lowest_unbaked)] pub type LowestUnbaked = StorageValue<_, ReferendumIndex, ValueQuery>; /// Information concerning any given referendum. /// /// TWOX-NOTE: SAFE as indexes are not under an attacker’s control. #[pallet::storage] - #[pallet::getter(fn referendum_info)] pub type ReferendumInfoOf = StorageMap< _, Twox64Concat, @@ -595,15 +589,15 @@ pub mod pallet { let who = T::SubmitOrigin::ensure_origin(origin)?; ensure!(value >= T::MinimumDeposit::get(), Error::::ValueLow); - let index = Self::public_prop_count(); + let index = PublicPropCount::::get(); let real_prop_count = PublicProps::::decode_len().unwrap_or(0) as u32; let max_proposals = T::MaxProposals::get(); ensure!(real_prop_count < max_proposals, Error::::TooMany); let proposal_hash = proposal.hash(); - if let Some((until, _)) = >::get(proposal_hash) { + if let Some((until, _)) = Blacklist::::get(proposal_hash) { ensure!( - >::block_number() >= until, + frame_system::Pallet::::block_number() >= until, Error::::ProposalBlacklisted, ); } @@ -638,11 +632,11 @@ pub mod pallet { let seconds = Self::len_of_deposit_of(proposal).ok_or(Error::::ProposalMissing)?; ensure!(seconds < T::MaxDeposits::get(), Error::::TooMany); - let mut deposit = Self::deposit_of(proposal).ok_or(Error::::ProposalMissing)?; + let mut deposit = DepositOf::::get(proposal).ok_or(Error::::ProposalMissing)?; T::Currency::reserve(&who, deposit.1)?; let ok = deposit.0.try_push(who.clone()).is_ok(); debug_assert!(ok, "`seconds` is below static limit; `try_insert` should succeed; qed"); - >::insert(proposal, deposit); + DepositOf::::insert(proposal, deposit); Self::deposit_event(Event::::Seconded { seconder: who, prop_index: proposal }); Ok(()) } @@ -683,9 +677,9 @@ pub mod pallet { let status = Self::referendum_status(ref_index)?; let h = status.proposal.hash(); - ensure!(!>::contains_key(h), Error::::AlreadyCanceled); + ensure!(!Cancellations::::contains_key(h), Error::::AlreadyCanceled); - >::insert(h, true); + Cancellations::::insert(h, true); Self::internal_cancel_referendum(ref_index); Ok(()) } @@ -703,14 +697,14 @@ pub mod pallet { proposal: BoundedCallOf, ) -> DispatchResult { T::ExternalOrigin::ensure_origin(origin)?; - ensure!(!>::exists(), Error::::DuplicateProposal); - if let Some((until, _)) = >::get(proposal.hash()) { + ensure!(!NextExternal::::exists(), Error::::DuplicateProposal); + if let Some((until, _)) = Blacklist::::get(proposal.hash()) { ensure!( - >::block_number() >= until, + frame_system::Pallet::::block_number() >= until, Error::::ProposalBlacklisted, ); } - >::put((proposal, VoteThreshold::SuperMajorityApprove)); + NextExternal::::put((proposal, VoteThreshold::SuperMajorityApprove)); Ok(()) } @@ -732,7 +726,7 @@ pub mod pallet { proposal: BoundedCallOf, ) -> DispatchResult { T::ExternalMajorityOrigin::ensure_origin(origin)?; - >::put((proposal, VoteThreshold::SimpleMajority)); + NextExternal::::put((proposal, VoteThreshold::SimpleMajority)); Ok(()) } @@ -754,7 +748,7 @@ pub mod pallet { proposal: BoundedCallOf, ) -> DispatchResult { T::ExternalDefaultOrigin::ensure_origin(origin)?; - >::put((proposal, VoteThreshold::SuperMajorityAgainst)); + NextExternal::::put((proposal, VoteThreshold::SuperMajorityAgainst)); Ok(()) } @@ -800,15 +794,15 @@ pub mod pallet { ensure!(voting_period > Zero::zero(), Error::::VotingPeriodLow); let (ext_proposal, threshold) = - >::get().ok_or(Error::::ProposalMissing)?; + NextExternal::::get().ok_or(Error::::ProposalMissing)?; ensure!( threshold != VoteThreshold::SuperMajorityApprove, Error::::NotSimpleMajority, ); ensure!(proposal_hash == ext_proposal.hash(), Error::::InvalidHash); - >::kill(); - let now = >::block_number(); + NextExternal::::kill(); + let now = frame_system::Pallet::::block_number(); let ref_index = Self::inject_referendum( now.saturating_add(voting_period), ext_proposal, @@ -840,7 +834,7 @@ pub mod pallet { } let mut existing_vetoers = - >::get(&proposal_hash).map(|pair| pair.1).unwrap_or_default(); + Blacklist::::get(&proposal_hash).map(|pair| pair.1).unwrap_or_default(); let insert_position = existing_vetoers.binary_search(&who).err().ok_or(Error::::AlreadyVetoed)?; existing_vetoers @@ -848,11 +842,11 @@ pub mod pallet { .map_err(|_| Error::::TooMany)?; let until = - >::block_number().saturating_add(T::CooloffPeriod::get()); - >::insert(&proposal_hash, (until, existing_vetoers)); + frame_system::Pallet::::block_number().saturating_add(T::CooloffPeriod::get()); + Blacklist::::insert(&proposal_hash, (until, existing_vetoers)); Self::deposit_event(Event::::Vetoed { who, proposal_hash, until }); - >::kill(); + NextExternal::::kill(); Self::clear_metadata(MetadataOwner::External); Ok(()) } @@ -943,7 +937,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::clear_public_proposals())] pub fn clear_public_proposals(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; - >::kill(); + PublicProps::::kill(); Ok(()) } @@ -1146,7 +1140,7 @@ pub mod pallet { ) -> DispatchResult { match owner { MetadataOwner::External => { - let (_, threshold) = >::get().ok_or(Error::::NoProposal)?; + let (_, threshold) = NextExternal::::get().ok_or(Error::::NoProposal)?; Self::ensure_external_origin(threshold, origin)?; }, MetadataOwner::Proposal(index) => { @@ -1201,7 +1195,7 @@ impl Pallet { /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. pub fn backing_for(proposal: PropIndex) -> Option> { - Self::deposit_of(proposal).map(|(l, d)| d.saturating_mul((l.len() as u32).into())) + DepositOf::::get(proposal).map(|(l, d)| d.saturating_mul((l.len() as u32).into())) } /// Get all referenda ready for tally at block `n`. @@ -1209,8 +1203,8 @@ impl Pallet { n: BlockNumberFor, ) -> Vec<(ReferendumIndex, ReferendumStatus, BoundedCallOf, BalanceOf>)> { - let next = Self::lowest_unbaked(); - let last = Self::referendum_count(); + let next = LowestUnbaked::::get(); + let last = ReferendumCount::::get(); Self::maturing_referenda_at_inner(n, next..last) } @@ -1221,7 +1215,7 @@ impl Pallet { { range .into_iter() - .map(|i| (i, Self::referendum_info(i))) + .map(|i| (i, ReferendumInfoOf::::get(i))) .filter_map(|(i, maybe_info)| match maybe_info { Some(ReferendumInfo::Ongoing(status)) => Some((i, status)), _ => None, @@ -1238,8 +1232,8 @@ impl Pallet { threshold: VoteThreshold, delay: BlockNumberFor, ) -> ReferendumIndex { - >::inject_referendum( - >::block_number().saturating_add(T::VotingPeriod::get()), + Pallet::::inject_referendum( + frame_system::Pallet::::block_number().saturating_add(T::VotingPeriod::get()), proposal, threshold, delay, @@ -1529,12 +1523,12 @@ impl Pallet { threshold: VoteThreshold, delay: BlockNumberFor, ) -> ReferendumIndex { - let ref_index = Self::referendum_count(); + let ref_index = ReferendumCount::::get(); ReferendumCount::::put(ref_index + 1); let status = ReferendumStatus { end, proposal, threshold, delay, tally: Default::default() }; let item = ReferendumInfo::Ongoing(status); - >::insert(ref_index, item); + ReferendumInfoOf::::insert(ref_index, item); Self::deposit_event(Event::::Started { ref_index, threshold }); ref_index } @@ -1551,7 +1545,7 @@ impl Pallet { /// Table the waiting external proposal for a vote, if there is one. fn launch_external(now: BlockNumberFor) -> DispatchResult { - if let Some((proposal, threshold)) = >::take() { + if let Some((proposal, threshold)) = NextExternal::::take() { LastTabledWasExternal::::put(true); Self::deposit_event(Event::::ExternalTabled); let ref_index = Self::inject_referendum( @@ -1569,15 +1563,15 @@ impl Pallet { /// Table the waiting public proposal with the highest backing for a vote. fn launch_public(now: BlockNumberFor) -> DispatchResult { - let mut public_props = Self::public_props(); + let mut public_props = PublicProps::::get(); if let Some((winner_index, _)) = public_props.iter().enumerate().max_by_key( // defensive only: All current public proposals have an amount locked |x| Self::backing_for((x.1).0).defensive_unwrap_or_else(Zero::zero), ) { let (prop_index, proposal, _) = public_props.swap_remove(winner_index); - >::put(public_props); + PublicProps::::put(public_props); - if let Some((depositors, deposit)) = >::take(prop_index) { + if let Some((depositors, deposit)) = DepositOf::::take(prop_index) { // refund depositors for d in depositors.iter() { T::Currency::unreserve(d, deposit); @@ -1642,8 +1636,8 @@ impl Pallet { let max_block_weight = T::BlockWeights::get().max_block; let mut weight = Weight::zero(); - let next = Self::lowest_unbaked(); - let last = Self::referendum_count(); + let next = LowestUnbaked::::get(); + let last = ReferendumCount::::get(); let r = last.saturating_sub(next); // pick out another public referendum if it's time. @@ -1674,9 +1668,9 @@ impl Pallet { // * We shouldn't iterate more than `LaunchPeriod/VotingPeriod + 1` times because the number // of unbaked referendum is bounded by this number. In case those number have changed in a // runtime upgrade the formula should be adjusted but the bound should still be sensible. - >::mutate(|ref_index| { + LowestUnbaked::::mutate(|ref_index| { while *ref_index < last && - Self::referendum_info(*ref_index) + ReferendumInfoOf::::get(*ref_index) .map_or(true, |info| matches!(info, ReferendumInfo::Finished { .. })) { *ref_index += 1 @@ -1692,7 +1686,7 @@ impl Pallet { fn len_of_deposit_of(proposal: PropIndex) -> Option { // DepositOf first tuple element is a vec, decoding its len is equivalent to decode a // `Compact`. - decode_compact_u32_at(&>::hashed_key_for(proposal)) + decode_compact_u32_at(&DepositOf::::hashed_key_for(proposal)) } /// Return a proposal of an index. diff --git a/substrate/frame/democracy/src/migrations/v1.rs b/substrate/frame/democracy/src/migrations/v1.rs index 5e423b9ab6eff7d2a96f94416bdd425827869fba..47f8df017f1e18d19289477936dc2a3c380f8e2c 100644 --- a/substrate/frame/democracy/src/migrations/v1.rs +++ b/substrate/frame/democracy/src/migrations/v1.rs @@ -108,7 +108,7 @@ pub mod v1 { .collect::>(); let bounded = BoundedVec::<_, T::MaxProposals>::truncate_from(props.clone()); PublicProps::::put(bounded); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); if props.len() as u32 > T::MaxProposals::get() { log::error!( @@ -126,7 +126,7 @@ pub mod v1 { StorageVersion::new(1).put::>(); - weight.saturating_add(T::DbWeight::get().reads_writes(1, 2)) + weight.saturating_add(T::DbWeight::get().reads_writes(1, 3)) } #[cfg(feature = "try-runtime")] diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index e2946ba98156ad3480f85ae4e86ba4a2036ff59c..9303c0da504f366288f6f06cb33c54abbd125321 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -194,7 +194,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { #[test] fn params_should_work() { new_test_ext().execute_with(|| { - assert_eq!(Democracy::referendum_count(), 0); + assert_eq!(ReferendumCount::::get(), 0); assert_eq!(Balances::free_balance(42), 0); assert_eq!(Balances::total_issuance(), 210); }); diff --git a/substrate/frame/democracy/src/tests/cancellation.rs b/substrate/frame/democracy/src/tests/cancellation.rs index b4c42f9c79053ad6db1641e7e431dc4be7661e9f..eeb1df301db8ffda60e349bb7dd2fa7c673b4be4 100644 --- a/substrate/frame/democracy/src/tests/cancellation.rs +++ b/substrate/frame/democracy/src/tests/cancellation.rs @@ -30,14 +30,14 @@ fn cancel_referendum_should_work() { ); assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1))); assert_ok!(Democracy::cancel_referendum(RuntimeOrigin::root(), r.into())); - assert_eq!(Democracy::lowest_unbaked(), 0); + assert_eq!(LowestUnbaked::::get(), 0); next_block(); next_block(); - assert_eq!(Democracy::lowest_unbaked(), 1); - assert_eq!(Democracy::lowest_unbaked(), Democracy::referendum_count()); + assert_eq!(LowestUnbaked::::get(), 1); + assert_eq!(LowestUnbaked::::get(), ReferendumCount::::get()); assert_eq!(Balances::free_balance(42), 0); }); } @@ -56,7 +56,7 @@ fn emergency_cancel_should_work() { assert_noop!(Democracy::emergency_cancel(RuntimeOrigin::signed(3), r), BadOrigin); assert_ok!(Democracy::emergency_cancel(RuntimeOrigin::signed(4), r)); - assert!(Democracy::referendum_info(r).is_none()); + assert!(ReferendumInfoOf::::get(r).is_none()); // some time later... diff --git a/substrate/frame/democracy/src/tests/external_proposing.rs b/substrate/frame/democracy/src/tests/external_proposing.rs index 08b497ab4b90e6ce458b7462c521b0d9d6d78640..78ef2904e5b6c29bf78f594ac3ffaff5c00c1c2a 100644 --- a/substrate/frame/democracy/src/tests/external_proposing.rs +++ b/substrate/frame/democracy/src/tests/external_proposing.rs @@ -24,12 +24,12 @@ fn veto_external_works() { new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),)); - assert!(>::exists()); + assert!(NextExternal::::exists()); let h = set_balance_proposal(2).hash(); assert_ok!(Democracy::veto_external(RuntimeOrigin::signed(3), h)); // cancelled. - assert!(!>::exists()); + assert!(!NextExternal::::exists()); // fails - same proposal can't be resubmitted. assert_noop!( Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),), @@ -46,7 +46,7 @@ fn veto_external_works() { fast_forward_to(2); // works; as we're out of the cooloff period. assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),)); - assert!(>::exists()); + assert!(NextExternal::::exists()); // 3 can't veto the same thing twice. assert_noop!( @@ -57,7 +57,7 @@ fn veto_external_works() { // 4 vetoes. assert_ok!(Democracy::veto_external(RuntimeOrigin::signed(4), h)); // cancelled again. - assert!(!>::exists()); + assert!(!NextExternal::::exists()); fast_forward_to(3); // same proposal fails as we're still in cooloff diff --git a/substrate/frame/democracy/src/tests/fast_tracking.rs b/substrate/frame/democracy/src/tests/fast_tracking.rs index 85e7792a4c2edf3728f2b0215fe94fc0dc3efdbb..89dce1dffe13eb5f950ee874d0366af3983f24a9 100644 --- a/substrate/frame/democracy/src/tests/fast_tracking.rs +++ b/substrate/frame/democracy/src/tests/fast_tracking.rs @@ -33,13 +33,13 @@ fn fast_track_referendum_works() { set_balance_proposal(2) )); let hash = note_preimage(1); - assert!(>::get(MetadataOwner::External).is_none()); + assert!(MetadataOf::::get(MetadataOwner::External).is_none()); assert_ok!(Democracy::set_metadata( RuntimeOrigin::signed(3), MetadataOwner::External, Some(hash), ),); - assert!(>::get(MetadataOwner::External).is_some()); + assert!(MetadataOf::::get(MetadataOwner::External).is_some()); assert_noop!(Democracy::fast_track(RuntimeOrigin::signed(1), h, 3, 2), BadOrigin); assert_ok!(Democracy::fast_track(RuntimeOrigin::signed(5), h, 2, 0)); assert_eq!( @@ -53,8 +53,8 @@ fn fast_track_referendum_works() { }) ); // metadata reset from the external proposal to the referendum. - assert!(>::get(MetadataOwner::External).is_none()); - assert!(>::get(MetadataOwner::Referendum(0)).is_some()); + assert!(MetadataOf::::get(MetadataOwner::External).is_none()); + assert!(MetadataOf::::get(MetadataOwner::Referendum(0)).is_some()); }); } diff --git a/substrate/frame/democracy/src/tests/metadata.rs b/substrate/frame/democracy/src/tests/metadata.rs index 1b6d66a8bc4486c555a5f0e1241f76280b33eeb7..341f14e5586bf9e0e3191eb8dbf87f1515739636 100644 --- a/substrate/frame/democracy/src/tests/metadata.rs +++ b/substrate/frame/democracy/src/tests/metadata.rs @@ -33,7 +33,7 @@ fn set_external_metadata_works() { ); // create an external proposal. assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2))); - assert!(>::exists()); + assert!(NextExternal::::exists()); // fails to set metadata with non external origin. assert_noop!( Democracy::set_metadata(RuntimeOrigin::signed(1), owner.clone(), Some(invalid_hash)), @@ -61,7 +61,7 @@ fn clear_metadata_works() { let owner = MetadataOwner::External; // create an external proposal. assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2))); - assert!(>::exists()); + assert!(NextExternal::::exists()); // set metadata. let hash = note_preimage(1); assert_ok!(Democracy::set_metadata(RuntimeOrigin::signed(2), owner.clone(), Some(hash))); @@ -87,7 +87,7 @@ fn set_proposal_metadata_works() { // create an external proposal. assert_ok!(propose_set_balance(1, 2, 5)); // metadata owner is a public proposal. - let owner = MetadataOwner::Proposal(Democracy::public_prop_count() - 1); + let owner = MetadataOwner::Proposal(PublicPropCount::::get() - 1); // fails to set non-existing preimage. assert_noop!( Democracy::set_metadata(RuntimeOrigin::signed(1), owner.clone(), Some(invalid_hash)), @@ -115,7 +115,7 @@ fn clear_proposal_metadata_works() { // create an external proposal. assert_ok!(propose_set_balance(1, 2, 5)); // metadata owner is a public proposal. - let owner = MetadataOwner::Proposal(Democracy::public_prop_count() - 1); + let owner = MetadataOwner::Proposal(PublicPropCount::::get() - 1); // set metadata. let hash = note_preimage(1); assert_ok!(Democracy::set_metadata(RuntimeOrigin::signed(1), owner.clone(), Some(hash))); diff --git a/substrate/frame/democracy/src/tests/public_proposals.rs b/substrate/frame/democracy/src/tests/public_proposals.rs index 69a2d3e25686f6a17337ff78c81d3c69a13ac345..01f47947f8e50e9be8fbcb9072b861fdf84f923e 100644 --- a/substrate/frame/democracy/src/tests/public_proposals.rs +++ b/substrate/frame/democracy/src/tests/public_proposals.rs @@ -97,10 +97,10 @@ fn cancel_proposal_should_work() { MetadataOwner::Proposal(0), Some(hash) )); - assert!(>::get(MetadataOwner::Proposal(0)).is_some()); + assert!(MetadataOf::::get(MetadataOwner::Proposal(0)).is_some()); assert_ok!(Democracy::cancel_proposal(RuntimeOrigin::root(), 0)); // metadata cleared, preimage unrequested. - assert!(>::get(MetadataOwner::Proposal(0)).is_none()); + assert!(MetadataOf::::get(MetadataOwner::Proposal(0)).is_none()); System::assert_has_event(crate::Event::ProposalCanceled { prop_index: 0 }.into()); System::assert_last_event( crate::Event::MetadataCleared { owner: MetadataOwner::Proposal(0), hash }.into(), diff --git a/substrate/frame/democracy/src/tests/scheduling.rs b/substrate/frame/democracy/src/tests/scheduling.rs index fdbc8fdb34947ae1454355ebd4afd6493e7de992..43f51628aaf5e6929434185787ad481851628bd7 100644 --- a/substrate/frame/democracy/src/tests/scheduling.rs +++ b/substrate/frame/democracy/src/tests/scheduling.rs @@ -30,10 +30,10 @@ fn simple_passing_should_work() { ); assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1))); assert_eq!(tally(r), Tally { ayes: 1, nays: 0, turnout: 10 }); - assert_eq!(Democracy::lowest_unbaked(), 0); + assert_eq!(LowestUnbaked::::get(), 0); next_block(); next_block(); - assert_eq!(Democracy::lowest_unbaked(), 1); + assert_eq!(LowestUnbaked::::get(), 1); assert_eq!(Balances::free_balance(42), 2); }); } @@ -140,16 +140,16 @@ fn lowest_unbaked_should_be_sensible() { assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r2, aye(1))); // r3 is canceled assert_ok!(Democracy::cancel_referendum(RuntimeOrigin::root(), r3.into())); - assert_eq!(Democracy::lowest_unbaked(), 0); + assert_eq!(LowestUnbaked::::get(), 0); next_block(); // r2 ends with approval - assert_eq!(Democracy::lowest_unbaked(), 0); + assert_eq!(LowestUnbaked::::get(), 0); next_block(); // r1 ends with approval - assert_eq!(Democracy::lowest_unbaked(), 3); - assert_eq!(Democracy::lowest_unbaked(), Democracy::referendum_count()); + assert_eq!(LowestUnbaked::::get(), 3); + assert_eq!(LowestUnbaked::::get(), ReferendumCount::::get()); // r2 is executed assert_eq!(Balances::free_balance(42), 2); diff --git a/substrate/frame/democracy/src/tests/voting.rs b/substrate/frame/democracy/src/tests/voting.rs index f096b633ee6d4a2b226dc5be0421523edb453de5..61b80cc97fed6ad458a1fcda01efe5bd89799ad4 100644 --- a/substrate/frame/democracy/src/tests/voting.rs +++ b/substrate/frame/democracy/src/tests/voting.rs @@ -65,13 +65,13 @@ fn single_proposal_should_work() { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); let r = 0; - assert!(Democracy::referendum_info(r).is_none()); + assert!(ReferendumInfoOf::::get(r).is_none()); // start of 2 => next referendum scheduled. fast_forward_to(2); assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1))); - assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(ReferendumCount::::get(), 1); assert_eq!( Democracy::referendum_status(0), Ok(ReferendumStatus { diff --git a/substrate/frame/election-provider-multi-phase/Cargo.toml b/substrate/frame/election-provider-multi-phase/Cargo.toml index 2074b51f50f475f077f814593da74b31b5dba6e0..43e3e7079d2fa78aa1e3515b41df87446ac5b370 100644 --- a/substrate/frame/election-provider-multi-phase/Cargo.toml +++ b/substrate/frame/election-provider-multi-phase/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/Cargo.toml b/substrate/frame/election-provider-multi-phase/test-staking-e2e/Cargo.toml index 25c280921f8c7c8d3660c52555ae5e67093c1a9b..fc696e04d689f706a4afa4459ea2b8f885ca22d4 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/Cargo.toml +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dev-dependencies] parking_lot = "0.12.1" -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } scale-info = { version = "2.11.1", features = ["derive"] } log = { workspace = true } diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs index c00bb66ea13044f8b11aa781e30896e03225aea8..2b1f1335c6fe888c3ff756b00327b74d5ba9f279 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs @@ -322,7 +322,7 @@ fn automatic_unbonding_pools() { let init_free_balance_2 = Balances::free_balance(2); let init_free_balance_3 = Balances::free_balance(3); - let pool_bonded_account = Pools::create_bonded_account(1); + let pool_bonded_account = Pools::generate_bonded_account(1); // creates a pool with 5 bonded, owned by 1. assert_ok!(Pools::create(RuntimeOrigin::signed(1), 5, 1, 1, 1)); diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 8f1775a7e5951ad1c9271f486a782b18fe5da900..e5987ec33f06c3263edca88cf0fe7fbdda4ddcf5 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -90,7 +90,6 @@ pub(crate) type Moment = u32; impl frame_system::Config for Runtime { type Block = Block; type AccountData = pallet_balances::AccountData; - type BlockHashCount = ConstU32<10>; } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -274,7 +273,7 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = sp_runtime::FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = Staking; + type StakeAdapter = pallet_nomination_pools::adapter::TransferStake; type PostUnbondingPoolsWindow = ConstU32<2>; type PalletId = PoolsPalletId; type MaxMetadataLen = ConstU32<256>; diff --git a/substrate/frame/election-provider-support/Cargo.toml b/substrate/frame/election-provider-support/Cargo.toml index 0d9748ee34e56fa5d43f0e238d2d69eda548eaec..1c63f90720f7b010fb584dc44f2e84ad78c61021 100644 --- a/substrate/frame/election-provider-support/Cargo.toml +++ b/substrate/frame/election-provider-support/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-election-provider-solution-type = { path = "solution-type" } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/election-provider-support/benchmarking/Cargo.toml b/substrate/frame/election-provider-support/benchmarking/Cargo.toml index 6e13f17bec1bbf237914df6baffdc2ede46c05f9..c2e644cfefab99145b839bf1c57917369a5f5cb2 100644 --- a/substrate/frame/election-provider-support/benchmarking/Cargo.toml +++ b/substrate/frame/election-provider-support/benchmarking/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/election-provider-support/solution-type/Cargo.toml b/substrate/frame/election-provider-support/solution-type/Cargo.toml index 09c6a492dd0d6ba498111fc2c8926212e7b35fc2..3f8893dad6f2094ae75dec2e6e9de00d0b091495 100644 --- a/substrate/frame/election-provider-support/solution-type/Cargo.toml +++ b/substrate/frame/election-provider-support/solution-type/Cargo.toml @@ -24,7 +24,7 @@ proc-macro2 = "1.0.56" proc-macro-crate = "3.0.0" [dev-dependencies] -parity-scale-codec = "3.6.1" +parity-scale-codec = "3.6.12" scale-info = "2.11.1" sp-arithmetic = { path = "../../../primitives/arithmetic" } # used by generate_solution_type: diff --git a/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml b/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml index 1fb9e2387ed8de1be004faf876315c21eeac9696..98da507384fd956e21a01cf075556bbe0b6b916b 100644 --- a/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml +++ b/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml @@ -20,7 +20,7 @@ clap = { version = "4.5.3", features = ["derive"] } honggfuzz = "0.5" rand = { version = "0.8", features = ["small_rng", "std"] } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-election-provider-solution-type = { path = ".." } frame-election-provider-support = { path = "../.." } diff --git a/substrate/frame/election-provider-support/solution-type/src/lib.rs b/substrate/frame/election-provider-support/solution-type/src/lib.rs index 80773f6fb476859746677711401d70bd955b8ad7..1a88f0cf835fbe813da9d990ef4fd98651096614 100644 --- a/substrate/frame/election-provider-support/solution-type/src/lib.rs +++ b/substrate/frame/election-provider-support/solution-type/src/lib.rs @@ -263,7 +263,16 @@ fn imports() -> Result { use _feps::private as _fepsp; )) }, - Err(e) => Err(syn::Error::new(Span::call_site(), e)), + Err(e) => match crate_name("polkadot-sdk") { + Ok(FoundCrate::Name(polkadot_sdk)) => { + let ident = syn::Ident::new(&polkadot_sdk, Span::call_site()); + Ok(quote!( + use #ident::frame_election_provider_support as _feps; + use _feps::private as _fepsp; + )) + }, + _ => Err(syn::Error::new(Span::call_site(), e)), + }, } } diff --git a/substrate/frame/elections-phragmen/Cargo.toml b/substrate/frame/elections-phragmen/Cargo.toml index 81dc48476a065b60e41ce6f703317b77ae75b0fe..dbcb740518b1379f54cd4265973b445f53109b7b 100644 --- a/substrate/frame/elections-phragmen/Cargo.toml +++ b/substrate/frame/elections-phragmen/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } log = { workspace = true } diff --git a/substrate/frame/examples/basic/Cargo.toml b/substrate/frame/examples/basic/Cargo.toml index 43b37c6beba2c6c2545c4b6bc5191e40009065fa..ba9f9eca27d79c854dd67a8d81130062f3d1f70d 100644 --- a/substrate/frame/examples/basic/Cargo.toml +++ b/substrate/frame/examples/basic/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index de37bcf75569575b5eb42336424af2e3a917bf1d..d351b27eecde3c506e17339f9f7300d522fcc87f 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -60,7 +60,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/examples/default-config/Cargo.toml b/substrate/frame/examples/default-config/Cargo.toml index 2aa062ee6c1a0765f9e20d955d1f312c06157966..0ad5b56cb6faa473d337f54fe7eaedaf31a70d9d 100644 --- a/substrate/frame/examples/default-config/Cargo.toml +++ b/substrate/frame/examples/default-config/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../support", default-features = false } diff --git a/substrate/frame/examples/dev-mode/Cargo.toml b/substrate/frame/examples/dev-mode/Cargo.toml index 71b97796ecddf89275c3594362d9ece122b7387f..d7570f570946f1df05665ad8804e62ad9c18030a 100644 --- a/substrate/frame/examples/dev-mode/Cargo.toml +++ b/substrate/frame/examples/dev-mode/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../support", default-features = false } diff --git a/substrate/frame/examples/dev-mode/src/tests.rs b/substrate/frame/examples/dev-mode/src/tests.rs index 1c79b5f5fa6050758f5158bdcbede75e914eaf97..e8a18ec13fe912497e32a821e4f10d75582609e1 100644 --- a/substrate/frame/examples/dev-mode/src/tests.rs +++ b/substrate/frame/examples/dev-mode/src/tests.rs @@ -54,7 +54,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/examples/frame-crate/Cargo.toml b/substrate/frame/examples/frame-crate/Cargo.toml index 48cb25f90949a9401a8261999c0332d16d497d04..29984bab3e0ffc5ac881eb086d91820c01e7d504 100644 --- a/substrate/frame/examples/frame-crate/Cargo.toml +++ b/substrate/frame/examples/frame-crate/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame = { package = "polkadot-sdk-frame", path = "../..", default-features = false, features = ["experimental", "runtime"] } diff --git a/substrate/frame/examples/kitchensink/Cargo.toml b/substrate/frame/examples/kitchensink/Cargo.toml index d8311897c6e1158f8a94520bfd1c6f2712aecbbc..db3e22daa01bd044cae876aabeac25543e814dcb 100644 --- a/substrate/frame/examples/kitchensink/Cargo.toml +++ b/substrate/frame/examples/kitchensink/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/examples/multi-block-migrations/Cargo.toml b/substrate/frame/examples/multi-block-migrations/Cargo.toml index 28eca8577154e85c7fbb0d22fca8aefb3c7d9237..61bb2bc61b4e3758fc47c413f35ac5420bbfb4ef 100644 --- a/substrate/frame/examples/multi-block-migrations/Cargo.toml +++ b/substrate/frame/examples/multi-block-migrations/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } pallet-migrations = { path = "../../migrations", default-features = false } frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } diff --git a/substrate/frame/examples/offchain-worker/Cargo.toml b/substrate/frame/examples/offchain-worker/Cargo.toml index 9363f7533526650e69bcc791e99d37fac17155a7..23ce79c34402da91cea1f1e02ae7ebd90dc6e5d3 100644 --- a/substrate/frame/examples/offchain-worker/Cargo.toml +++ b/substrate/frame/examples/offchain-worker/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } lite-json = { version = "0.2.0", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/examples/offchain-worker/src/tests.rs b/substrate/frame/examples/offchain-worker/src/tests.rs index 3525b3b67edf1569f00600e1e210e426c5f858dc..e2c57a8c1e1abcb855a97db9590edc19c7bf881b 100644 --- a/substrate/frame/examples/offchain-worker/src/tests.rs +++ b/substrate/frame/examples/offchain-worker/src/tests.rs @@ -61,7 +61,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/examples/single-block-migrations/Cargo.toml b/substrate/frame/examples/single-block-migrations/Cargo.toml index b1d560a85f3ff59de2ab6560223f7b7657f2b27a..080500f629671837316e724b6825493c3fcb4b67 100644 --- a/substrate/frame/examples/single-block-migrations/Cargo.toml +++ b/substrate/frame/examples/single-block-migrations/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] docify = "0.2.8" log = { version = "0.4.21", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../../support", default-features = false } frame-executive = { path = "../../executive", default-features = false } diff --git a/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs b/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs index 18ef4e72cc4f5ce938abf03d5eaea3039ec0b030..7b543d72c98404d84ba8f68b3d864176c4182fb9 100644 --- a/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs +++ b/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs @@ -67,10 +67,10 @@ impl UncheckedOnRuntimeUpgrade for InnerMigrateV0ToV1 { // Write the new value to storage let new = crate::CurrentAndPreviousValue { current: old_value, previous: None }; crate::Value::::put(new); - // One read for the old value, one write for the new value - T::DbWeight::get().reads_writes(1, 1) + // One read + write for taking the old value, and one write for setting the new value + T::DbWeight::get().reads_writes(1, 2) } else { - // One read for trying to access the old value + // No writes since there was no old value, just one read for checking T::DbWeight::get().reads(1) } } @@ -184,7 +184,7 @@ mod test { // value. assert_eq!( weight, - ::DbWeight::get().reads_writes(1, 1) + ::DbWeight::get().reads_writes(1, 2) ); // After the migration, the new value should be set as the `current` value. diff --git a/substrate/frame/examples/split/Cargo.toml b/substrate/frame/examples/split/Cargo.toml index 1ef3521e06063cf15679e248c6b46ae27a14e946..6cb4d7ddd6c06951b749d796746a7f5a63ee343f 100644 --- a/substrate/frame/examples/split/Cargo.toml +++ b/substrate/frame/examples/split/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/examples/tasks/Cargo.toml b/substrate/frame/examples/tasks/Cargo.toml index 3f59d57ea0f202729f11ac549daa828424343671..95246ef3f6643aafe215bb4bacf0e2e2598149ae 100644 --- a/substrate/frame/examples/tasks/Cargo.toml +++ b/substrate/frame/examples/tasks/Cargo.toml @@ -14,7 +14,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/executive/Cargo.toml b/substrate/frame/executive/Cargo.toml index 95de7c3f3d1f086a39a8f12af6c8a851eff3fa4d..4cce0fa9f9504ae48ca1929f87311896b81ca5cf 100644 --- a/substrate/frame/executive/Cargo.toml +++ b/substrate/frame/executive/Cargo.toml @@ -16,8 +16,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -aquamarine = "0.3.2" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +aquamarine = "0.5.0" +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } log = { workspace = true } @@ -32,7 +32,7 @@ sp-std = { path = "../../primitives/std", default-features = false } sp-tracing = { path = "../../primitives/tracing", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" pallet-balances = { path = "../balances" } pallet-transaction-payment = { path = "../transaction-payment" } sp-core = { path = "../../primitives/core" } diff --git a/substrate/frame/fast-unstake/Cargo.toml b/substrate/frame/fast-unstake/Cargo.toml index f05f22f764164ce15704a9200c78e65b2867c908..5b7121e2eae3788fdf37c0467871f0233dd62393 100644 --- a/substrate/frame/fast-unstake/Cargo.toml +++ b/substrate/frame/fast-unstake/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/fast-unstake/src/lib.rs b/substrate/frame/fast-unstake/src/lib.rs index 8ba306201310e220afdb4cf8cb0d92a043bcafa6..f31c9c640260b2bccad684ce5aa23ef384847d43 100644 --- a/substrate/frame/fast-unstake/src/lib.rs +++ b/substrate/frame/fast-unstake/src/lib.rs @@ -141,7 +141,7 @@ macro_rules! log { ($level:tt, $patter:expr $(, $values:expr)* $(,)?) => { log::$level!( target: crate::LOG_TARGET, - concat!("[{:?}] 💨 ", $patter), >::block_number() $(, $values)* + concat!("[{:?}] 💨 ", $patter), frame_system::Pallet::::block_number() $(, $values)* ) }; } @@ -227,7 +227,6 @@ pub mod pallet { /// checked. The checking is represented by updating [`UnstakeRequest::checked`], which is /// stored in [`Head`]. #[pallet::storage] - #[pallet::getter(fn eras_to_check_per_block)] pub type ErasToCheckPerBlock = StorageValue<_, u32, ValueQuery>; #[pallet::event] @@ -332,7 +331,7 @@ pub mod pallet { pub fn register_fast_unstake(origin: OriginFor) -> DispatchResult { let ctrl = ensure_signed(origin)?; - ensure!(ErasToCheckPerBlock::::get() != 0, >::CallNotAllowed); + ensure!(ErasToCheckPerBlock::::get() != 0, Error::::CallNotAllowed); let stash_account = T::Staking::stash_by_ctrl(&ctrl).map_err(|_| Error::::NotController)?; ensure!(!Queue::::contains_key(&stash_account), Error::::AlreadyQueued); @@ -373,7 +372,7 @@ pub mod pallet { pub fn deregister(origin: OriginFor) -> DispatchResult { let ctrl = ensure_signed(origin)?; - ensure!(ErasToCheckPerBlock::::get() != 0, >::CallNotAllowed); + ensure!(ErasToCheckPerBlock::::get() != 0, Error::::CallNotAllowed); let stash_account = T::Staking::stash_by_ctrl(&ctrl).map_err(|_| Error::::NotController)?; diff --git a/substrate/frame/glutton/Cargo.toml b/substrate/frame/glutton/Cargo.toml index 5ce010f1c2622fbbefa053bf1bb45383e853af4c..730c4e70935c0be3cb840087011a37ca9668b317 100644 --- a/substrate/frame/glutton/Cargo.toml +++ b/substrate/frame/glutton/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] blake2 = { version = "0.10.4", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } log = { workspace = true } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/grandpa/Cargo.toml b/substrate/frame/grandpa/Cargo.toml index f4dd92129f38aeb76a1df8afd21494102eb68bd9..302ce327aed4b037432b660cf65b0c9aba5123f6 100644 --- a/substrate/frame/grandpa/Cargo.toml +++ b/substrate/frame/grandpa/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/identity/Cargo.toml b/substrate/frame/identity/Cargo.toml index 8c0052004ae3d595f3d1f0bef75d92584d3c3ff5..e0bce8a77bdc68c26a9de9b95438b8b06ff4228b 100644 --- a/substrate/frame/identity/Cargo.toml +++ b/substrate/frame/identity/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } enumflags2 = { version = "0.7.7" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/identity/src/lib.rs b/substrate/frame/identity/src/lib.rs index 4a977880b3150cf9ffa7e2b4032e258483a6d242..5a36101cc2f793c6e1f858b7e0cc2b53d4bf74b2 100644 --- a/substrate/frame/identity/src/lib.rs +++ b/substrate/frame/identity/src/lib.rs @@ -1169,7 +1169,9 @@ pub mod pallet { pub fn set_primary_username(origin: OriginFor, username: Username) -> DispatchResult { // ensure `username` maps to `origin` (i.e. has already been set by an authority). let who = ensure_signed(origin)?; - ensure!(AccountOfUsername::::contains_key(&username), Error::::NoUsername); + let account_of_username = + AccountOfUsername::::get(&username).ok_or(Error::::NoUsername)?; + ensure!(who == account_of_username, Error::::InvalidUsername); let (registration, _maybe_username) = IdentityOf::::get(&who).ok_or(Error::::NoIdentity)?; IdentityOf::::insert(&who, (registration, Some(username.clone()))); diff --git a/substrate/frame/identity/src/tests.rs b/substrate/frame/identity/src/tests.rs index 0a9464256ce3fbf7bf84d0a463b9c00ad87bef29..60579a23b91b9d51bbe850085ae97b283d83e47f 100644 --- a/substrate/frame/identity/src/tests.rs +++ b/substrate/frame/identity/src/tests.rs @@ -25,7 +25,7 @@ use crate::{ use codec::{Decode, Encode}; use frame_support::{ - assert_noop, assert_ok, derive_impl, parameter_types, + assert_err, assert_noop, assert_ok, derive_impl, parameter_types, traits::{ConstU32, ConstU64, Get, OnFinalize, OnInitialize}, BoundedVec, }; @@ -1491,6 +1491,76 @@ fn setting_primary_should_work() { }); } +#[test] +fn must_own_primary() { + new_test_ext().execute_with(|| { + // set up authority + let [authority, _] = unfunded_accounts(); + let suffix: Vec = b"test".to_vec(); + let allocation: u32 = 10; + assert_ok!(Identity::add_username_authority( + RuntimeOrigin::root(), + authority.clone(), + suffix.clone(), + allocation + )); + + // Set up first user ("pi") and a username. + let pi_public = sr25519_generate(0.into(), None); + let pi_account: AccountIdOf = MultiSigner::Sr25519(pi_public).into_account().into(); + let (pi_username, pi_to_sign) = + test_username_of(b"username314159".to_vec(), suffix.clone()); + let encoded_pi_username = Encode::encode(&pi_to_sign.to_vec()); + let pi_signature = MultiSignature::Sr25519( + sr25519_sign(0.into(), &pi_public, &encoded_pi_username).unwrap(), + ); + assert_ok!(Identity::set_username_for( + RuntimeOrigin::signed(authority.clone()), + pi_account.clone(), + pi_username.clone(), + Some(pi_signature) + )); + + // Set up second user ("e") and a username. + let e_public = sr25519_generate(1.into(), None); + let e_account: AccountIdOf = MultiSigner::Sr25519(e_public).into_account().into(); + let (e_username, e_to_sign) = test_username_of(b"username271828".to_vec(), suffix.clone()); + let encoded_e_username = Encode::encode(&e_to_sign.to_vec()); + let e_signature = MultiSignature::Sr25519( + sr25519_sign(1.into(), &e_public, &encoded_e_username).unwrap(), + ); + assert_ok!(Identity::set_username_for( + RuntimeOrigin::signed(authority.clone()), + e_account.clone(), + e_username.clone(), + Some(e_signature) + )); + + // Ensure that both users have their usernames. + assert_eq!( + AccountOfUsername::::get::<&Username>(&pi_to_sign), + Some(pi_account.clone()) + ); + assert_eq!( + AccountOfUsername::::get::<&Username>(&e_to_sign), + Some(e_account.clone()) + ); + + // Cannot set primary to a username that does not exist. + let (_, c_username) = test_username_of(b"speedoflight".to_vec(), suffix.clone()); + assert_err!( + Identity::set_primary_username(RuntimeOrigin::signed(pi_account.clone()), c_username,), + Error::::NoUsername + ); + + // Cannot take someone else's username as your primary. + assert_err!( + Identity::set_primary_username(RuntimeOrigin::signed(pi_account.clone()), e_to_sign,), + Error::::InvalidUsername + ); + }); +} + #[test] fn unaccepted_usernames_should_expire() { new_test_ext().execute_with(|| { diff --git a/substrate/frame/im-online/Cargo.toml b/substrate/frame/im-online/Cargo.toml index 46b416f0f9a8d72a12aa12f9d8eeb99aaf4c1c2a..78192a81d7b461d0c834662b8bd0e4c50ea31333 100644 --- a/substrate/frame/im-online/Cargo.toml +++ b/substrate/frame/im-online/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index cc448dc1ae10bcc80a4389348b5969042bc02caf..2aff9a0e26df5cfbd96813c741ea184c6b11a308 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -127,7 +127,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/indices/Cargo.toml b/substrate/frame/indices/Cargo.toml index 8684f347270f59b3032a0056ba25bbb133cd3a22..248bae003ed856a828ce82863ad2fadfb7f0a927 100644 --- a/substrate/frame/indices/Cargo.toml +++ b/substrate/frame/indices/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/indices/src/mock.rs b/substrate/frame/indices/src/mock.rs index 9f8bf8c3758832d203d088616b4cb5247a116805..87b8d79a7f83b0c6f20ad1b11b99fb9b8dcbe9a8 100644 --- a/substrate/frame/indices/src/mock.rs +++ b/substrate/frame/indices/src/mock.rs @@ -53,7 +53,6 @@ impl frame_system::Config for Test { type Lookup = Indices; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/insecure-randomness-collective-flip/Cargo.toml b/substrate/frame/insecure-randomness-collective-flip/Cargo.toml index f4d65d9e560a51afe6211ca2889a95eb864a42f3..c2ec14cb4bc77c5668750684ae983b41ac46e780 100644 --- a/substrate/frame/insecure-randomness-collective-flip/Cargo.toml +++ b/substrate/frame/insecure-randomness-collective-flip/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } safe-mix = { version = "1.0", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/lottery/Cargo.toml b/substrate/frame/lottery/Cargo.toml index 5f79704445f964eae544f0c8678f08f86ab85213..be59e5ec8935102bd03782f7c745775c46bacc18 100644 --- a/substrate/frame/lottery/Cargo.toml +++ b/substrate/frame/lottery/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/membership/Cargo.toml b/substrate/frame/membership/Cargo.toml index 6f67db0ae709901f30c2339c40fd6d3399b06606..9f19c40973687a41936372f6e116eb2dc8417306 100644 --- a/substrate/frame/membership/Cargo.toml +++ b/substrate/frame/membership/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/merkle-mountain-range/Cargo.toml b/substrate/frame/merkle-mountain-range/Cargo.toml index 6dc919e16505a164e84c0e5e5b6c4f299b2da955..0d73c567cf4e16babb1488d0ad6e5d43c11639d8 100644 --- a/substrate/frame/merkle-mountain-range/Cargo.toml +++ b/substrate/frame/merkle-mountain-range/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } @@ -28,9 +28,9 @@ sp-runtime = { path = "../../primitives/runtime", default-features = false } sp-std = { path = "../../primitives/std", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" env_logger = "0.11" -itertools = "0.10.3" +itertools = "0.11" [features] default = ["std"] diff --git a/substrate/frame/merkle-mountain-range/src/lib.rs b/substrate/frame/merkle-mountain-range/src/lib.rs index e2b40974579e8376723f466198d74755603285d0..a86443f2e0114120cac8b14e85de08ee183eda93 100644 --- a/substrate/frame/merkle-mountain-range/src/lib.rs +++ b/substrate/frame/merkle-mountain-range/src/lib.rs @@ -260,15 +260,15 @@ pub mod pallet { /// Stateless MMR proof verification for batch of leaves. /// -/// This function can be used to verify received MMR [primitives::Proof] (`proof`) +/// This function can be used to verify received MMR [primitives::LeafProof] (`proof`) /// for given leaves set (`leaves`) against a known MMR root hash (`root`). /// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the -/// [primitives::Proof]. +/// [primitives::LeafProof]. pub fn verify_leaves_proof( root: H::Output, leaves: Vec>, - proof: primitives::Proof, + proof: primitives::LeafProof, ) -> Result<(), primitives::Error> where H: traits::Hash, @@ -342,7 +342,7 @@ impl, I: 'static> Pallet { pub fn generate_proof( block_numbers: Vec>, best_known_block_number: Option>, - ) -> Result<(Vec>, primitives::Proof>), primitives::Error> { + ) -> Result<(Vec>, primitives::LeafProof>), primitives::Error> { // check whether best_known_block_number provided, else use current best block let best_known_block_number = best_known_block_number.unwrap_or_else(|| >::block_number()); @@ -362,11 +362,6 @@ impl, I: 'static> Pallet { mmr.generate_proof(leaf_indices) } - /// Return the on-chain MMR root hash. - pub fn mmr_root() -> HashOf { - RootHash::::get() - } - /// Verify MMR proof for given `leaves`. /// /// This method is safe to use within the runtime code. @@ -375,7 +370,7 @@ impl, I: 'static> Pallet { /// or the proof is invalid. pub fn verify_leaves( leaves: Vec>, - proof: primitives::Proof>, + proof: primitives::LeafProof>, ) -> Result<(), primitives::Error> { if proof.leaf_count > NumberOfLeaves::::get() || proof.leaf_count == 0 || @@ -393,4 +388,37 @@ impl, I: 'static> Pallet { Err(primitives::Error::Verify.log_debug("The proof is incorrect.")) } } + + pub fn generate_ancestry_proof( + prev_block_number: BlockNumberFor, + best_known_block_number: Option>, + ) -> Result>, Error> { + // check whether best_known_block_number provided, else use current best block + let best_known_block_number = + best_known_block_number.unwrap_or_else(|| >::block_number()); + + let leaf_count = Self::block_num_to_leaf_index(best_known_block_number)?.saturating_add(1); + let prev_leaf_count = Self::block_num_to_leaf_index(prev_block_number)?.saturating_add(1); + + let mmr: ModuleMmr = mmr::Mmr::new(leaf_count); + mmr.generate_ancestry_proof(prev_leaf_count) + } + + pub fn verify_ancestry_proof( + ancestry_proof: primitives::AncestryProof>, + ) -> Result<(), Error> { + let mmr: ModuleMmr = + mmr::Mmr::new(ancestry_proof.leaf_count); + let is_valid = mmr.verify_ancestry_proof(ancestry_proof)?; + if is_valid { + Ok(()) + } else { + Err(Error::Verify.log_debug("The ancestry proof is incorrect.")) + } + } + + /// Return the on-chain MMR root hash. + pub fn mmr_root() -> HashOf { + RootHash::::get() + } } diff --git a/substrate/frame/merkle-mountain-range/src/mmr/mmr.rs b/substrate/frame/merkle-mountain-range/src/mmr/mmr.rs index aeb3e7ea66414a062a238da3f84795b53da4f68b..5efc172d1e93f1d7a56e3b36da20f93c6e1df1f9 100644 --- a/substrate/frame/merkle-mountain-range/src/mmr/mmr.rs +++ b/substrate/frame/merkle-mountain-range/src/mmr/mmr.rs @@ -23,17 +23,17 @@ use crate::{ primitives::{self, Error, NodeIndex}, Config, HashOf, HashingOf, }; -use sp_mmr_primitives::{mmr_lib, utils::NodesUtils}; +use sp_mmr_primitives::{mmr_lib, mmr_lib::MMRStoreReadOps, utils::NodesUtils, LeafIndex}; use sp_std::prelude::*; /// Stateless verification of the proof for a batch of leaves. /// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the -/// [primitives::Proof] +/// [primitives::LeafProof] pub fn verify_leaves_proof( root: H::Output, leaves: Vec>, - proof: primitives::Proof, + proof: primitives::LeafProof, ) -> Result where H: sp_runtime::traits::Hash, @@ -69,7 +69,8 @@ where T: Config, I: 'static, L: primitives::FullLeaf, - Storage: mmr_lib::MMRStore>, + Storage: + MMRStoreReadOps> + mmr_lib::MMRStoreWriteOps>, { mmr: mmr_lib::MMR, Hasher, L>, Storage>, leaves: NodeIndex, @@ -80,7 +81,8 @@ where T: Config, I: 'static, L: primitives::FullLeaf, - Storage: mmr_lib::MMRStore>, + Storage: + MMRStoreReadOps> + mmr_lib::MMRStoreWriteOps>, { /// Create a pointer to an existing MMR with given number of leaves. pub fn new(leaves: NodeIndex) -> Self { @@ -91,11 +93,11 @@ where /// Verify proof for a set of leaves. /// Note, the leaves should be sorted such that corresponding leaves and leaf indices have /// the same position in both the `leaves` vector and the `leaf_indices` vector contained in the - /// [primitives::Proof] + /// [primitives::LeafProof] pub fn verify_leaves_proof( &self, leaves: Vec, - proof: primitives::Proof>, + proof: primitives::LeafProof>, ) -> Result { let p = mmr_lib::MerkleProof::, Hasher, L>>::new( self.mmr.mmr_size(), @@ -117,6 +119,44 @@ where .map_err(|e| Error::Verify.log_debug(e)) } + pub fn verify_ancestry_proof( + &self, + ancestry_proof: primitives::AncestryProof>, + ) -> Result { + let prev_peaks_proof = + mmr_lib::NodeMerkleProof::, Hasher, L>>::new( + self.mmr.mmr_size(), + ancestry_proof + .items + .into_iter() + .map(|(index, hash)| (index, Node::Hash(hash))) + .collect(), + ); + + let raw_ancestry_proof = mmr_lib::AncestryProof::< + NodeOf, + Hasher, L>, + > { + prev_peaks: ancestry_proof + .prev_peaks + .into_iter() + .map(|hash| Node::Hash(hash)) + .collect(), + prev_size: mmr_lib::helper::leaf_index_to_mmr_size(ancestry_proof.prev_leaf_count - 1), + proof: prev_peaks_proof, + }; + + let prev_root = mmr_lib::ancestry_proof::bagging_peaks_hashes::< + NodeOf, + Hasher, L>, + >(raw_ancestry_proof.prev_peaks.clone()) + .map_err(|e| Error::Verify.log_debug(e))?; + let root = self.mmr.get_root().map_err(|e| Error::GetRoot.log_error(e))?; + raw_ancestry_proof + .verify_ancestor(root, prev_root) + .map_err(|e| Error::Verify.log_debug(e)) + } + /// Return the internal size of the MMR (number of nodes). #[cfg(test)] pub fn size(&self) -> NodeIndex { @@ -145,7 +185,7 @@ where /// Commit the changes to underlying storage, return current number of leaves and /// calculate the new MMR's root hash. - pub fn finalize(self) -> Result<(NodeIndex, HashOf), Error> { + pub fn finalize(mut self) -> Result<(NodeIndex, HashOf), Error> { let root = self.mmr.get_root().map_err(|e| Error::GetRoot.log_error(e))?; self.mmr.commit().map_err(|e| Error::Commit.log_error(e))?; Ok((self.leaves, root.hash())) @@ -166,7 +206,7 @@ where pub fn generate_proof( &self, leaf_indices: Vec, - ) -> Result<(Vec, primitives::Proof>), Error> { + ) -> Result<(Vec, primitives::LeafProof>), Error> { let positions = leaf_indices .iter() .map(|index| mmr_lib::leaf_index_to_pos(*index)) @@ -174,7 +214,7 @@ where let store = >::default(); let leaves = positions .iter() - .map(|pos| match mmr_lib::MMRStore::get_elem(&store, *pos) { + .map(|pos| match store.get_elem(*pos) { Ok(Some(Node::Data(leaf))) => Ok(leaf), e => Err(Error::LeafNotFound.log_debug(e)), }) @@ -184,11 +224,34 @@ where self.mmr .gen_proof(positions) .map_err(|e| Error::GenerateProof.log_error(e)) - .map(|p| primitives::Proof { + .map(|p| primitives::LeafProof { leaf_indices, leaf_count, items: p.proof_items().iter().map(|x| x.hash()).collect(), }) .map(|p| (leaves, p)) } + + pub fn generate_ancestry_proof( + &self, + prev_leaf_count: LeafIndex, + ) -> Result>, Error> { + let prev_mmr_size = NodesUtils::new(prev_leaf_count).size(); + let raw_ancestry_proof = self + .mmr + .gen_ancestry_proof(prev_mmr_size) + .map_err(|e| Error::GenerateProof.log_error(e))?; + + Ok(primitives::AncestryProof { + prev_peaks: raw_ancestry_proof.prev_peaks.into_iter().map(|p| p.hash()).collect(), + prev_leaf_count, + leaf_count: self.leaves, + items: raw_ancestry_proof + .proof + .proof_items() + .iter() + .map(|(index, item)| (*index, item.hash())) + .collect(), + }) + } } diff --git a/substrate/frame/merkle-mountain-range/src/mmr/storage.rs b/substrate/frame/merkle-mountain-range/src/mmr/storage.rs index f2acc35a137ffb46a39396762eafe30d7296e017..6848b8f1b9906b85bfc7c3b9ca9d5a52b4ddaed8 100644 --- a/substrate/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/substrate/frame/merkle-mountain-range/src/mmr/storage.rs @@ -60,7 +60,7 @@ impl Default for Storage { } } -impl mmr_lib::MMRStore> for Storage +impl mmr_lib::MMRStoreReadOps> for Storage where T: Config, I: 'static, @@ -98,13 +98,20 @@ where Ok(sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &temp_key) .and_then(|v| codec::Decode::decode(&mut &*v).ok())) } +} +impl mmr_lib::MMRStoreWriteOps> for Storage +where + T: Config, + I: 'static, + L: primitives::FullLeaf + codec::Decode, +{ fn append(&mut self, _: NodeIndex, _: Vec>) -> mmr_lib::Result<()> { panic!("MMR must not be altered in the off-chain context.") } } -impl mmr_lib::MMRStore> for Storage +impl mmr_lib::MMRStoreReadOps> for Storage where T: Config, I: 'static, @@ -113,7 +120,14 @@ where fn get_elem(&self, pos: NodeIndex) -> mmr_lib::Result>> { Ok(Nodes::::get(pos).map(Node::Hash)) } +} +impl mmr_lib::MMRStoreWriteOps> for Storage +where + T: Config, + I: 'static, + L: primitives::FullLeaf, +{ fn append(&mut self, pos: NodeIndex, elems: Vec>) -> mmr_lib::Result<()> { if elems.is_empty() { return Ok(()) diff --git a/substrate/frame/merkle-mountain-range/src/tests.rs b/substrate/frame/merkle-mountain-range/src/tests.rs index 88de7511c9f280b6996419f07ac1f5c458d8a395..f8cfcb4e2c286f949207826990ba715485247ca2 100644 --- a/substrate/frame/merkle-mountain-range/src/tests.rs +++ b/substrate/frame/merkle-mountain-range/src/tests.rs @@ -22,7 +22,7 @@ use sp_core::{ offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt}, H256, }; -use sp_mmr_primitives::{mmr_lib::helper, utils, Compact, Proof}; +use sp_mmr_primitives::{mmr_lib::helper, utils, Compact, LeafProof}; use sp_runtime::BuildStorage; pub(crate) fn new_test_ext() -> sp_io::TestExternalities { @@ -283,7 +283,7 @@ fn should_generate_proofs_correctly() { proofs[0], ( vec![Compact::new(((0, H256::repeat_byte(1)).into(), LeafData::new(1).into(),))], - Proof { + LeafProof { leaf_indices: vec![0], leaf_count: 7, items: vec![ @@ -298,7 +298,7 @@ fn should_generate_proofs_correctly() { historical_proofs[0][0], ( vec![Compact::new(((0, H256::repeat_byte(1)).into(), LeafData::new(1).into(),))], - Proof { leaf_indices: vec![0], leaf_count: 1, items: vec![] } + LeafProof { leaf_indices: vec![0], leaf_count: 1, items: vec![] } ) ); @@ -314,7 +314,7 @@ fn should_generate_proofs_correctly() { proofs[2], ( vec![Compact::new(((2, H256::repeat_byte(3)).into(), LeafData::new(3).into(),))], - Proof { + LeafProof { leaf_indices: vec![2], leaf_count: 7, items: vec![ @@ -334,7 +334,7 @@ fn should_generate_proofs_correctly() { historical_proofs[2][0], ( vec![Compact::new(((2, H256::repeat_byte(3)).into(), LeafData::new(3).into(),))], - Proof { + LeafProof { leaf_indices: vec![2], leaf_count: 3, items: vec![hex( @@ -354,7 +354,7 @@ fn should_generate_proofs_correctly() { historical_proofs[2][2], ( vec![Compact::new(((2, H256::repeat_byte(3)).into(), LeafData::new(3).into(),))], - Proof { + LeafProof { leaf_indices: vec![2], leaf_count: 5, items: vec![ @@ -372,7 +372,7 @@ fn should_generate_proofs_correctly() { ( // NOTE: the leaf index is equivalent to the block number(in this case 5) - 1 vec![Compact::new(((4, H256::repeat_byte(5)).into(), LeafData::new(5).into(),))], - Proof { + LeafProof { leaf_indices: vec![4], leaf_count: 7, items: vec![ @@ -387,7 +387,7 @@ fn should_generate_proofs_correctly() { historical_proofs[4][0], ( vec![Compact::new(((4, H256::repeat_byte(5)).into(), LeafData::new(5).into(),))], - Proof { + LeafProof { leaf_indices: vec![4], leaf_count: 5, items: vec![hex( @@ -402,7 +402,7 @@ fn should_generate_proofs_correctly() { proofs[6], ( vec![Compact::new(((6, H256::repeat_byte(7)).into(), LeafData::new(7).into(),))], - Proof { + LeafProof { leaf_indices: vec![6], leaf_count: 7, items: vec![ @@ -433,7 +433,7 @@ fn should_generate_batch_proof_correctly() { // then assert_eq!( proof, - Proof { + LeafProof { // the leaf indices are equivalent to the above specified block numbers - 1. leaf_indices: vec![0, 4, 5], leaf_count: 7, @@ -451,7 +451,7 @@ fn should_generate_batch_proof_correctly() { // then assert_eq!( historical_proof, - Proof { + LeafProof { leaf_indices: vec![0, 4, 5], leaf_count: 6, items: vec![ @@ -516,43 +516,40 @@ fn should_verify() { }); } -#[test] -fn should_verify_batch_proofs() { - fn generate_and_verify_batch_proof( - ext: &mut sp_io::TestExternalities, - block_numbers: &Vec, - blocks_to_add: usize, - ) { - let (leaves, proof) = ext.execute_with(|| { - crate::Pallet::::generate_proof(block_numbers.to_vec(), None).unwrap() - }); +fn generate_and_verify_batch_proof( + ext: &mut sp_io::TestExternalities, + block_numbers: &Vec, + blocks_to_add: usize, +) { + let (leaves, proof) = ext.execute_with(|| { + crate::Pallet::::generate_proof(block_numbers.to_vec(), None).unwrap() + }); - let max_block_number = ext.execute_with(|| frame_system::Pallet::::block_number()); - let min_block_number = block_numbers.iter().max().unwrap(); + let max_block_number = ext.execute_with(|| frame_system::Pallet::::block_number()); + let min_block_number = block_numbers.iter().max().unwrap(); - // generate all possible historical proofs for the given blocks - let historical_proofs = (*min_block_number..=max_block_number) - .map(|best_block| { - ext.execute_with(|| { - crate::Pallet::::generate_proof(block_numbers.to_vec(), Some(best_block)) - .unwrap() - }) + // generate all possible historical proofs for the given blocks + let historical_proofs = (*min_block_number..=max_block_number) + .map(|best_block| { + ext.execute_with(|| { + crate::Pallet::::generate_proof(block_numbers.to_vec(), Some(best_block)) + .unwrap() }) - .collect::>(); - - ext.execute_with(|| { - add_blocks(blocks_to_add); - // then - assert_eq!(crate::Pallet::::verify_leaves(leaves, proof), Ok(())); - historical_proofs.iter().for_each(|(leaves, proof)| { - assert_eq!( - crate::Pallet::::verify_leaves(leaves.clone(), proof.clone()), - Ok(()) - ); - }); }) - } + .collect::>(); + + ext.execute_with(|| { + add_blocks(blocks_to_add); + // then + assert_eq!(crate::Pallet::::verify_leaves(leaves, proof), Ok(())); + historical_proofs.iter().for_each(|(leaves, proof)| { + assert_eq!(crate::Pallet::::verify_leaves(leaves.clone(), proof.clone()), Ok(())); + }); + }) +} +#[test] +fn should_verify_batch_proofs() { let _ = env_logger::try_init(); use itertools::Itertools; @@ -790,3 +787,24 @@ fn does_not_panic_when_generating_historical_proofs() { ); }); } + +#[test] +fn generating_and_verifying_ancestry_proofs_works_correctly() { + let _ = env_logger::try_init(); + let mut ext = new_test_ext(); + ext.execute_with(|| add_blocks(500)); + ext.persist_offchain_overlay(); + register_offchain_ext(&mut ext); + + ext.execute_with(|| { + // Check that generating and verifying ancestry proofs works correctly + // for each previous block + for prev_block_number in 1..501 { + let proof = Pallet::::generate_ancestry_proof(prev_block_number, None).unwrap(); + Pallet::::verify_ancestry_proof(proof).unwrap(); + } + + // Check that we can't generate ancestry proofs for a future block. + assert_eq!(Pallet::::generate_ancestry_proof(501, None), Err(Error::GenerateProof)); + }); +} diff --git a/substrate/frame/message-queue/Cargo.toml b/substrate/frame/message-queue/Cargo.toml index f263c41831beab8f77aa04522e6cec40d75af703..e44cbeb1550ccfdb0daf8e871e924df261a59227 100644 --- a/substrate/frame/message-queue/Cargo.toml +++ b/substrate/frame/message-queue/Cargo.toml @@ -12,7 +12,7 @@ description = "FRAME pallet to queue and process messages" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } log = { workspace = true } diff --git a/substrate/frame/metadata-hash-extension/Cargo.toml b/substrate/frame/metadata-hash-extension/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..13d4bd0c2ea909700dda8d1ec621892c4a728724 --- /dev/null +++ b/substrate/frame/metadata-hash-extension/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "frame-metadata-hash-extension" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +homepage.workspace = true +repository.workspace = true +description = "FRAME signed extension for verifying the metadata hash" + +[dependencies] +array-bytes = "6.2.2" +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } +sp-runtime = { path = "../../primitives/runtime", default-features = false, features = ["serde"] } +frame-support = { path = "../support", default-features = false } +frame-system = { path = "../system", default-features = false } +log = { workspace = true, default-features = false } +docify = "0.2.8" + +[dev-dependencies] +substrate-wasm-builder = { path = "../../utils/wasm-builder", features = ["metadata-hash"] } +substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } +sp-api = { path = "../../primitives/api" } +sp-transaction-pool = { path = "../../primitives/transaction-pool" } +merkleized-metadata = "0.1.0" +frame-metadata = { version = "16.0.0", features = ["current"] } +sp-tracing = { path = "../../primitives/tracing" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-runtime/std", +] diff --git a/substrate/frame/metadata-hash-extension/src/lib.rs b/substrate/frame/metadata-hash-extension/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d09acbfb3df22e6c3e6706019ede1f16621ef767 --- /dev/null +++ b/substrate/frame/metadata-hash-extension/src/lib.rs @@ -0,0 +1,168 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +//! The [`CheckMetadataHash`] signed extension. +//! +//! The extension for optionally checking the metadata hash. For information how it works and what +//! it does exactly, see the docs of [`CheckMetadataHash`]. +//! +//! # Integration +//! +//! As any signed extension you will need to add it to your runtime signed extensions: +#![doc = docify::embed!("src/tests.rs", add_metadata_hash_extension)] +//! As the extension requires the `RUNTIME_METADATA_HASH` environment variable to be present at +//! compile time, it requires a little bit more setup. To have this environment variable available +//! at compile time required to tell the `substrate-wasm-builder` to do so: +#![doc = docify::embed!("src/tests.rs", enable_metadata_hash_in_wasm_builder)] +//! As generating the metadata hash requires to compile the runtime twice, it is +//! recommended to only enable the metadata hash generation when doing a build for a release or when +//! you want to test this feature. + +extern crate alloc; +/// For our tests +extern crate self as frame_metadata_hash_extension; + +use codec::{Decode, Encode}; +use frame_support::DebugNoBound; +use frame_system::Config; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::{TransactionValidityError, UnknownTransaction}, +}; + +#[cfg(test)] +mod tests; + +/// The mode of [`CheckMetadataHash`]. +#[derive(Decode, Encode, PartialEq, Debug, TypeInfo, Clone, Copy, Eq)] +enum Mode { + Disabled, + Enabled, +} + +/// Wrapper around the metadata hash and from where to get it from. +#[derive(Default, Debug, PartialEq, Clone, Copy, Eq)] +enum MetadataHash { + /// Fetch it from the `RUNTIME_METADATA_HASH` env variable at compile time. + #[default] + FetchFromEnv, + /// Use the given metadata hash. + Custom([u8; 32]), +} + +impl MetadataHash { + /// Returns the metadata hash. + fn hash(&self) -> Option<[u8; 32]> { + match self { + Self::FetchFromEnv => + option_env!("RUNTIME_METADATA_HASH").map(array_bytes::hex2array_unchecked), + Self::Custom(hash) => Some(*hash), + } + } +} + +/// Extension for optionally verifying the metadata hash. +/// +/// The metadata hash is cryptographical representation of the runtime metadata. This metadata hash +/// is build as described in [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html). +/// This metadata hash should give users the confidence that what they build with an online wallet +/// is the same they are signing with their offline wallet and then applying on chain. To ensure +/// that the online wallet is not tricking the offline wallet into decoding and showing an incorrect +/// extrinsic, the offline wallet will include the metadata hash into the additional signed data and +/// the runtime will then do the same. If the metadata hash doesn't match, the signature +/// verification will fail and thus, the transaction will be rejected. The RFC contains more details +/// on how it works. +/// +/// The extension adds one byte (the `mode`) to the size of the extrinsic. This one byte is +/// controlling if the metadata hash should be added to the signed data or not. Mode `0` means that +/// the metadata hash is not added and thus, `None` is added to the signed data. Mode `1` means that +/// the metadata hash is added and thus, `Some(metadata_hash)` is added to the signed data. Further +/// values of `mode` are reserved for future changes. +/// +/// The metadata hash is read from the environment variable `RUNTIME_METADATA_HASH`. This +/// environment variable is for example set by the `substrate-wasm-builder` when the feature for +/// generating the metadata hash is enabled. If the environment variable is not set and `mode = 1` +/// is passed, the transaction is rejected with [`UnknownTransaction::CannotLookup`]. +#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo, DebugNoBound)] +#[scale_info(skip_type_params(T))] +pub struct CheckMetadataHash { + _phantom: core::marker::PhantomData, + mode: Mode, + #[codec(skip)] + metadata_hash: MetadataHash, +} + +impl CheckMetadataHash { + /// Creates new `SignedExtension` to check metadata hash. + pub fn new(enable: bool) -> Self { + Self { + _phantom: core::marker::PhantomData, + mode: if enable { Mode::Enabled } else { Mode::Disabled }, + metadata_hash: MetadataHash::FetchFromEnv, + } + } + + /// Create an instance that uses the given `metadata_hash`. + /// + /// This is useful for testing the extension. + pub fn new_with_custom_hash(metadata_hash: [u8; 32]) -> Self { + Self { + _phantom: core::marker::PhantomData, + mode: Mode::Enabled, + metadata_hash: MetadataHash::Custom(metadata_hash), + } + } +} + +impl SignedExtension for CheckMetadataHash { + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = Option<[u8; 32]>; + type Pre = (); + const IDENTIFIER: &'static str = "CheckMetadataHash"; + + fn additional_signed(&self) -> Result { + let signed = match self.mode { + Mode::Disabled => None, + Mode::Enabled => match self.metadata_hash.hash() { + Some(hash) => Some(hash), + None => return Err(UnknownTransaction::CannotLookup.into()), + }, + }; + + log::debug!( + target: "runtime::metadata-hash", + "CheckMetadataHash::additional_signed => {:?}", + signed.as_ref().map(|h| array_bytes::bytes2hex("0x", h)), + ); + + Ok(signed) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } +} diff --git a/substrate/frame/metadata-hash-extension/src/tests.rs b/substrate/frame/metadata-hash-extension/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..f13eecfd94bfb5f78224e7dc40f2b08e1ce7c034 --- /dev/null +++ b/substrate/frame/metadata-hash-extension/src/tests.rs @@ -0,0 +1,179 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::CheckMetadataHash; +use codec::{Decode, Encode}; +use frame_metadata::RuntimeMetadataPrefixed; +use frame_support::{ + derive_impl, + pallet_prelude::{InvalidTransaction, TransactionValidityError}, +}; +use merkleized_metadata::{generate_metadata_digest, ExtraInfo}; +use sp_api::{Metadata, ProvideRuntimeApi}; +use sp_runtime::{ + traits::{Extrinsic as _, SignedExtension}, + transaction_validity::{TransactionSource, UnknownTransaction}, +}; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; +use substrate_test_runtime_client::{ + prelude::*, + runtime::{self, ExtrinsicBuilder}, + DefaultTestClientBuilderExt, TestClientBuilder, +}; + +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime! { + pub enum Test { + System: frame_system, + } +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Test { + type Block = Block; +} + +#[test] +fn rejects_when_no_metadata_hash_was_passed() { + let ext = CheckMetadataHash::::decode(&mut &1u8.encode()[..]).unwrap(); + assert_eq!(Err(UnknownTransaction::CannotLookup.into()), ext.additional_signed()); +} + +#[test] +fn rejects_unknown_mode() { + assert!(CheckMetadataHash::::decode(&mut &50u8.encode()[..]).is_err()); +} + +/// Generate the metadata hash for the `test-runtime`. +fn generate_metadata_hash(metadata: RuntimeMetadataPrefixed) -> [u8; 32] { + let runtime_version = runtime::VERSION; + let base58_prefix = 0; + + let extra_info = ExtraInfo { + spec_version: runtime_version.spec_version, + spec_name: runtime_version.spec_name.into(), + base58_prefix, + decimals: 10, + token_symbol: "TOKEN".into(), + }; + + generate_metadata_digest(&metadata.1, extra_info).unwrap().hash() +} + +#[test] +fn ensure_check_metadata_works_on_real_extrinsics() { + sp_tracing::try_init_simple(); + + let client = TestClientBuilder::new().build(); + let runtime_api = client.runtime_api(); + let best_hash = client.chain_info().best_hash; + + let metadata = RuntimeMetadataPrefixed::decode( + &mut &runtime_api.metadata_at_version(best_hash, 15).unwrap().unwrap()[..], + ) + .unwrap(); + + let valid_transaction = ExtrinsicBuilder::new_include_data(vec![1, 2, 3]) + .metadata_hash(generate_metadata_hash(metadata)) + .build(); + // Ensure that the transaction is signed. + assert!(valid_transaction.is_signed().unwrap()); + + runtime_api + .validate_transaction(best_hash, TransactionSource::External, valid_transaction, best_hash) + .unwrap() + .unwrap(); + + // Including some random metadata hash should make the transaction invalid. + let invalid_transaction = ExtrinsicBuilder::new_include_data(vec![1, 2, 3]) + .metadata_hash([10u8; 32]) + .build(); + // Ensure that the transaction is signed. + assert!(invalid_transaction.is_signed().unwrap()); + + assert_eq!( + TransactionValidityError::from(InvalidTransaction::BadProof), + runtime_api + .validate_transaction( + best_hash, + TransactionSource::External, + invalid_transaction, + best_hash + ) + .unwrap() + .unwrap_err() + ); +} + +#[allow(unused)] +mod docs { + use super::*; + + #[docify::export] + mod add_metadata_hash_extension { + frame_support::construct_runtime! { + pub enum Runtime { + System: frame_system, + } + } + + /// The `SignedExtension` to the basic transaction logic. + pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckMortality, + frame_system::CheckNonce, + frame_system::CheckWeight, + // Add the `CheckMetadataHash` extension. + // The position in this list is not important, so we could also add it to beginning. + frame_metadata_hash_extension::CheckMetadataHash, + ); + + /// In your runtime this will be your real address type. + type Address = (); + /// In your runtime this will be your real signature type. + type Signature = (); + + /// Unchecked extrinsic type as expected by this runtime. + pub type UncheckedExtrinsic = + sp_runtime::generic::UncheckedExtrinsic; + } + + // Put here to not have it in the docs as well. + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] + impl frame_system::Config for add_metadata_hash_extension::Runtime { + type Block = Block; + type RuntimeEvent = add_metadata_hash_extension::RuntimeEvent; + type RuntimeOrigin = add_metadata_hash_extension::RuntimeOrigin; + type RuntimeCall = add_metadata_hash_extension::RuntimeCall; + type PalletInfo = add_metadata_hash_extension::PalletInfo; + } + + #[docify::export] + fn enable_metadata_hash_in_wasm_builder() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + // Requires the `metadata-hash` feature to be activated. + // You need to pass the main token symbol and its number of decimals. + .enable_metadata_hash("TOKEN", 12) + // The runtime will be build twice and the second time the `RUNTIME_METADATA_HASH` + // environment variable will be set for the `CheckMetadataHash` extension. + .build() + } +} diff --git a/substrate/frame/migrations/Cargo.toml b/substrate/frame/migrations/Cargo.toml index 4726ac5c521e7395a29d374ab195a4a5a2147ff5..69e910a4e4f6e56b2b848f9b0f402da40d73f77d 100644 --- a/substrate/frame/migrations/Cargo.toml +++ b/substrate/frame/migrations/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } docify = "0.2.8" impl-trait-for-tuples = "0.2.2" log = "0.4.21" diff --git a/substrate/frame/mixnet/Cargo.toml b/substrate/frame/mixnet/Cargo.toml index 964d6acb889ad0e02b900efb0264f761c5afbeb7..44a567d668fb3c3452b4492831b0be66595a7c05 100644 --- a/substrate/frame/mixnet/Cargo.toml +++ b/substrate/frame/mixnet/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } frame-benchmarking = { default-features = false, optional = true, path = "../benchmarking" } frame-support = { default-features = false, path = "../support" } frame-system = { default-features = false, path = "../system" } diff --git a/substrate/frame/multisig/Cargo.toml b/substrate/frame/multisig/Cargo.toml index 2437acbc2e231b8d9c12fef4e2089e0110193be4..649a7100325f931e940760688710f88a1fbb6154 100644 --- a/substrate/frame/multisig/Cargo.toml +++ b/substrate/frame/multisig/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs index 0d73e3db66153f6c5fe16dd4974567c3584a2372..cfdd33f7dfcc3d3f5a49c302c0784718a70dfaca 100644 --- a/substrate/frame/multisig/src/tests.rs +++ b/substrate/frame/multisig/src/tests.rs @@ -41,7 +41,6 @@ frame_support::construct_runtime!( #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; - type BlockHashCount = ConstU32<250>; type AccountData = pallet_balances::AccountData; // This pallet wishes to overwrite this. type BaseCallFilter = TestBaseCallFilter; diff --git a/substrate/frame/nft-fractionalization/Cargo.toml b/substrate/frame/nft-fractionalization/Cargo.toml index b5a929468f7dc734ac3efb394b8a99475bb00a41..e2a7e34c637b430dbda56f1690938c1cde2b100e 100644 --- a/substrate/frame/nft-fractionalization/Cargo.toml +++ b/substrate/frame/nft-fractionalization/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/nft-fractionalization/src/lib.rs b/substrate/frame/nft-fractionalization/src/lib.rs index e97d3802fd206ca52ee008da007b46776ea76de8..cb269f464c48aea9555498c1bdf3f4d261c01895 100644 --- a/substrate/frame/nft-fractionalization/src/lib.rs +++ b/substrate/frame/nft-fractionalization/src/lib.rs @@ -75,7 +75,7 @@ pub mod pallet { AssetId, Balance as AssetBalance, Fortitude::Polite, Precision::{BestEffort, Exact}, - Preservation::Preserve, + Preservation::{Expendable, Preserve}, }, }, BoundedVec, PalletId, @@ -374,7 +374,7 @@ pub mod pallet { account: &T::AccountId, amount: AssetBalanceOf, ) -> DispatchResult { - T::Assets::burn_from(asset_id.clone(), account, amount, Exact, Polite)?; + T::Assets::burn_from(asset_id.clone(), account, amount, Expendable, Exact, Polite)?; T::Assets::start_destroy(asset_id, None) } diff --git a/substrate/frame/nfts/Cargo.toml b/substrate/frame/nfts/Cargo.toml index 4f818ea3e08c52e741124f42463f3b9ecc3ae9c9..5c5c011c94ea27467e5b8bbd18fda890a181acf2 100644 --- a/substrate/frame/nfts/Cargo.toml +++ b/substrate/frame/nfts/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } enumflags2 = { version = "0.7.7" } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/nfts/runtime-api/Cargo.toml b/substrate/frame/nfts/runtime-api/Cargo.toml index 84cbd1f51c98c673df2f9084d34fad77ec69dd54..6bee98fb51e0c908dfb70d28891e91cb55a7c6ea 100644 --- a/substrate/frame/nfts/runtime-api/Cargo.toml +++ b/substrate/frame/nfts/runtime-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } pallet-nfts = { path = "..", default-features = false } sp-api = { path = "../../../primitives/api", default-features = false } sp-std = { path = "../../../primitives/std", default-features = false } diff --git a/substrate/frame/nis/Cargo.toml b/substrate/frame/nis/Cargo.toml index d0ba74a9273152dcac8e541ee8be8a41d1a5b584..1e3a0609c46bbfc40b044eae839f9bd0303e0178 100644 --- a/substrate/frame/nis/Cargo.toml +++ b/substrate/frame/nis/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/nis/src/lib.rs b/substrate/frame/nis/src/lib.rs index 63287f6a1802104df4f03982f92b82010a65924b..f38755836fb9f15dd6db8eaab38f206dea43b562 100644 --- a/substrate/frame/nis/src/lib.rs +++ b/substrate/frame/nis/src/lib.rs @@ -808,7 +808,7 @@ pub mod pallet { ensure!(summary.thawed <= throttle, Error::::Throttled); let cp_amount = T::CounterpartAmount::convert(receipt.proportion); - T::Counterpart::burn_from(&who, cp_amount, Exact, Polite)?; + T::Counterpart::burn_from(&who, cp_amount, Expendable, Exact, Polite)?; // Multiply the proportion it is by the total issued. let our_account = Self::account_id(); @@ -897,6 +897,7 @@ pub mod pallet { T::Counterpart::burn_from( &who, T::CounterpartAmount::convert(receipt.proportion), + Expendable, Exact, Polite, )?; diff --git a/substrate/frame/nis/src/tests.rs b/substrate/frame/nis/src/tests.rs index 01724999ae7e9fb346f940be776e8b1273ea98f4..a17aaf421827f3aba79fa36065178922b0af6d93 100644 --- a/substrate/frame/nis/src/tests.rs +++ b/substrate/frame/nis/src/tests.rs @@ -24,7 +24,7 @@ use frame_support::{ traits::{ fungible::{hold::Inspect as InspectHold, Inspect as FunInspect, Mutate as FunMutate}, nonfungible::{Inspect, Transfer}, - tokens::{Fortitude::Force, Precision::Exact}, + tokens::{Fortitude::Force, Precision::Exact, Preservation::Expendable}, }, }; use sp_arithmetic::Perquintill; @@ -646,9 +646,9 @@ fn thaw_when_issuance_lower_works() { enlarge(100, 1); // Everybody else's balances goes down by 25% - assert_ok!(Balances::burn_from(&2, 25, Exact, Force)); - assert_ok!(Balances::burn_from(&3, 25, Exact, Force)); - assert_ok!(Balances::burn_from(&4, 25, Exact, Force)); + assert_ok!(Balances::burn_from(&2, 25, Expendable, Exact, Force)); + assert_ok!(Balances::burn_from(&3, 25, Expendable, Exact, Force)); + assert_ok!(Balances::burn_from(&4, 25, Expendable, Exact, Force)); run_to_block(4); assert_ok!(Nis::thaw_private(signed(1), 0, None)); diff --git a/substrate/frame/node-authorization/Cargo.toml b/substrate/frame/node-authorization/Cargo.toml index 63376163cdcb78baa03a266189d3e52ee13466a7..17ed16d2623368826f1ad93c6b4f5032775319cf 100644 --- a/substrate/frame/node-authorization/Cargo.toml +++ b/substrate/frame/node-authorization/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/nomination-pools/Cargo.toml b/substrate/frame/nomination-pools/Cargo.toml index eddcc8e4e1ddb9a51fcbec8dd1c922d20c43833c..bf4e01a3184793d638b1c87f5984a517a18e2ceb 100644 --- a/substrate/frame/nomination-pools/Cargo.toml +++ b/substrate/frame/nomination-pools/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # parity -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/substrate/frame/nomination-pools/benchmarking/Cargo.toml b/substrate/frame/nomination-pools/benchmarking/Cargo.toml index 4985d7acbec92f8258f32338bc348981922c53a9..3f9463a9c429b93da7cf5945a6ebd2ac46077196 100644 --- a/substrate/frame/nomination-pools/benchmarking/Cargo.toml +++ b/substrate/frame/nomination-pools/benchmarking/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # parity -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # FRAME @@ -27,6 +27,7 @@ frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } pallet-bags-list = { path = "../../bags-list", default-features = false } pallet-staking = { path = "../../staking", default-features = false } +pallet-delegated-staking = { path = "../../delegated-staking", default-features = false } pallet-nomination-pools = { path = "..", default-features = false } # Substrate Primitives @@ -53,6 +54,7 @@ std = [ "frame-system/std", "pallet-bags-list/std", "pallet-balances/std", + "pallet-delegated-staking/std", "pallet-nomination-pools/std", "pallet-staking/std", "pallet-timestamp/std", @@ -72,6 +74,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-delegated-staking/runtime-benchmarks", "pallet-nomination-pools/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", diff --git a/substrate/frame/nomination-pools/benchmarking/src/inner.rs b/substrate/frame/nomination-pools/benchmarking/src/inner.rs index 277060e7f640f962bd112a6f337339ec1cf2559e..43de0fddb8b5fd574f26464d8332507ff96a1575 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/inner.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/inner.rs @@ -23,22 +23,24 @@ use frame_support::{ assert_ok, ensure, traits::{ fungible::{Inspect, Mutate, Unbalanced}, - Get, + tokens::Preservation, + Get, Imbalance, }, }; use frame_system::RawOrigin as RuntimeOrigin; use pallet_nomination_pools::{ + adapter::{StakeStrategy, StakeStrategyType}, BalanceOf, BondExtra, BondedPoolInner, BondedPools, ClaimPermission, ClaimPermissions, Commission, CommissionChangeRate, CommissionClaimPermission, ConfigOp, GlobalMaxCommission, MaxPoolMembers, MaxPoolMembersPerPool, MaxPools, Metadata, MinCreateBond, MinJoinBond, - Pallet as Pools, PoolMembers, PoolRoles, PoolState, RewardPools, SubPoolsStorage, + Pallet as Pools, PoolId, PoolMembers, PoolRoles, PoolState, RewardPools, SubPoolsStorage, }; use pallet_staking::MaxNominationsOf; use sp_runtime::{ traits::{Bounded, StaticLookup, Zero}, Perbill, }; -use sp_staking::{EraIndex, StakingInterface}; +use sp_staking::EraIndex; use sp_std::{vec, vec::Vec}; // `frame_benchmarking::benchmarks!` macro needs this use pallet_nomination_pools::Call; @@ -101,18 +103,46 @@ fn create_pool_account( let pool_account = pallet_nomination_pools::BondedPools::::iter() .find(|(_, bonded_pool)| bonded_pool.roles.depositor == pool_creator) - .map(|(pool_id, _)| Pools::::create_bonded_account(pool_id)) + .map(|(pool_id, _)| Pools::::generate_bonded_account(pool_id)) .expect("pool_creator created a pool above"); (pool_creator, pool_account) } +fn migrate_to_transfer_stake(pool_id: PoolId) { + if T::StakeAdapter::strategy_type() == StakeStrategyType::Transfer { + // should already be in the correct strategy + return; + } + let pool_acc = Pools::::generate_bonded_account(pool_id); + // drop the agent and its associated delegators . + T::StakeAdapter::remove_as_agent(&pool_acc); + + // tranfer funds from all members to the pool account. + PoolMembers::::iter() + .filter(|(_, member)| member.pool_id == pool_id) + .for_each(|(member_acc, member)| { + let member_balance = member.total_balance(); + ::Currency::transfer( + &member_acc, + &pool_acc, + member_balance, + Preservation::Preserve, + ) + .expect("member should have enough balance to transfer"); + }); +} + fn vote_to_balance( vote: u64, ) -> Result, &'static str> { vote.try_into().map_err(|_| "could not convert u64 to Balance") } +fn is_transfer_stake_strategy() -> bool { + T::StakeAdapter::strategy_type() == StakeStrategyType::Transfer +} + #[allow(unused)] struct ListScenario { /// Stash/Controller that is expected to be moved. @@ -151,7 +181,7 @@ impl ListScenario { let (pool_creator1, pool_origin1) = create_pool_account::(USER_SEED + 1, origin_weight, Some(Perbill::from_percent(50))); - T::Staking::nominate( + T::StakeAdapter::nominate( &pool_origin1, // NOTE: these don't really need to be validators. vec![account("random_validator", 0, USER_SEED)], @@ -160,7 +190,7 @@ impl ListScenario { let (_, pool_origin2) = create_pool_account::(USER_SEED + 2, origin_weight, Some(Perbill::from_percent(50))); - T::Staking::nominate( + T::StakeAdapter::nominate( &pool_origin2, vec![account("random_validator", 0, USER_SEED)].clone(), )?; @@ -178,7 +208,7 @@ impl ListScenario { let (_, pool_dest1) = create_pool_account::(USER_SEED + 3, dest_weight, Some(Perbill::from_percent(50))); - T::Staking::nominate(&pool_dest1, vec![account("random_validator", 0, USER_SEED)])?; + T::StakeAdapter::nominate(&pool_dest1, vec![account("random_validator", 0, USER_SEED)])?; let weight_of = pallet_staking::Pallet::::weight_of_fn(); assert_eq!(vote_to_balance::(weight_of(&pool_origin1)).unwrap(), origin_weight); @@ -204,11 +234,12 @@ impl ListScenario { self.origin1_member = Some(joiner.clone()); CurrencyOf::::set_balance(&joiner, amount * 2u32.into()); - let original_bonded = T::Staking::active_stake(&self.origin1).unwrap(); + let original_bonded = T::StakeAdapter::active_stake(&self.origin1); // Unbond `amount` from the underlying pool account so when the member joins // we will maintain `current_bonded`. - T::Staking::unbond(&self.origin1, amount).expect("the pool was created in `Self::new`."); + T::StakeAdapter::unbond(&self.origin1, amount) + .expect("the pool was created in `Self::new`."); // Account pool points for the unbonded balance. BondedPools::::mutate(&1, |maybe_pool| { @@ -231,13 +262,20 @@ impl ListScenario { } frame_benchmarking::benchmarks! { + where_clause { + where + T: pallet_staking::Config, + pallet_staking::BalanceOf: From, + BalanceOf: Into, + } + join { let origin_weight = Pools::::depositor_min_bond() * 2u32.into(); // setup the worst case list scenario. let scenario = ListScenario::::new(origin_weight, true)?; assert_eq!( - T::Staking::active_stake(&scenario.origin1).unwrap(), + T::StakeAdapter::active_stake(&scenario.origin1), origin_weight ); @@ -252,7 +290,7 @@ frame_benchmarking::benchmarks! { verify { assert_eq!(CurrencyOf::::balance(&joiner), joiner_free - max_additional); assert_eq!( - T::Staking::active_stake(&scenario.origin1).unwrap(), + T::StakeAdapter::active_stake(&scenario.origin1), scenario.dest_weight ); } @@ -267,7 +305,7 @@ frame_benchmarking::benchmarks! { }: bond_extra(RuntimeOrigin::Signed(scenario.creator1.clone()), BondExtra::FreeBalance(extra)) verify { assert!( - T::Staking::active_stake(&scenario.origin1).unwrap() >= + T::StakeAdapter::active_stake(&scenario.origin1) >= scenario.dest_weight ); } @@ -283,7 +321,7 @@ frame_benchmarking::benchmarks! { let _ = Pools::::set_claim_permission(RuntimeOrigin::Signed(scenario.creator1.clone()).into(), ClaimPermission::PermissionlessAll); // transfer exactly `extra` to the depositor of the src pool (1), - let reward_account1 = Pools::::create_reward_account(1); + let reward_account1 = Pools::::generate_reward_account(1); assert!(extra >= CurrencyOf::::minimum_balance()); let _ = CurrencyOf::::mint_into(&reward_account1, extra); @@ -291,7 +329,7 @@ frame_benchmarking::benchmarks! { verify { // commission of 50% deducted here. assert!( - T::Staking::active_stake(&scenario.origin1).unwrap() >= + T::StakeAdapter::active_stake(&scenario.origin1) >= scenario.dest_weight / 2u32.into() ); } @@ -302,7 +340,7 @@ frame_benchmarking::benchmarks! { let origin_weight = Pools::::depositor_min_bond() * 2u32.into(); let ed = CurrencyOf::::minimum_balance(); let (depositor, pool_account) = create_pool_account::(0, origin_weight, Some(commission)); - let reward_account = Pools::::create_reward_account(1); + let reward_account = Pools::::generate_reward_account(1); // Send funds to the reward account of the pool CurrencyOf::::set_balance(&reward_account, ed + origin_weight); @@ -345,7 +383,7 @@ frame_benchmarking::benchmarks! { whitelist_account!(member_id); }: _(RuntimeOrigin::Signed(member_id.clone()), member_id_lookup, all_points) verify { - let bonded_after = T::Staking::active_stake(&scenario.origin1).unwrap(); + let bonded_after = T::StakeAdapter::active_stake(&scenario.origin1); // We at least went down to the destination bag assert!(bonded_after <= scenario.dest_weight); let member = PoolMembers::::get( @@ -354,7 +392,7 @@ frame_benchmarking::benchmarks! { .unwrap(); assert_eq!( member.unbonding_eras.keys().cloned().collect::>(), - vec![0 + T::Staking::bonding_duration()] + vec![0 + T::StakeAdapter::bonding_duration()] ); assert_eq!( member.unbonding_eras.values().cloned().collect::>(), @@ -376,7 +414,7 @@ frame_benchmarking::benchmarks! { // Sanity check join worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), min_create_bond + min_join_bond ); assert_eq!(CurrencyOf::::balance(&joiner), min_join_bond); @@ -386,7 +424,7 @@ frame_benchmarking::benchmarks! { // Sanity check that unbond worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), min_create_bond ); assert_eq!(pallet_staking::Ledger::::get(&pool_account).unwrap().unlocking.len(), 1); @@ -419,7 +457,7 @@ frame_benchmarking::benchmarks! { // Sanity check join worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), min_create_bond + min_join_bond ); assert_eq!(CurrencyOf::::balance(&joiner), min_join_bond); @@ -430,7 +468,7 @@ frame_benchmarking::benchmarks! { // Sanity check that unbond worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), min_create_bond ); assert_eq!(pallet_staking::Ledger::::get(&pool_account).unwrap().unlocking.len(), 1); @@ -470,17 +508,17 @@ frame_benchmarking::benchmarks! { // here to ensure the complete flow for destroying a pool works - the reward pool account // should never exist by time the depositor withdraws so we test that it gets cleaned // up when unbonding. - let reward_account = Pools::::create_reward_account(1); + let reward_account = Pools::::generate_reward_account(1); assert!(frame_system::Account::::contains_key(&reward_account)); Pools::::fully_unbond(RuntimeOrigin::Signed(depositor.clone()).into(), depositor.clone()).unwrap(); // Sanity check that unbond worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), Zero::zero() ); assert_eq!( - CurrencyOf::::balance(&pool_account), + T::StakeAdapter::total_balance(&pool_account), min_create_bond ); assert_eq!(pallet_staking::Ledger::::get(&pool_account).unwrap().unlocking.len(), 1); @@ -522,8 +560,8 @@ frame_benchmarking::benchmarks! { let depositor_lookup = T::Lookup::unlookup(depositor.clone()); // Give the depositor some balance to bond - CurrencyOf::::set_balance(&depositor, min_create_bond * 2u32.into()); - + // it needs to transfer min balance to reward account as well so give additional min balance. + CurrencyOf::::set_balance(&depositor, min_create_bond + CurrencyOf::::minimum_balance() * 2u32.into()); // Make sure no Pools exist at a pre-condition for our verify checks assert_eq!(RewardPools::::count(), 0); assert_eq!(BondedPools::::count(), 0); @@ -556,8 +594,8 @@ frame_benchmarking::benchmarks! { } ); assert_eq!( - T::Staking::active_stake(&Pools::::create_bonded_account(1)), - Ok(min_create_bond) + T::StakeAdapter::active_stake(&Pools::::generate_bonded_account(1)), + min_create_bond ); } @@ -596,8 +634,8 @@ frame_benchmarking::benchmarks! { } ); assert_eq!( - T::Staking::active_stake(&Pools::::create_bonded_account(1)), - Ok(min_create_bond) + T::StakeAdapter::active_stake(&Pools::::generate_bonded_account(1)), + min_create_bond ); } @@ -681,13 +719,13 @@ frame_benchmarking::benchmarks! { .map(|i| account("stash", USER_SEED, i)) .collect(); - assert_ok!(T::Staking::nominate(&pool_account, validators)); - assert!(T::Staking::nominations(&Pools::::create_bonded_account(1)).is_some()); + assert_ok!(T::StakeAdapter::nominate(&pool_account, validators)); + assert!(T::StakeAdapter::nominations(&Pools::::generate_bonded_account(1)).is_some()); whitelist_account!(depositor); }:_(RuntimeOrigin::Signed(depositor.clone()), 1) verify { - assert!(T::Staking::nominations(&Pools::::create_bonded_account(1)).is_none()); + assert!(T::StakeAdapter::nominations(&Pools::::generate_bonded_account(1)).is_none()); } set_commission { @@ -786,7 +824,7 @@ frame_benchmarking::benchmarks! { // Sanity check join worked assert_eq!( - T::Staking::active_stake(&pool_account).unwrap(), + T::StakeAdapter::active_stake(&pool_account), min_create_bond + min_join_bond ); }:_(RuntimeOrigin::Signed(joiner.clone()), ClaimPermission::Permissioned) @@ -800,7 +838,7 @@ frame_benchmarking::benchmarks! { let origin_weight = Pools::::depositor_min_bond() * 2u32.into(); let ed = CurrencyOf::::minimum_balance(); let (depositor, pool_account) = create_pool_account::(0, origin_weight, Some(commission)); - let reward_account = Pools::::create_reward_account(1); + let reward_account = Pools::::generate_reward_account(1); CurrencyOf::::set_balance(&reward_account, ed + origin_weight); // member claims a payout to make some commission available. @@ -829,7 +867,7 @@ frame_benchmarking::benchmarks! { let (depositor, _) = create_pool_account::(0, Pools::::depositor_min_bond() * 2u32.into(), None); // Remove ed freeze to create a scenario where the ed deposit needs to be adjusted. - let _ = Pools::::unfreeze_pool_deposit(&Pools::::create_reward_account(1)); + let _ = Pools::::unfreeze_pool_deposit(&Pools::::generate_reward_account(1)); assert!(&Pools::::check_ed_imbalance().is_err()); whitelist_account!(depositor); @@ -838,6 +876,147 @@ frame_benchmarking::benchmarks! { assert!(&Pools::::check_ed_imbalance().is_ok()); } + apply_slash { + // Note: With older `TransferStake` strategy, slashing is greedy and apply_slash should + // always fail. + + // We want to fill member's unbonding pools. So let's bond with big enough amount. + let deposit_amount = Pools::::depositor_min_bond() * T::MaxUnbonding::get().into() * 4u32.into(); + let (depositor, pool_account) = create_pool_account::(0, deposit_amount, None); + let depositor_lookup = T::Lookup::unlookup(depositor.clone()); + + // verify user balance in the pool. + assert_eq!(PoolMembers::::get(&depositor).unwrap().total_balance(), deposit_amount); + // verify delegated balance. + assert!(is_transfer_stake_strategy::() || T::StakeAdapter::member_delegation_balance(&depositor) == deposit_amount); + + // ugly type conversion between balances of pallet staking and pools (which really are same + // type). Maybe there is a better way? + let slash_amount: u128 = deposit_amount.into()/2; + + // slash pool by half + pallet_staking::slashing::do_slash::( + &pool_account, + slash_amount.into(), + &mut pallet_staking::BalanceOf::::zero(), + &mut pallet_staking::NegativeImbalanceOf::::zero(), + EraIndex::zero() + ); + + // verify user balance is slashed in the pool. + assert_eq!(PoolMembers::::get(&depositor).unwrap().total_balance(), deposit_amount/2u32.into()); + // verify delegated balance are not yet slashed. + assert!(is_transfer_stake_strategy::() || T::StakeAdapter::member_delegation_balance(&depositor) == deposit_amount); + + // Fill member's sub pools for the worst case. + for i in 1..(T::MaxUnbonding::get() + 1) { + pallet_staking::CurrentEra::::put(i); + assert!(Pools::::unbond(RuntimeOrigin::Signed(depositor.clone()).into(), depositor_lookup.clone(), Pools::::depositor_min_bond()).is_ok()); + } + + pallet_staking::CurrentEra::::put(T::MaxUnbonding::get() + 2); + + let slash_reporter = create_funded_user_with_balance::("slasher", 0, CurrencyOf::::minimum_balance()); + whitelist_account!(depositor); + }: + { + let res = Pools::::apply_slash(RuntimeOrigin::Signed(slash_reporter.clone()).into(), depositor_lookup.clone()); + // for transfer stake strategy, apply slash would error, otherwise success. + assert!(is_transfer_stake_strategy::() ^ res.is_ok()); + } + verify { + // verify balances are correct and slash applied. + assert_eq!(PoolMembers::::get(&depositor).unwrap().total_balance(), deposit_amount/2u32.into()); + assert!(is_transfer_stake_strategy::() || T::StakeAdapter::member_delegation_balance(&depositor) == deposit_amount/2u32.into()); + } + + apply_slash_fail { + // Bench the scenario where pool has some unapplied slash but the member does not have any + // slash to be applied. + let deposit_amount = Pools::::depositor_min_bond() * 10u32.into(); + // Create pool. + let (depositor, pool_account) = create_pool_account::(0, deposit_amount, None); + + // slash pool by half + let slash_amount: u128 = deposit_amount.into()/2; + pallet_staking::slashing::do_slash::( + &pool_account, + slash_amount.into(), + &mut pallet_staking::BalanceOf::::zero(), + &mut pallet_staking::NegativeImbalanceOf::::zero(), + EraIndex::zero() + ); + + pallet_staking::CurrentEra::::put(1); + + // new member joins the pool who should not be affected by slash. + let min_join_bond = MinJoinBond::::get().max(CurrencyOf::::minimum_balance()); + let join_amount = min_join_bond * T::MaxUnbonding::get().into() * 2u32.into(); + let joiner = create_funded_user_with_balance::("joiner", 0, join_amount * 2u32.into()); + let joiner_lookup = T::Lookup::unlookup(joiner.clone()); + assert!(Pools::::join(RuntimeOrigin::Signed(joiner.clone()).into(), join_amount, 1).is_ok()); + + // Fill member's sub pools for the worst case. + for i in 0..T::MaxUnbonding::get() { + pallet_staking::CurrentEra::::put(i + 2); // +2 because we already set the current era to 1. + assert!(Pools::::unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner_lookup.clone(), min_join_bond).is_ok()); + } + + pallet_staking::CurrentEra::::put(T::MaxUnbonding::get() + 3); + whitelist_account!(joiner); + + }: { + // Since the StakeAdapter can be different based on the runtime config, the errors could be different as well. + assert!(Pools::::apply_slash(RuntimeOrigin::Signed(joiner.clone()).into(), joiner_lookup.clone()).is_err()); + } + + + pool_migrate { + // create a pool. + let deposit_amount = Pools::::depositor_min_bond() * 2u32.into(); + let (depositor, pool_account) = create_pool_account::(0, deposit_amount, None); + + // migrate pool to transfer stake. + let _ = migrate_to_transfer_stake::(1); + }: { + // Try migrate to `DelegateStake`. Would succeed only if `DelegateStake` strategy is used. + let res = Pools::::migrate_pool_to_delegate_stake(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into()); + assert!(is_transfer_stake_strategy::() ^ res.is_ok()); + } + verify { + // this queries agent balance if `DelegateStake` strategy. + assert!(T::StakeAdapter::total_balance(&pool_account) == deposit_amount); + } + + migrate_delegation { + // create a pool. + let deposit_amount = Pools::::depositor_min_bond() * 2u32.into(); + let (depositor, pool_account) = create_pool_account::(0, deposit_amount, None); + let depositor_lookup = T::Lookup::unlookup(depositor.clone()); + + // migrate pool to transfer stake. + let _ = migrate_to_transfer_stake::(1); + + // Now migrate pool to delegate stake keeping delegators unmigrated. + let migration_res = Pools::::migrate_pool_to_delegate_stake(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into()); + assert!(is_transfer_stake_strategy::() ^ migration_res.is_ok()); + + // verify balances that we will check again later. + assert!(T::StakeAdapter::member_delegation_balance(&depositor) == Zero::zero()); + assert_eq!(PoolMembers::::get(&depositor).unwrap().total_balance(), deposit_amount); + + whitelist_account!(depositor); + }: { + let res = Pools::::migrate_delegation(RuntimeOrigin::Signed(depositor.clone()).into(), depositor_lookup.clone()); + // for transfer stake strategy, apply slash would error, otherwise success. + assert!(is_transfer_stake_strategy::() ^ res.is_ok()); + } + verify { + // verify balances once more. + assert!(is_transfer_stake_strategy::() || T::StakeAdapter::member_delegation_balance(&depositor) == deposit_amount); + assert_eq!(PoolMembers::::get(&depositor).unwrap().total_balance(), deposit_amount); + } + impl_benchmark_test_suite!( Pallet, crate::mock::new_test_ext(), diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs index 45e8f1f27e99a52b5900aa5e18c5439d9d7baa5c..910cdf2e3dff6353d90a2ba138c4731b0b020a0f 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs @@ -18,6 +18,7 @@ //! Benchmarks for the nomination pools coupled with the staking and bags list pallets. #![cfg_attr(not(feature = "std"), no_std)] +#![recursion_limit = "256"] #[cfg(feature = "runtime-benchmarks")] pub mod inner; diff --git a/substrate/frame/nomination-pools/benchmarking/src/mock.rs b/substrate/frame/nomination-pools/benchmarking/src/mock.rs index 2752d53a6b9f3364c234d9144a6c40b10b449a5b..def98b4d2945e20c6c3475383e8e526f19b8110d 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/mock.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/mock.rs @@ -77,7 +77,7 @@ impl pallet_balances::Config for Runtime { type WeightInfo = (); type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; - type RuntimeHoldReason = (); + type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = (); } @@ -120,7 +120,7 @@ impl pallet_staking::Config for Runtime { type MaxControllersInDeprecationBatch = ConstU32<100>; type MaxUnlockingChunks = ConstU32<32>; type HistoryDepth = ConstU32<84>; - type EventListeners = Pools; + type EventListeners = (Pools, DelegatedStaking); type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; @@ -166,7 +166,8 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = Staking; + type StakeAdapter = + pallet_nomination_pools::adapter::DelegateStake; type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; type MaxMetadataLen = ConstU32<256>; type MaxUnbonding = ConstU32<8>; @@ -175,6 +176,20 @@ impl pallet_nomination_pools::Config for Runtime { type AdminOrigin = frame_system::EnsureRoot; } +parameter_types! { + pub const DelegatedStakingPalletId: PalletId = PalletId(*b"py/dlstk"); + pub const SlashRewardFraction: Perbill = Perbill::from_percent(1); +} +impl pallet_delegated_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = DelegatedStakingPalletId; + type Currency = Balances; + type OnSlash = (); + type SlashRewardFraction = SlashRewardFraction; + type RuntimeHoldReason = RuntimeHoldReason; + type CoreStaking = Staking; +} + impl crate::Config for Runtime {} type Block = frame_system::mocking::MockBlock; @@ -187,6 +202,7 @@ frame_support::construct_runtime!( Staking: pallet_staking, VoterList: pallet_bags_list::, Pools: pallet_nomination_pools, + DelegatedStaking: pallet_delegated_staking, } ); diff --git a/substrate/frame/nomination-pools/fuzzer/src/call.rs b/substrate/frame/nomination-pools/fuzzer/src/call.rs index 027fb2b69138c64f8903f99737187b7cd65c12c2..9e10d87da6750e4171d2736eb6fb7dcbc7324640 100644 --- a/substrate/frame/nomination-pools/fuzzer/src/call.rs +++ b/substrate/frame/nomination-pools/fuzzer/src/call.rs @@ -306,7 +306,7 @@ fn main() { BondedPools::::iter().for_each(|(id, _)| { let amount = random_ed_multiple(&mut rng); let _ = - Balances::deposit_creating(&Pools::create_reward_account(id), amount); + Balances::deposit_creating(&Pools::generate_reward_account(id), amount); // if we just paid out the reward agent, let's calculate how much we expect // our reward agent to have earned. if reward_agent.pool_id.map_or(false, |mid| mid == id) { diff --git a/substrate/frame/nomination-pools/runtime-api/Cargo.toml b/substrate/frame/nomination-pools/runtime-api/Cargo.toml index 7828f26fe6fe1378942479f44f40e325da265817..a0ddac9e045675aefe7b8139e0048f3399663da8 100644 --- a/substrate/frame/nomination-pools/runtime-api/Cargo.toml +++ b/substrate/frame/nomination-pools/runtime-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } sp-api = { path = "../../../primitives/api", default-features = false } sp-std = { path = "../../../primitives/std", default-features = false } pallet-nomination-pools = { path = "..", default-features = false } diff --git a/substrate/frame/nomination-pools/src/adapter.rs b/substrate/frame/nomination-pools/src/adapter.rs new file mode 100644 index 0000000000000000000000000000000000000000..caf4671191d8896a17c130b5e6ffeafc42a19c20 --- /dev/null +++ b/substrate/frame/nomination-pools/src/adapter.rs @@ -0,0 +1,389 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use sp_staking::{DelegationInterface, DelegationMigrator}; + +/// Types of stake strategies. +/// +/// Useful for determining current staking strategy of a runtime and enforce integrity tests. +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebugNoBound, PartialEq)] +pub enum StakeStrategyType { + /// Member funds are transferred to pool account and staked. + /// + /// This is the older staking strategy used by pools. For a new runtime, it is recommended to + /// use [`StakeStrategyType::Delegate`] strategy instead. + Transfer, + /// Member funds are delegated to pool account and staked. + Delegate, +} + +/// An adapter trait that can support multiple staking strategies. +/// +/// Depending on which staking strategy we want to use, the staking logic can be slightly +/// different. Refer the two possible strategies currently: [`TransferStake`] and +/// [`DelegateStake`] for more detail. +pub trait StakeStrategy { + type Balance: frame_support::traits::tokens::Balance; + type AccountId: Clone + sp_std::fmt::Debug; + type CoreStaking: StakingInterface; + + /// The type of staking strategy of the current adapter. + fn strategy_type() -> StakeStrategyType; + + /// See [`StakingInterface::bonding_duration`]. + fn bonding_duration() -> EraIndex { + Self::CoreStaking::bonding_duration() + } + + /// See [`StakingInterface::current_era`]. + fn current_era() -> EraIndex { + Self::CoreStaking::current_era() + } + + /// See [`StakingInterface::minimum_nominator_bond`]. + fn minimum_nominator_bond() -> Self::Balance { + Self::CoreStaking::minimum_nominator_bond() + } + + /// Balance that can be transferred from pool account to member. + /// + /// This is part of the pool balance that is not actively staked. That is, tokens that are + /// in unbonding period or unbonded. + fn transferable_balance(pool_account: &Self::AccountId) -> Self::Balance; + + /// Total balance of the pool including amount that is actively staked. + fn total_balance(pool_account: &Self::AccountId) -> Self::Balance; + + /// Amount of tokens delegated by the member. + fn member_delegation_balance(member_account: &Self::AccountId) -> Self::Balance; + + /// See [`StakingInterface::active_stake`]. + fn active_stake(pool_account: &Self::AccountId) -> Self::Balance { + Self::CoreStaking::active_stake(pool_account).unwrap_or_default() + } + + /// See [`StakingInterface::total_stake`]. + fn total_stake(pool_account: &Self::AccountId) -> Self::Balance { + Self::CoreStaking::total_stake(pool_account).unwrap_or_default() + } + + /// Which strategy the pool account is using. + /// + /// This can be different from the [`Self::strategy_type`] of the adapter if the pool has not + /// migrated to the new strategy yet. + fn pool_strategy(pool_account: &Self::AccountId) -> StakeStrategyType { + match Self::CoreStaking::is_virtual_staker(pool_account) { + true => StakeStrategyType::Delegate, + false => StakeStrategyType::Transfer, + } + } + + /// See [`StakingInterface::nominate`]. + fn nominate( + pool_account: &Self::AccountId, + validators: Vec, + ) -> DispatchResult { + Self::CoreStaking::nominate(pool_account, validators) + } + + /// See [`StakingInterface::chill`]. + fn chill(pool_account: &Self::AccountId) -> DispatchResult { + Self::CoreStaking::chill(pool_account) + } + + /// Pledge `amount` towards `pool_account` and update the pool bond. Also see + /// [`StakingInterface::bond`]. + fn pledge_bond( + who: &Self::AccountId, + pool_account: &Self::AccountId, + reward_account: &Self::AccountId, + amount: Self::Balance, + bond_type: BondType, + ) -> DispatchResult; + + /// See [`StakingInterface::unbond`]. + fn unbond(pool_account: &Self::AccountId, amount: Self::Balance) -> DispatchResult { + Self::CoreStaking::unbond(pool_account, amount) + } + + /// See [`StakingInterface::withdraw_unbonded`]. + fn withdraw_unbonded( + pool_account: &Self::AccountId, + num_slashing_spans: u32, + ) -> Result { + Self::CoreStaking::withdraw_unbonded(pool_account.clone(), num_slashing_spans) + } + + /// Withdraw funds from pool account to member account. + fn member_withdraw( + who: &Self::AccountId, + pool_account: &Self::AccountId, + amount: Self::Balance, + num_slashing_spans: u32, + ) -> DispatchResult; + + /// Check if there is any pending slash for the pool. + fn has_pending_slash(pool_account: &Self::AccountId) -> bool; + + /// Slash the member account with `amount` against pending slashes for the pool. + fn member_slash( + who: &Self::AccountId, + pool_account: &Self::AccountId, + amount: Self::Balance, + maybe_reporter: Option, + ) -> DispatchResult; + + /// Migrate pool account from being a direct nominator to a delegated agent. + /// + /// This is useful for migrating a pool account from [`StakeStrategyType::Transfer`] to + /// [`StakeStrategyType::Delegate`]. + fn migrate_nominator_to_agent( + pool_account: &Self::AccountId, + reward_account: &Self::AccountId, + ) -> DispatchResult; + + /// Migrate member balance from pool account to member account. + /// + /// This is useful for a pool account that migrated from [`StakeStrategyType::Transfer`] to + /// [`StakeStrategyType::Delegate`]. Its members can then migrate their delegated balance + /// back to their account. + /// + /// Internally, the member funds that are locked in the pool account are transferred back and + /// locked in the member account. + fn migrate_delegation( + pool: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + ) -> DispatchResult; + + /// List of validators nominated by the pool account. + #[cfg(feature = "runtime-benchmarks")] + fn nominations(pool_account: &Self::AccountId) -> Option> { + Self::CoreStaking::nominations(pool_account) + } + + /// Remove the pool account as agent. + /// + /// Useful for migrating pool account from a delegated agent to a direct nominator. Only used + /// in tests and benchmarks. + #[cfg(feature = "runtime-benchmarks")] + fn remove_as_agent(_pool: &Self::AccountId) { + // noop by default + } +} + +/// A staking strategy implementation that supports transfer based staking. +/// +/// In order to stake, this adapter transfers the funds from the member/delegator account to the +/// pool account and stakes through the pool account on `Staking`. +/// +/// This is the older Staking strategy used by pools. To switch to the newer [`DelegateStake`] +/// strategy in an existing runtime, storage migration is required. See +/// [`migration::unversioned::DelegationStakeMigration`]. For new runtimes, it is highly recommended +/// to use the [`DelegateStake`] strategy. +pub struct TransferStake(PhantomData<(T, Staking)>); + +impl, AccountId = T::AccountId>> + StakeStrategy for TransferStake +{ + type Balance = BalanceOf; + type AccountId = T::AccountId; + type CoreStaking = Staking; + + fn strategy_type() -> StakeStrategyType { + StakeStrategyType::Transfer + } + + fn transferable_balance(pool_account: &Self::AccountId) -> BalanceOf { + T::Currency::balance(pool_account).saturating_sub(Self::active_stake(pool_account)) + } + + fn total_balance(pool_account: &Self::AccountId) -> BalanceOf { + T::Currency::total_balance(pool_account) + } + + fn member_delegation_balance(_member_account: &T::AccountId) -> Staking::Balance { + // for transfer stake, delegation balance is always zero. + Zero::zero() + } + + fn pledge_bond( + who: &T::AccountId, + pool_account: &Self::AccountId, + reward_account: &Self::AccountId, + amount: BalanceOf, + bond_type: BondType, + ) -> DispatchResult { + match bond_type { + BondType::Create => { + // first bond + T::Currency::transfer(who, pool_account, amount, Preservation::Expendable)?; + Staking::bond(pool_account, amount, &reward_account) + }, + BondType::Extra => { + // additional bond + T::Currency::transfer(who, pool_account, amount, Preservation::Preserve)?; + Staking::bond_extra(pool_account, amount) + }, + } + } + + fn member_withdraw( + who: &T::AccountId, + pool_account: &Self::AccountId, + amount: BalanceOf, + _num_slashing_spans: u32, + ) -> DispatchResult { + T::Currency::transfer(pool_account, &who, amount, Preservation::Expendable)?; + + Ok(()) + } + + fn has_pending_slash(_: &Self::AccountId) -> bool { + // for transfer stake strategy, slashing is greedy and never deferred. + false + } + + fn member_slash( + _who: &T::AccountId, + _pool: &Self::AccountId, + _amount: Staking::Balance, + _maybe_reporter: Option, + ) -> DispatchResult { + Err(Error::::Defensive(DefensiveError::DelegationUnsupported).into()) + } + + fn migrate_nominator_to_agent( + _pool: &Self::AccountId, + _reward_account: &Self::AccountId, + ) -> DispatchResult { + Err(Error::::Defensive(DefensiveError::DelegationUnsupported).into()) + } + + fn migrate_delegation( + _pool: &Self::AccountId, + _delegator: &Self::AccountId, + _value: Self::Balance, + ) -> DispatchResult { + Err(Error::::Defensive(DefensiveError::DelegationUnsupported).into()) + } +} + +/// A staking strategy implementation that supports delegation based staking. +/// +/// In this approach, first the funds are delegated from delegator to the pool account and later +/// staked with `Staking`. The advantage of this approach is that the funds are held in the +/// user account itself and not in the pool account. +/// +/// This is the newer staking strategy used by pools. Once switched to this and migrated, ideally +/// the `TransferStake` strategy should not be used. Or a separate migration would be required for +/// it which is not provided by this pallet. +/// +/// Use [`migration::unversioned::DelegationStakeMigration`] to migrate to this strategy. +pub struct DelegateStake( + PhantomData<(T, Staking, Delegation)>, +); + +impl< + T: Config, + Staking: StakingInterface, AccountId = T::AccountId>, + Delegation: DelegationInterface, AccountId = T::AccountId> + + DelegationMigrator, AccountId = T::AccountId>, + > StakeStrategy for DelegateStake +{ + type Balance = BalanceOf; + type AccountId = T::AccountId; + type CoreStaking = Staking; + + fn strategy_type() -> StakeStrategyType { + StakeStrategyType::Delegate + } + + fn transferable_balance(pool_account: &Self::AccountId) -> BalanceOf { + Delegation::agent_balance(pool_account).saturating_sub(Self::active_stake(pool_account)) + } + + fn total_balance(pool_account: &Self::AccountId) -> BalanceOf { + Delegation::agent_balance(pool_account) + } + + fn member_delegation_balance(member_account: &T::AccountId) -> BalanceOf { + Delegation::delegator_balance(member_account) + } + + fn pledge_bond( + who: &T::AccountId, + pool_account: &Self::AccountId, + reward_account: &Self::AccountId, + amount: BalanceOf, + bond_type: BondType, + ) -> DispatchResult { + match bond_type { + BondType::Create => { + // first delegation + Delegation::delegate(who, pool_account, reward_account, amount) + }, + BondType::Extra => { + // additional delegation + Delegation::delegate_extra(who, pool_account, amount) + }, + } + } + + fn member_withdraw( + who: &T::AccountId, + pool_account: &Self::AccountId, + amount: BalanceOf, + num_slashing_spans: u32, + ) -> DispatchResult { + Delegation::withdraw_delegation(&who, pool_account, amount, num_slashing_spans) + } + + fn has_pending_slash(pool_account: &Self::AccountId) -> bool { + Delegation::has_pending_slash(pool_account) + } + + fn member_slash( + who: &T::AccountId, + pool_account: &Self::AccountId, + amount: BalanceOf, + maybe_reporter: Option, + ) -> DispatchResult { + Delegation::delegator_slash(pool_account, who, amount, maybe_reporter) + } + + fn migrate_nominator_to_agent( + pool: &Self::AccountId, + reward_account: &Self::AccountId, + ) -> DispatchResult { + Delegation::migrate_nominator_to_agent(pool, reward_account) + } + + fn migrate_delegation( + pool: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + ) -> DispatchResult { + Delegation::migrate_delegation(pool, delegator, value) + } + + #[cfg(feature = "runtime-benchmarks")] + fn remove_as_agent(pool: &Self::AccountId) { + Delegation::drop_agent(pool) + } +} diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 0fdb7e3eff5ccca340a5b26f00010e0240377e03..816334c1a084072c7f953b366d0b114316a82d33 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -351,6 +351,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +use adapter::StakeStrategy; use codec::Codec; use frame_support::{ defensive, defensive_assert, ensure, @@ -397,6 +398,7 @@ pub mod mock; #[cfg(test)] mod tests; +pub mod adapter; pub mod migration; pub mod weights; @@ -425,11 +427,11 @@ pub enum ConfigOp { } /// The type of bonding that can happen to a pool. -enum BondType { +pub enum BondType { /// Someone is bonding into the pool upon creation. Create, /// Someone is adding more funds later to this pool. - Later, + Extra, } /// How to increase the bond of a member. @@ -549,9 +551,19 @@ impl PoolMember { /// Total balance of the member, both active and unbonding. /// Doesn't mutate state. - #[cfg(any(feature = "try-runtime", feature = "fuzzing", test, debug_assertions))] - fn total_balance(&self) -> BalanceOf { - let pool = BondedPool::::get(self.pool_id).unwrap(); + /// + /// Worst case, iterates over [`TotalUnbondingPools`] member unbonding pools to calculate member + /// balance. + pub fn total_balance(&self) -> BalanceOf { + let pool = match BondedPool::::get(self.pool_id) { + Some(pool) => pool, + None => { + // this internal function is always called with a valid pool id. + defensive!("pool should exist; qed"); + return Zero::zero(); + }, + }; + let active_balance = pool.points_to_balance(self.active_points()); let sub_pools = match SubPoolsStorage::::get(self.pool_id) { @@ -973,12 +985,12 @@ impl BondedPool { /// Get the bonded account id of this pool. fn bonded_account(&self) -> T::AccountId { - Pallet::::create_bonded_account(self.id) + Pallet::::generate_bonded_account(self.id) } /// Get the reward account id of this pool. fn reward_account(&self) -> T::AccountId { - Pallet::::create_reward_account(self.id) + Pallet::::generate_reward_account(self.id) } /// Consume self and put into storage. @@ -995,8 +1007,7 @@ impl BondedPool { /// /// This is often used for bonding and issuing new funds into the pool. fn balance_to_point(&self, new_funds: BalanceOf) -> BalanceOf { - let bonded_balance = - T::Staking::active_stake(&self.bonded_account()).unwrap_or(Zero::zero()); + let bonded_balance = T::StakeAdapter::active_stake(&self.bonded_account()); Pallet::::balance_to_point(bonded_balance, self.points, new_funds) } @@ -1004,8 +1015,7 @@ impl BondedPool { /// /// This is often used for unbonding. fn points_to_balance(&self, points: BalanceOf) -> BalanceOf { - let bonded_balance = - T::Staking::active_stake(&self.bonded_account()).unwrap_or(Zero::zero()); + let bonded_balance = T::StakeAdapter::active_stake(&self.bonded_account()); Pallet::::point_to_balance(bonded_balance, self.points, points) } @@ -1052,18 +1062,6 @@ impl BondedPool { self } - /// The pools balance that is transferable provided it is expendable by staking pallet. - fn transferable_balance(&self) -> BalanceOf { - let account = self.bonded_account(); - // Note on why we can't use `Currency::reducible_balance`: Since pooled account has a - // provider (staking pallet), the account can not be set expendable by - // `pallet-nomination-pool`. This means reducible balance always returns balance preserving - // ED in the account. What we want though is transferable balance given the account can be - // dusted. - T::Currency::balance(&account) - .saturating_sub(T::Staking::active_stake(&account).unwrap_or_default()) - } - fn is_root(&self, who: &T::AccountId) -> bool { self.roles.root.as_ref().map_or(false, |root| root == who) } @@ -1127,8 +1125,7 @@ impl BondedPool { fn ok_to_be_open(&self) -> Result<(), DispatchError> { ensure!(!self.is_destroying(), Error::::CanNotChangeState); - let bonded_balance = - T::Staking::active_stake(&self.bonded_account()).unwrap_or(Zero::zero()); + let bonded_balance = T::StakeAdapter::active_stake(&self.bonded_account()); ensure!(!bonded_balance.is_zero(), Error::::OverflowRisk); let points_to_balance_ratio_floor = self @@ -1257,28 +1254,17 @@ impl BondedPool { amount: BalanceOf, ty: BondType, ) -> Result, DispatchError> { - // Cache the value - let bonded_account = self.bonded_account(); - T::Currency::transfer( - who, - &bonded_account, - amount, - match ty { - BondType::Create => Preservation::Expendable, - BondType::Later => Preservation::Preserve, - }, - )?; // We must calculate the points issued *before* we bond who's funds, else points:balance // ratio will be wrong. let points_issued = self.issue(amount); - match ty { - BondType::Create => T::Staking::bond(&bonded_account, amount, &self.reward_account())?, - // The pool should always be created in such a way its in a state to bond extra, but if - // the active balance is slashed below the minimum bonded or the account cannot be - // found, we exit early. - BondType::Later => T::Staking::bond_extra(&bonded_account, amount)?, - } + T::StakeAdapter::pledge_bond( + who, + &self.bonded_account(), + &self.reward_account(), + amount, + ty, + )?; TotalValueLocked::::mutate(|tvl| { tvl.saturating_accrue(amount); }); @@ -1456,7 +1442,7 @@ impl RewardPool { /// This is sum of all the rewards that are claimable by pool members. fn current_balance(id: PoolId) -> BalanceOf { T::Currency::reducible_balance( - &Pallet::::create_reward_account(id), + &Pallet::::generate_reward_account(id), Preservation::Expendable, Fortitude::Polite, ) @@ -1569,7 +1555,7 @@ impl Get for TotalUnbondingPools { // NOTE: this may be dangerous in the scenario bonding_duration gets decreased because // we would no longer be able to decode `BoundedBTreeMap::, // TotalUnbondingPools>`, which uses `TotalUnbondingPools` as the bound - T::Staking::bonding_duration() + T::PostUnbondingPoolsWindow::get() + T::StakeAdapter::bonding_duration() + T::PostUnbondingPoolsWindow::get() } } @@ -1646,7 +1632,9 @@ pub mod pallet { type U256ToBalance: Convert>; /// The interface for nominating. - type Staking: StakingInterface, AccountId = Self::AccountId>; + /// + /// Note: Switching to a new [`StakeStrategy`] might require a migration of the storage. + type StakeAdapter: StakeStrategy>; /// The amount of eras a `SubPools::with_era` pool can exist before it gets merged into the /// `SubPools::no_era` pool. In other words, this is the amount of eras a member will be @@ -1950,6 +1938,16 @@ pub mod pallet { BondExtraRestricted, /// No imbalance in the ED deposit for the pool. NothingToAdjust, + /// No slash pending that can be applied to the member. + NothingToSlash, + /// No delegation to migrate. + NoDelegationToMigrate, + /// The pool has already migrated to enable delegation. + PoolAlreadyMigrated, + /// The pool has not migrated yet to enable delegation. + PoolNotMigrated, + /// This call is not allowed in the current state of the pallet. + NotSupported, } #[derive(Encode, Decode, PartialEq, TypeInfo, PalletError, RuntimeDebug)] @@ -1965,6 +1963,10 @@ pub mod pallet { /// The bonded account should only be killed by the staking system when the depositor is /// withdrawing BondedStashKilledPrematurely, + /// The delegation feature is unsupported. + DelegationUnsupported, + /// Unable to slash to the member of the pool. + SlashNotApplied, } impl From for Error { @@ -2019,7 +2021,7 @@ pub mod pallet { )?; bonded_pool.try_inc_members()?; - let points_issued = bonded_pool.try_bond_funds(&who, amount, BondType::Later)?; + let points_issued = bonded_pool.try_bond_funds(&who, amount, BondType::Extra)?; PoolMembers::insert( who.clone(), @@ -2141,12 +2143,12 @@ pub mod pallet { &mut reward_pool, )?; - let current_era = T::Staking::current_era(); - let unbond_era = T::Staking::bonding_duration().saturating_add(current_era); + let current_era = T::StakeAdapter::current_era(); + let unbond_era = T::StakeAdapter::bonding_duration().saturating_add(current_era); // Unbond in the actual underlying nominator. let unbonding_balance = bonded_pool.dissolve(unbonding_points); - T::Staking::unbond(&bonded_pool.bonded_account(), unbonding_balance)?; + T::StakeAdapter::unbond(&bonded_pool.bonded_account(), unbonding_balance)?; // Note that we lazily create the unbonding pools here if they don't already exist let mut sub_pools = SubPoolsStorage::::get(member.pool_id) @@ -2209,7 +2211,7 @@ pub mod pallet { // For now we only allow a pool to withdraw unbonded if its not destroying. If the pool // is destroying then `withdraw_unbonded` can be used. ensure!(pool.state != PoolState::Destroying, Error::::NotDestroying); - T::Staking::withdraw_unbonded(pool.bonded_account(), num_slashing_spans)?; + T::StakeAdapter::withdraw_unbonded(&pool.bonded_account(), num_slashing_spans)?; Ok(()) } @@ -2232,7 +2234,10 @@ pub mod pallet { /// /// # Note /// - /// If the target is the depositor, the pool will be destroyed. + /// - If the target is the depositor, the pool will be destroyed. + /// - If the pool has any pending slash, we also try to slash the member before letting them + /// withdraw. This calculation adds some weight overhead and is only defensive. In reality, + /// pool slashes must have been already applied via permissionless [`Call::apply_slash`]. #[pallet::call_index(5)] #[pallet::weight( T::WeightInfo::withdraw_unbonded_kill(*num_slashing_spans) @@ -2246,23 +2251,43 @@ pub mod pallet { let member_account = T::Lookup::lookup(member_account)?; let mut member = PoolMembers::::get(&member_account).ok_or(Error::::PoolMemberNotFound)?; - let current_era = T::Staking::current_era(); + let current_era = T::StakeAdapter::current_era(); let bonded_pool = BondedPool::::get(member.pool_id) .defensive_ok_or::>(DefensiveError::PoolNotFound.into())?; let mut sub_pools = SubPoolsStorage::::get(member.pool_id).ok_or(Error::::SubPoolsNotFound)?; + let slash_weight = + // apply slash if any before withdraw. + match Self::do_apply_slash(&member_account, None) { + Ok(_) => T::WeightInfo::apply_slash(), + Err(e) => { + let no_pending_slash: DispatchResult = Err(Error::::NothingToSlash.into()); + // This is an expected error. We add appropriate fees and continue withdrawal. + if Err(e) == no_pending_slash { + T::WeightInfo::apply_slash_fail() + } else { + // defensive: if we can't apply slash for some reason, we abort. + return Err(Error::::Defensive(DefensiveError::SlashNotApplied).into()); + } + } + + }; + bonded_pool.ok_to_withdraw_unbonded_with(&caller, &member_account)?; + let pool_account = bonded_pool.bonded_account(); // NOTE: must do this after we have done the `ok_to_withdraw_unbonded_other_with` check. let withdrawn_points = member.withdraw_unlocked(current_era); ensure!(!withdrawn_points.is_empty(), Error::::CannotWithdrawAny); // Before calculating the `balance_to_unbond`, we call withdraw unbonded to ensure the - // `transferrable_balance` is correct. - let stash_killed = - T::Staking::withdraw_unbonded(bonded_pool.bonded_account(), num_slashing_spans)?; + // `transferable_balance` is correct. + let stash_killed = T::StakeAdapter::withdraw_unbonded( + &bonded_pool.bonded_account(), + num_slashing_spans, + )?; // defensive-only: the depositor puts enough funds into the stash so that it will only // be destroyed when they are leaving. @@ -2271,6 +2296,20 @@ pub mod pallet { Error::::Defensive(DefensiveError::BondedStashKilledPrematurely) ); + if stash_killed { + // Maybe an extra consumer left on the pool account, if so, remove it. + if frame_system::Pallet::::consumers(&pool_account) == 1 { + frame_system::Pallet::::dec_consumers(&pool_account); + } + + // Note: This is not pretty, but we have to do this because of a bug where old pool + // accounts might have had an extra consumer increment. We know at this point no + // other pallet should depend on pool account so safe to do this. + // Refer to following issues: + // - https://github.com/paritytech/polkadot-sdk/issues/4440 + // - https://github.com/paritytech/polkadot-sdk/issues/2037 + } + let mut sum_unlocked_points: BalanceOf = Zero::zero(); let balance_to_unbond = withdrawn_points .iter() @@ -2295,15 +2334,16 @@ pub mod pallet { // don't exist. This check is also defensive in cases where the unbond pool does not // update its balance (e.g. a bug in the slashing hook.) We gracefully proceed in // order to ensure members can leave the pool and it can be destroyed. - .min(bonded_pool.transferable_balance()); + .min(T::StakeAdapter::transferable_balance(&bonded_pool.bonded_account())); - T::Currency::transfer( - &bonded_pool.bonded_account(), + // this can fail if the pool uses `DelegateStake` strategy and the member delegation + // is not claimed yet. See `Call::migrate_delegation()`. + T::StakeAdapter::member_withdraw( &member_account, + &bonded_pool.bonded_account(), balance_to_unbond, - Preservation::Expendable, - ) - .defensive()?; + num_slashing_spans, + )?; Self::deposit_event(Event::::Withdrawn { member: member_account.clone(), @@ -2325,20 +2365,20 @@ pub mod pallet { if member_account == bonded_pool.roles.depositor { Pallet::::dissolve_pool(bonded_pool); - None + Weight::default() } else { bonded_pool.dec_members().put(); SubPoolsStorage::::insert(member.pool_id, sub_pools); - Some(T::WeightInfo::withdraw_unbonded_update(num_slashing_spans)) + T::WeightInfo::withdraw_unbonded_update(num_slashing_spans) } } else { // we certainly don't need to delete any pools, because no one is being removed. SubPoolsStorage::::insert(member.pool_id, sub_pools); PoolMembers::::insert(&member_account, member); - Some(T::WeightInfo::withdraw_unbonded_update(num_slashing_spans)) + T::WeightInfo::withdraw_unbonded_update(num_slashing_spans) }; - Ok(post_info_weight.into()) + Ok(Some(post_info_weight.saturating_add(slash_weight)).into()) } /// Create a new delegation pool. @@ -2433,7 +2473,7 @@ pub mod pallet { Error::::MinimumBondNotMet ); - T::Staking::nominate(&bonded_pool.bonded_account(), validators) + T::StakeAdapter::nominate(&bonded_pool.bonded_account(), validators) } /// Set a new state for the pool. @@ -2621,12 +2661,12 @@ pub mod pallet { .active_points(); if bonded_pool.points_to_balance(depositor_points) >= - T::Staking::minimum_nominator_bond() + T::StakeAdapter::minimum_nominator_bond() { ensure!(bonded_pool.can_nominate(&who), Error::::NotNominator); } - T::Staking::chill(&bonded_pool.bonded_account()) + T::StakeAdapter::chill(&bonded_pool.bonded_account()) } /// `origin` bonds funds from `extra` for some pool member `member` into their respective @@ -2823,6 +2863,119 @@ pub mod pallet { Ok(()) } + + /// Apply a pending slash on a member. + /// + /// Fails unless [`crate::pallet::Config::StakeAdapter`] is of strategy type: + /// [`adapter::StakeStrategyType::Delegate`]. + /// + /// This call can be dispatched permissionlessly (i.e. by any account). If the member has + /// slash to be applied, caller may be rewarded with the part of the slash. + #[pallet::call_index(23)] + #[pallet::weight(T::WeightInfo::apply_slash())] + pub fn apply_slash( + origin: OriginFor, + member_account: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { + ensure!( + T::StakeAdapter::strategy_type() == adapter::StakeStrategyType::Delegate, + Error::::NotSupported + ); + + let who = ensure_signed(origin)?; + let member_account = T::Lookup::lookup(member_account)?; + Self::do_apply_slash(&member_account, Some(who))?; + + // If successful, refund the fees. + Ok(Pays::No.into()) + } + + /// Migrates delegated funds from the pool account to the `member_account`. + /// + /// Fails unless [`crate::pallet::Config::StakeAdapter`] is of strategy type: + /// [`adapter::StakeStrategyType::Delegate`]. + /// + /// This is a permission-less call and refunds any fee if claim is successful. + /// + /// If the pool has migrated to delegation based staking, the staked tokens of pool members + /// can be moved and held in their own account. See [`adapter::DelegateStake`] + #[pallet::call_index(24)] + #[pallet::weight(T::WeightInfo::migrate_delegation())] + pub fn migrate_delegation( + origin: OriginFor, + member_account: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { + let _caller = ensure_signed(origin)?; + + ensure!( + T::StakeAdapter::strategy_type() == adapter::StakeStrategyType::Delegate, + Error::::NotSupported + ); + + let member_account = T::Lookup::lookup(member_account)?; + let member = + PoolMembers::::get(&member_account).ok_or(Error::::PoolMemberNotFound)?; + + // ensure pool is migrated. + ensure!( + T::StakeAdapter::pool_strategy(&Self::generate_bonded_account(member.pool_id)) == + adapter::StakeStrategyType::Delegate, + Error::::PoolNotMigrated + ); + + let pool_contribution = member.total_balance(); + ensure!(pool_contribution >= MinJoinBond::::get(), Error::::MinimumBondNotMet); + // the member must have some contribution to be migrated. + ensure!(pool_contribution > Zero::zero(), Error::::NoDelegationToMigrate); + + let delegation = T::StakeAdapter::member_delegation_balance(&member_account); + // delegation can be claimed only once. + ensure!(delegation == Zero::zero(), Error::::NoDelegationToMigrate); + + let diff = pool_contribution.defensive_saturating_sub(delegation); + T::StakeAdapter::migrate_delegation( + &Pallet::::generate_bonded_account(member.pool_id), + &member_account, + diff, + )?; + + // if successful, we refund the fee. + Ok(Pays::No.into()) + } + + /// Migrate pool from [`adapter::StakeStrategyType::Transfer`] to + /// [`adapter::StakeStrategyType::Delegate`]. + /// + /// Fails unless [`crate::pallet::Config::StakeAdapter`] is of strategy type: + /// [`adapter::StakeStrategyType::Delegate`]. + /// + /// This call can be dispatched permissionlessly, and refunds any fee if successful. + /// + /// If the pool has already migrated to delegation based staking, this call will fail. + #[pallet::call_index(25)] + #[pallet::weight(T::WeightInfo::pool_migrate())] + pub fn migrate_pool_to_delegate_stake( + origin: OriginFor, + pool_id: PoolId, + ) -> DispatchResultWithPostInfo { + // gate this call to be called only if `DelegateStake` strategy is used. + ensure!( + T::StakeAdapter::strategy_type() == adapter::StakeStrategyType::Delegate, + Error::::NotSupported + ); + + let _caller = ensure_signed(origin)?; + // ensure pool exists. + let bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; + ensure!( + T::StakeAdapter::pool_strategy(&bonded_pool.bonded_account()) == + adapter::StakeStrategyType::Transfer, + Error::::PoolAlreadyMigrated + ); + + Self::migrate_to_delegate_stake(pool_id)?; + Ok(Pays::No.into()) + } } #[pallet::hooks] @@ -2838,7 +2991,7 @@ pub mod pallet { "Minimum points to balance ratio must be greater than 0" ); assert!( - T::Staking::bonding_duration() < TotalUnbondingPools::::get(), + T::StakeAdapter::bonding_duration() < TotalUnbondingPools::::get(), "There must be more unbonding pools then the bonding duration / so a slash can be applied to relevant unbonding pools. (We assume / the bonding duration > slash deffer duration.", @@ -2856,7 +3009,7 @@ impl Pallet { /// It is essentially `max { MinNominatorBond, MinCreateBond, MinJoinBond }`, where the former /// is coming from the staking pallet and the latter two are configured in this pallet. pub fn depositor_min_bond() -> BalanceOf { - T::Staking::minimum_nominator_bond() + T::StakeAdapter::minimum_nominator_bond() .max(MinCreateBond::::get()) .max(MinJoinBond::::get()) .max(T::Currency::minimum_balance()) @@ -2892,7 +3045,7 @@ impl Pallet { "bonded account of dissolving pool should have no consumers" ); defensive_assert!( - T::Staking::total_stake(&bonded_account).unwrap_or_default() == Zero::zero(), + T::StakeAdapter::total_stake(&bonded_pool.bonded_account()) == Zero::zero(), "dissolving pool should not have any stake in the staking pallet" ); @@ -2915,11 +3068,12 @@ impl Pallet { "could not transfer all amount to depositor while dissolving pool" ); defensive_assert!( - T::Currency::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), + T::StakeAdapter::total_balance(&bonded_pool.bonded_account()) == Zero::zero(), "dissolving pool should not have any balance" ); // NOTE: Defensively force set balance to zero. T::Currency::set_balance(&reward_account, Zero::zero()); + // With `DelegateStake` strategy, this won't do anything. T::Currency::set_balance(&bonded_pool.bonded_account(), Zero::zero()); Self::deposit_event(Event::::Destroyed { pool_id: bonded_pool.id }); @@ -2930,12 +3084,19 @@ impl Pallet { } /// Create the main, bonded account of a pool with the given id. - pub fn create_bonded_account(id: PoolId) -> T::AccountId { + pub fn generate_bonded_account(id: PoolId) -> T::AccountId { T::PalletId::get().into_sub_account_truncating((AccountType::Bonded, id)) } + fn migrate_to_delegate_stake(id: PoolId) -> DispatchResult { + T::StakeAdapter::migrate_nominator_to_agent( + &Self::generate_bonded_account(id), + &Self::generate_reward_account(id), + ) + } + /// Create the reward account of a pool with the given id. - pub fn create_reward_account(id: PoolId) -> T::AccountId { + pub fn generate_reward_account(id: PoolId) -> T::AccountId { // NOTE: in order to have a distinction in the test account id type (u128), we put // account_type first so it does not get truncated out. T::PalletId::get().into_sub_account_truncating((AccountType::Reward, id)) @@ -3179,9 +3340,9 @@ impl Pallet { let (points_issued, bonded) = match extra { BondExtra::FreeBalance(amount) => - (bonded_pool.try_bond_funds(&member_account, amount, BondType::Later)?, amount), + (bonded_pool.try_bond_funds(&member_account, amount, BondType::Extra)?, amount), BondExtra::Rewards => - (bonded_pool.try_bond_funds(&member_account, claimed, BondType::Later)?, claimed), + (bonded_pool.try_bond_funds(&member_account, claimed, BondType::Extra)?, claimed), }; bonded_pool.ok_to_be_open()?; @@ -3302,6 +3463,36 @@ impl Pallet { Ok(()) } + /// Slash member against the pending slash for the pool. + fn do_apply_slash( + member_account: &T::AccountId, + reporter: Option, + ) -> DispatchResult { + // calculate points to be slashed. + let member = + PoolMembers::::get(&member_account).ok_or(Error::::PoolMemberNotFound)?; + + let pool_account = Pallet::::generate_bonded_account(member.pool_id); + ensure!(T::StakeAdapter::has_pending_slash(&pool_account), Error::::NothingToSlash); + + let unslashed_balance = T::StakeAdapter::member_delegation_balance(&member_account); + let slashed_balance = member.total_balance(); + defensive_assert!( + unslashed_balance >= slashed_balance, + "unslashed balance should always be greater or equal to the slashed" + ); + + // if nothing to slash, return error. + ensure!(unslashed_balance > slashed_balance, Error::::NothingToSlash); + + T::StakeAdapter::member_slash( + &member_account, + &pool_account, + unslashed_balance.defensive_saturating_sub(slashed_balance), + reporter, + ) + } + /// Apply freeze on reward account to restrict it from going below ED. pub(crate) fn freeze_pool_deposit(reward_acc: &T::AccountId) -> DispatchResult { T::Currency::set_freeze( @@ -3380,7 +3571,7 @@ impl Pallet { ); for id in reward_pools { - let account = Self::create_reward_account(id); + let account = Self::generate_reward_account(id); if T::Currency::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite) < T::Currency::minimum_balance() { @@ -3465,8 +3656,7 @@ impl Pallet { pool is being destroyed and the depositor is the last member", ); - expected_tvl += - T::Staking::total_stake(&bonded_pool.bonded_account()).unwrap_or_default(); + expected_tvl += T::StakeAdapter::total_stake(&bonded_pool.bonded_account()); Ok(()) })?; @@ -3491,19 +3681,28 @@ impl Pallet { } for (pool_id, _pool) in BondedPools::::iter() { - let pool_account = Pallet::::create_bonded_account(pool_id); + let pool_account = Pallet::::generate_bonded_account(pool_id); let subs = SubPoolsStorage::::get(pool_id).unwrap_or_default(); let sum_unbonding_balance = subs.sum_unbonding_balance(); - let bonded_balance = T::Staking::active_stake(&pool_account).unwrap_or_default(); - let total_balance = T::Currency::total_balance(&pool_account); + let bonded_balance = T::StakeAdapter::active_stake(&pool_account); + let total_balance = T::StakeAdapter::total_balance(&pool_account); + + // At the time when StakeAdapter is changed but migration is not yet done, the new + // adapter would return zero balance (as it is not an agent yet). We handle that by + // falling back to reading actual balance of the pool account. + let pool_balance = if total_balance.is_zero() { + T::Currency::total_balance(&pool_account) + } else { + total_balance + }; assert!( - total_balance >= bonded_balance + sum_unbonding_balance, - "faulty pool: {:?} / {:?}, total_balance {:?} >= bonded_balance {:?} + sum_unbonding_balance {:?}", + pool_balance >= bonded_balance + sum_unbonding_balance, + "faulty pool: {:?} / {:?}, pool_balance {:?} >= bonded_balance {:?} + sum_unbonding_balance {:?}", pool_id, _pool, - total_balance, + pool_balance, bonded_balance, sum_unbonding_balance ); @@ -3529,7 +3728,7 @@ impl Pallet { pub fn check_ed_imbalance() -> Result<(), DispatchError> { let mut failed: u32 = 0; BondedPools::::iter_keys().for_each(|id| { - let reward_acc = Self::create_reward_account(id); + let reward_acc = Self::generate_reward_account(id); let frozen_balance = T::Currency::balance_frozen(&FreezeReason::PoolMinBalance.into(), &reward_acc); @@ -3600,7 +3799,7 @@ impl Pallet { pub fn api_balance_to_points(pool_id: PoolId, new_funds: BalanceOf) -> BalanceOf { if let Some(pool) = BondedPool::::get(pool_id) { let bonded_balance = - T::Staking::active_stake(&pool.bonded_account()).unwrap_or(Zero::zero()); + T::StakeAdapter::active_stake(&Self::generate_bonded_account(pool_id)); Pallet::::balance_to_point(bonded_balance, pool.points, new_funds) } else { Zero::zero() diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 796b310862afcb8b897d4dafd66395e33e1970fb..a3989559dfbb01a0f13f53944e34f578c4d87cfd 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -107,6 +107,137 @@ pub mod unversioned { Ok(()) } } + + /// Migrate existing pools from [`adapter::StakeStrategyType::Transfer`] to + /// [`adapter::StakeStrategyType::Delegate`]. + /// + /// Note: This only migrates the pools, the members are not migrated. They can use the + /// permission-less [`Pallet::migrate_delegation()`] to migrate their funds. + /// + /// This migration does not break any existing pool storage item, does not need to happen in any + /// sequence and hence can be applied unversioned on a production runtime. + /// + /// Takes `MaxPools` as type parameter to limit the number of pools that should be migrated in a + /// single block. It should be set such that migration weight does not exceed the block weight + /// limit. If all pools can be safely migrated, it is good to keep this number a little higher + /// than the actual number of pools to handle any extra pools created while the migration is + /// proposed, and before it is executed. + /// + /// If there are pools that fail to migrate or did not fit in the bounds, the remaining pools + /// can be migrated via the permission-less extrinsic [`Call::migrate_pool_to_delegate_stake`]. + pub struct DelegationStakeMigration(sp_std::marker::PhantomData<(T, MaxPools)>); + + impl> OnRuntimeUpgrade for DelegationStakeMigration { + fn on_runtime_upgrade() -> Weight { + let mut count: u32 = 0; + + BondedPools::::iter_keys().take(MaxPools::get() as usize).for_each(|id| { + let pool_acc = Pallet::::generate_bonded_account(id); + + // only migrate if the pool is in Transfer Strategy. + if T::StakeAdapter::pool_strategy(&pool_acc) == adapter::StakeStrategyType::Transfer + { + let _ = Pallet::::migrate_to_delegate_stake(id).map_err(|err| { + log!( + warn, + "failed to migrate pool {:?} to delegate stake strategy with err: {:?}", + id, + err + ) + }); + count.saturating_inc(); + } + }); + + log!(info, "migrated {:?} pools to delegate stake strategy", count); + + // reads: (bonded pool key + current pool strategy) * MaxPools (worst case) + T::DbWeight::get() + .reads_writes(2, 0) + .saturating_mul(MaxPools::get() as u64) + // migration weight: `pool_migrate` weight * count + .saturating_add(T::WeightInfo::pool_migrate().saturating_mul(count.into())) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + // ensure stake adapter is correct. + ensure!( + T::StakeAdapter::strategy_type() == adapter::StakeStrategyType::Delegate, + "Current strategy is not `Delegate" + ); + + if BondedPools::::count() > MaxPools::get() { + // we log a warning if the number of pools exceeds the bound. + log!( + warn, + "Number of pools {} exceeds the maximum bound {}. This would leave some pools unmigrated.", BondedPools::::count(), MaxPools::get() + ); + } + + let mut pool_balances: Vec> = Vec::new(); + BondedPools::::iter_keys().take(MaxPools::get() as usize).for_each(|id| { + let pool_account = Pallet::::generate_bonded_account(id); + let current_strategy = T::StakeAdapter::pool_strategy(&pool_account); + + // we ensure migration is idempotent. + let pool_balance = if current_strategy == adapter::StakeStrategyType::Transfer { + T::Currency::total_balance(&pool_account) + } else { + T::StakeAdapter::total_balance(&pool_account) + }; + + pool_balances.push(pool_balance); + }); + + Ok(pool_balances.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(data: Vec) -> Result<(), TryRuntimeError> { + let expected_pool_balances: Vec> = Decode::decode(&mut &data[..]).unwrap(); + + for (index, id) in + BondedPools::::iter_keys().take(MaxPools::get() as usize).enumerate() + { + let pool_account = Pallet::::generate_bonded_account(id); + if T::StakeAdapter::pool_strategy(&pool_account) == + adapter::StakeStrategyType::Transfer + { + log!(error, "Pool {} failed to migrate", id,); + return Err(TryRuntimeError::Other("Pool failed to migrate")); + } + + let actual_balance = T::StakeAdapter::total_balance(&pool_account); + let expected_balance = expected_pool_balances.get(index).unwrap(); + + if actual_balance != *expected_balance { + log!( + error, + "Pool {} balance mismatch. Expected: {:?}, Actual: {:?}", + id, + expected_balance, + actual_balance + ); + return Err(TryRuntimeError::Other("Pool balance mismatch")); + } + + // account balance should be zero. + let pool_account_balance = T::Currency::total_balance(&pool_account); + if pool_account_balance != Zero::zero() { + log!( + error, + "Pool account balance was expected to be zero. Pool: {}, Balance: {:?}", + id, + pool_account_balance + ); + return Err(TryRuntimeError::Other("Pool account balance not migrated")); + } + } + + Ok(()) + } + } } pub mod v8 { @@ -201,7 +332,7 @@ pub(crate) mod v7 { impl V7BondedPool { #[allow(dead_code)] fn bonded_account(&self) -> T::AccountId { - Pallet::::create_bonded_account(self.id) + Pallet::::generate_bonded_account(self.id) } } @@ -275,7 +406,7 @@ mod v6 { impl MigrateToV6 { fn freeze_ed(pool_id: PoolId) -> Result<(), ()> { - let reward_acc = Pallet::::create_reward_account(pool_id); + let reward_acc = Pallet::::generate_reward_account(pool_id); Pallet::::freeze_pool_deposit(&reward_acc).map_err(|e| { log!(error, "Failed to freeze ED for pool {} with error: {:?}", pool_id, e); () @@ -760,7 +891,7 @@ pub mod v2 { }; let accumulated_reward = RewardPool::::current_balance(id); - let reward_account = Pallet::::create_reward_account(id); + let reward_account = Pallet::::generate_reward_account(id); let mut sum_paid_out = BalanceOf::::zero(); members @@ -882,7 +1013,7 @@ pub mod v2 { // all reward accounts must have more than ED. RewardPools::::iter().try_for_each(|(id, _)| -> Result<(), TryRuntimeError> { ensure!( - >::balance(&Pallet::::create_reward_account(id)) >= + >::balance(&Pallet::::generate_reward_account(id)) >= T::Currency::minimum_balance(), "Reward accounts must have greater balance than ED." ); @@ -1022,11 +1153,8 @@ mod helpers { use super::*; pub(crate) fn calculate_tvl_by_total_stake() -> BalanceOf { - BondedPools::::iter() - .map(|(id, inner)| { - T::Staking::total_stake(&BondedPool { id, inner: inner.clone() }.bonded_account()) - .unwrap_or_default() - }) + BondedPools::::iter_keys() + .map(|id| T::StakeAdapter::total_stake(&Pallet::::generate_bonded_account(id))) .reduce(|acc, total_balance| acc + total_balance) .unwrap_or_default() } diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 686402b843492e8f92bb26231a7ed3becf0c0e03..b659c975a8395c0d8afb486909da3695a28ba102 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -36,12 +36,12 @@ pub type Currency = ::Currency; // Ext builder creates a pool with id 1. pub fn default_bonded_account() -> AccountId { - Pools::create_bonded_account(1) + Pools::generate_bonded_account(1) } // Ext builder creates a pool with id 1. pub fn default_reward_account() -> AccountId { - Pools::create_reward_account(1) + Pools::generate_reward_account(1) } parameter_types! { @@ -71,7 +71,7 @@ impl StakingMock { /// Does not modify any [`SubPools`] of the pool as [`Default::default`] is passed for /// `slashed_unlocking`. pub fn slash_by(pool_id: PoolId, amount: Balance) { - let acc = Pools::create_bonded_account(pool_id); + let acc = Pools::generate_bonded_account(pool_id); let bonded = BondedBalanceMap::get(); let pre_total = bonded.get(&acc).unwrap(); Self::set_bonded_balance(acc, pre_total - amount); @@ -111,6 +111,10 @@ impl sp_staking::StakingInterface for StakingMock { .ok_or(DispatchError::Other("NotStash")) } + fn is_virtual_staker(_who: &Self::AccountId) -> bool { + false + } + fn bond_extra(who: &Self::AccountId, extra: Self::Balance) -> DispatchResult { let mut x = BondedBalanceMap::get(); x.get_mut(who).map(|v| *v += extra); @@ -160,7 +164,8 @@ impl sp_staking::StakingInterface for StakingMock { Pools::on_withdraw(&who, unlocking_before.saturating_sub(unlocking(&staker_map))); UnbondingBalanceMap::set(&unbonding_map); - Ok(UnbondingBalanceMap::get().is_empty() && BondedBalanceMap::get().is_empty()) + Ok(UnbondingBalanceMap::get().get(&who).unwrap().is_empty() && + BondedBalanceMap::get().get(&who).unwrap().is_zero()) } fn bond(stash: &Self::AccountId, value: Self::Balance, _: &Self::AccountId) -> DispatchResult { @@ -313,7 +318,7 @@ impl pools::Config for Runtime { type RewardCounter = RewardCounter; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = StakingMock; + type StakeAdapter = adapter::TransferStake; type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; type PalletId = PoolsPalletId; type MaxMetadataLen = MaxMetadataLen; diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index f6ef1e6eaac217816e410bc85a837f30bda179f4..8fc339c695bde447f950a946f6001392c496f333 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -95,8 +95,8 @@ fn test_setup_works() { PoolMember:: { pool_id: last_pool, points: 10, ..Default::default() } ); - let bonded_account = Pools::create_bonded_account(last_pool); - let reward_account = Pools::create_reward_account(last_pool); + let bonded_account = Pools::generate_bonded_account(last_pool); + let reward_account = Pools::generate_reward_account(last_pool); // the bonded_account should be bonded by the depositor's funds. assert_eq!(StakingMock::active_stake(&bonded_account).unwrap(), 10); @@ -728,7 +728,7 @@ mod join { ); // Force the pools bonded balance to 0, simulating a 100% slash - StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 0); + StakingMock::set_bonded_balance(Pools::generate_bonded_account(1), 0); assert_noop!( Pools::join(RuntimeOrigin::signed(11), 420, 1), Error::::OverflowRisk @@ -755,7 +755,7 @@ mod join { <::MaxPointsToBalance as Get>::get().into(); StakingMock::set_bonded_balance( - Pools::create_bonded_account(123), + Pools::generate_bonded_account(123), max_points_to_balance, ); assert_noop!( @@ -764,7 +764,7 @@ mod join { ); StakingMock::set_bonded_balance( - Pools::create_bonded_account(123), + Pools::generate_bonded_account(123), Balance::MAX / max_points_to_balance, ); // Balance needs to be gt Balance::MAX / `MaxPointsToBalance` @@ -773,7 +773,10 @@ mod join { TokenError::FundsUnavailable, ); - StakingMock::set_bonded_balance(Pools::create_bonded_account(1), max_points_to_balance); + StakingMock::set_bonded_balance( + Pools::generate_bonded_account(1), + max_points_to_balance, + ); // Cannot join a pool that isn't open unsafe_set_state(123, PoolState::Blocked); @@ -804,7 +807,7 @@ mod join { #[cfg_attr(not(debug_assertions), should_panic)] fn join_panics_when_reward_pool_not_found() { ExtBuilder::default().build_and_execute(|| { - StakingMock::set_bonded_balance(Pools::create_bonded_account(123), 100); + StakingMock::set_bonded_balance(Pools::generate_bonded_account(123), 100); BondedPool:: { id: 123, inner: BondedPoolInner { @@ -1979,7 +1982,7 @@ mod claim_payout { assert_eq!(member_20.last_recorded_reward_counter, 0.into()); // pre-fund the reward account of pool id 3 with some funds. - Currency::set_balance(&Pools::create_reward_account(3), 10); + Currency::set_balance(&Pools::generate_reward_account(3), 10); // create pool 3 Currency::set_balance(&30, 100); @@ -1988,7 +1991,7 @@ mod claim_payout { // reward counter is still the same. let (member_30, _, reward_pool_30) = Pools::get_member_with_pools(&30).unwrap(); assert_eq!( - Currency::free_balance(&Pools::create_reward_account(3)), + Currency::free_balance(&Pools::generate_reward_account(3)), 10 + Currency::minimum_balance() ); @@ -4594,6 +4597,92 @@ mod withdraw_unbonded { assert_eq!(ClaimPermissions::::contains_key(20), false); }); } + + #[test] + fn destroy_works_without_erroneous_extra_consumer() { + ExtBuilder::default().ed(1).build_and_execute(|| { + // 10 is the depositor for pool 1, with min join bond 10. + // set pool to destroying. + unsafe_set_state(1, PoolState::Destroying); + + // set current era + CurrentEra::set(1); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10)); + + assert_eq!( + pool_events_since_last_call(), + vec![ + Event::Created { depositor: 10, pool_id: 1 }, + Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 }, + ] + ); + + // move to era when unbonded funds can be withdrawn. + CurrentEra::set(4); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0)); + + assert_eq!( + pool_events_since_last_call(), + vec![ + Event::Withdrawn { member: 10, pool_id: 1, points: 10, balance: 10 }, + Event::MemberRemoved { pool_id: 1, member: 10 }, + Event::Destroyed { pool_id: 1 }, + ] + ); + + // pool is destroyed. + assert!(!Metadata::::contains_key(1)); + // ensure the pool account is reaped. + assert!(!frame_system::Account::::contains_key(&Pools::generate_bonded_account(1))); + }) + } + + #[test] + fn destroy_works_with_erroneous_extra_consumer() { + ExtBuilder::default().ed(1).build_and_execute(|| { + // 10 is the depositor for pool 1, with min join bond 10. + let pool_one = Pools::generate_bonded_account(1); + + // set pool to destroying. + unsafe_set_state(1, PoolState::Destroying); + + // set current era + CurrentEra::set(1); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10)); + + assert_eq!( + pool_events_since_last_call(), + vec![ + Event::Created { depositor: 10, pool_id: 1 }, + Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 }, + ] + ); + + // move to era when unbonded funds can be withdrawn. + CurrentEra::set(4); + + // increment consumer by 1 reproducing the erroneous consumer bug. + // refer https://github.com/paritytech/polkadot-sdk/issues/4440. + assert_ok!(frame_system::Pallet::::inc_consumers(&pool_one)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0)); + + assert_eq!( + pool_events_since_last_call(), + vec![ + Event::Withdrawn { member: 10, pool_id: 1, points: 10, balance: 10 }, + Event::MemberRemoved { pool_id: 1, member: 10 }, + Event::Destroyed { pool_id: 1 }, + ] + ); + + // pool is destroyed. + assert!(!Metadata::::contains_key(1)); + // ensure the pool account is reaped. + assert!(!frame_system::Account::::contains_key(&pool_one)); + }) + } } mod create { @@ -4604,7 +4693,7 @@ mod create { fn create_works() { ExtBuilder::default().build_and_execute(|| { // next pool id is 2. - let next_pool_stash = Pools::create_bonded_account(2); + let next_pool_stash = Pools::generate_bonded_account(2); let ed = Currency::minimum_balance(); assert_eq!(TotalValueLocked::::get(), 10); @@ -4925,6 +5014,13 @@ mod set_state { // surpassed. Making this pool destroyable by anyone. StakingMock::slash_by(1, 10); + // in mock we are using transfer stake which implies slash is greedy. Extrinsic to + // apply pending slash should fail. + assert_noop!( + Pools::apply_slash(RuntimeOrigin::signed(11), 10), + Error::::NotSupported + ); + // When assert_ok!(Pools::set_state(RuntimeOrigin::signed(11), 1, PoolState::Destroying)); // Then @@ -7387,3 +7483,61 @@ mod chill { }) } } + +// the test mock is using `TransferStake` and so `DelegateStake` is not tested here. Extrinsics +// meant for `DelegateStake` should be gated. +// +// `DelegateStake` tests are in `pallet-nomination-pools-test-delegate-stake`. Since we support both +// strategies currently, we keep these tests as it is but in future we may remove `TransferStake` +// completely. +mod delegate_stake { + use super::*; + #[test] + fn delegation_specific_calls_are_gated() { + ExtBuilder::default().with_check(0).build_and_execute(|| { + // Given + Currency::set_balance(&11, ExistentialDeposit::get() + 2); + assert!(!PoolMembers::::contains_key(11)); + + // When + assert_ok!(Pools::join(RuntimeOrigin::signed(11), 2, 1)); + + // Then + assert_eq!( + pool_events_since_last_call(), + vec![ + Event::Created { depositor: 10, pool_id: 1 }, + Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true }, + ] + ); + + assert_eq!( + PoolMembers::::get(11).unwrap(), + PoolMember:: { pool_id: 1, points: 2, ..Default::default() } + ); + + // ensure pool 1 cannot be migrated. + assert_noop!( + Pools::migrate_pool_to_delegate_stake(RuntimeOrigin::signed(10), 1), + Error::::NotSupported + ); + + // members cannot be migrated either. + assert_noop!( + Pools::migrate_delegation(RuntimeOrigin::signed(10), 11), + Error::::NotSupported + ); + + // Given + // The bonded balance is slashed in half + StakingMock::slash_by(1, 6); + + // since slash is greedy with `TransferStake`, `apply_slash` should not work either. + assert_noop!( + Pools::apply_slash(RuntimeOrigin::signed(10), 11), + Error::::NotSupported + ); + }); + } +} diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index 57ea8dc388f6869c8f4f2be761816cced9758e19..21711a499b623fad15198b265b99476545f6b2b5 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-04-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-dcu62vjg-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_nomination_pools -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nomination-pools/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_nomination_pools +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/nomination-pools/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -73,6 +71,10 @@ pub trait WeightInfo { fn set_claim_permission() -> Weight; fn claim_commission() -> Weight; fn adjust_pool_deposit() -> Weight; + fn apply_slash() -> Weight; + fn apply_slash_fail() -> Weight; + fn pool_migrate() -> Weight; + fn migrate_delegation() -> Weight; } /// Weights for `pallet_nomination_pools` using the Substrate node and recommended hardware. @@ -100,6 +102,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -112,11 +116,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3425` + // Measured: `3458` // Estimated: `8877` - // Minimum execution time: 201_783_000 picoseconds. - Weight::from_parts(206_014_000, 8877) - .saturating_add(T::DbWeight::get().reads(20_u64)) + // Minimum execution time: 195_962_000 picoseconds. + Weight::from_parts(201_682_000, 8877) + .saturating_add(T::DbWeight::get().reads(21_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -133,6 +137,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -145,11 +151,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3435` + // Measured: `3468` // Estimated: `8877` - // Minimum execution time: 204_124_000 picoseconds. - Weight::from_parts(207_910_000, 8877) - .saturating_add(T::DbWeight::get().reads(17_u64)) + // Minimum execution time: 197_466_000 picoseconds. + Weight::from_parts(201_356_000, 8877) + .saturating_add(T::DbWeight::get().reads(18_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) @@ -168,6 +174,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -180,11 +188,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3500` + // Measured: `3533` // Estimated: `8877` - // Minimum execution time: 240_342_000 picoseconds. - Weight::from_parts(245_735_000, 8877) - .saturating_add(T::DbWeight::get().reads(18_u64)) + // Minimum execution time: 232_623_000 picoseconds. + Weight::from_parts(236_970_000, 8877) + .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().writes(14_u64)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) @@ -203,8 +211,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 81_054_000 picoseconds. - Weight::from_parts(83_324_000, 3719) + // Minimum execution time: 77_992_000 picoseconds. + Weight::from_parts(79_927_000, 3719) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -228,6 +236,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -242,11 +252,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3622` + // Measured: `3655` // Estimated: `27847` - // Minimum execution time: 188_835_000 picoseconds. - Weight::from_parts(192_565_000, 27847) - .saturating_add(T::DbWeight::get().reads(20_u64)) + // Minimum execution time: 182_368_000 picoseconds. + Weight::from_parts(185_387_000, 27847) + .saturating_add(T::DbWeight::get().reads(21_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) @@ -257,6 +267,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -268,13 +280,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1848` + // Measured: `1881` // Estimated: `4764` - // Minimum execution time: 73_556_000 picoseconds. - Weight::from_parts(76_075_881, 4764) - // Standard Error: 1_419 - .saturating_add(Weight::from_parts(54_476, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Minimum execution time: 72_179_000 picoseconds. + Weight::from_parts(75_031_092, 4764) + // Standard Error: 1_487 + .saturating_add(Weight::from_parts(56_741, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -289,6 +301,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -306,13 +320,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2238` + // Measured: `2271` // Estimated: `27847` - // Minimum execution time: 144_177_000 picoseconds. - Weight::from_parts(148_686_524, 27847) - // Standard Error: 2_475 - .saturating_add(Weight::from_parts(77_460, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Minimum execution time: 137_277_000 picoseconds. + Weight::from_parts(143_537_793, 27847) + // Standard Error: 3_049 + .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -329,6 +343,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::SlashingSpans` (r:1 w:0) /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:2 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:2 w:1) @@ -364,14 +380,14 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2525` + // Measured: `2558` // Estimated: `27847` - // Minimum execution time: 255_957_000 picoseconds. - Weight::from_parts(264_206_788, 27847) - // Standard Error: 4_229 - .saturating_add(Weight::from_parts(3_064, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(24_u64)) - .saturating_add(T::DbWeight::get().writes(20_u64)) + // Minimum execution time: 242_522_000 picoseconds. + Weight::from_parts(250_740_608, 27847) + // Standard Error: 4_517 + .saturating_add(Weight::from_parts(13_231, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(25_u64)) + .saturating_add(T::DbWeight::get().writes(21_u64)) } /// Storage: `NominationPools::LastPoolId` (r:1 w:1) /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -393,12 +409,14 @@ impl WeightInfo for SubstrateWeight { /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:1) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:2 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:2 w:1) @@ -419,11 +437,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `1284` + // Measured: `1317` // Estimated: `8538` - // Minimum execution time: 193_527_000 picoseconds. - Weight::from_parts(197_140_000, 8538) - .saturating_add(T::DbWeight::get().reads(24_u64)) + // Minimum execution time: 182_740_000 picoseconds. + Weight::from_parts(188_820_000, 8538) + .saturating_add(T::DbWeight::get().reads(25_u64)) .saturating_add(T::DbWeight::get().writes(17_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) @@ -459,12 +477,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1976` + // Measured: `2009` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 86_054_000 picoseconds. - Weight::from_parts(88_743_932, 4556) - // Standard Error: 12_699 - .saturating_add(Weight::from_parts(1_829_097, 0).saturating_mul(n.into())) + // Minimum execution time: 83_649_000 picoseconds. + Weight::from_parts(85_754_306, 4556) + // Standard Error: 12_757 + .saturating_add(Weight::from_parts(1_616_356, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -478,10 +496,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: - // Measured: `1434` + // Measured: `1467` // Estimated: `4556` - // Minimum execution time: 34_544_000 picoseconds. - Weight::from_parts(35_910_000, 4556) + // Minimum execution time: 34_594_000 picoseconds. + Weight::from_parts(36_173_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -496,10 +514,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 14_111_000 picoseconds. - Weight::from_parts(15_204_218, 3735) - // Standard Error: 226 - .saturating_add(Weight::from_parts(1_291, 0).saturating_mul(n.into())) + // Minimum execution time: 13_945_000 picoseconds. + Weight::from_parts(14_764_062, 3735) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_406, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -519,8 +537,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_524_000 picoseconds. - Weight::from_parts(4_882_000, 0) + // Minimum execution time: 4_523_000 picoseconds. + Weight::from_parts(4_727_000, 0) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -529,8 +547,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 17_975_000 picoseconds. - Weight::from_parts(18_549_000, 3719) + // Minimum execution time: 17_124_000 picoseconds. + Weight::from_parts(17_718_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -558,10 +576,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `2143` + // Measured: `2176` // Estimated: `4556` - // Minimum execution time: 81_574_000 picoseconds. - Weight::from_parts(83_519_000, 4556) + // Minimum execution time: 78_293_000 picoseconds. + Weight::from_parts(81_177_000, 4556) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -577,8 +595,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 35_015_000 picoseconds. - Weight::from_parts(36_159_000, 3719) + // Minimum execution time: 33_105_000 picoseconds. + Weight::from_parts(34_106_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -590,8 +608,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 17_775_000 picoseconds. - Weight::from_parts(18_358_000, 3719) + // Minimum execution time: 16_710_000 picoseconds. + Weight::from_parts(17_269_000, 3719) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -601,8 +619,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_997_000 picoseconds. - Weight::from_parts(18_041_000, 3719) + // Minimum execution time: 16_557_000 picoseconds. + Weight::from_parts(17_431_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -612,8 +630,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 17_000_000 picoseconds. - Weight::from_parts(17_807_000, 3719) + // Minimum execution time: 16_723_000 picoseconds. + Weight::from_parts(17_155_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -625,8 +643,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_803_000 picoseconds. - Weight::from_parts(15_401_000, 3702) + // Minimum execution time: 14_667_000 picoseconds. + Weight::from_parts(15_242_000, 3702) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -642,8 +660,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 69_759_000 picoseconds. - Weight::from_parts(71_985_000, 3719) + // Minimum execution time: 64_219_000 picoseconds. + Weight::from_parts(66_718_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -659,11 +677,58 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 73_829_000 picoseconds. - Weight::from_parts(75_966_000, 4764) + // Minimum execution time: 70_284_000 picoseconds. + Weight::from_parts(71_375_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + fn apply_slash() -> Weight { + // Proof Size summary in bytes: + // Measured: `694` + // Estimated: `3702` + // Minimum execution time: 13_403_000 picoseconds. + Weight::from_parts(14_064_000, 3702) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + fn apply_slash_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `732` + // Estimated: `3702` + // Minimum execution time: 14_419_000 picoseconds. + Weight::from_parts(15_004_000, 3702) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + fn pool_migrate() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 759_000 picoseconds. + Weight::from_parts(819_000, 0) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:0) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn migrate_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `1648` + // Estimated: `27847` + // Minimum execution time: 36_192_000 picoseconds. + Weight::from_parts(37_038_000, 27847) + .saturating_add(T::DbWeight::get().reads(6_u64)) + } } // For backwards compatibility and tests. @@ -690,6 +755,8 @@ impl WeightInfo for () { /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -702,11 +769,11 @@ impl WeightInfo for () { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn join() -> Weight { // Proof Size summary in bytes: - // Measured: `3425` + // Measured: `3458` // Estimated: `8877` - // Minimum execution time: 201_783_000 picoseconds. - Weight::from_parts(206_014_000, 8877) - .saturating_add(RocksDbWeight::get().reads(20_u64)) + // Minimum execution time: 195_962_000 picoseconds. + Weight::from_parts(201_682_000, 8877) + .saturating_add(RocksDbWeight::get().reads(21_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -723,6 +790,8 @@ impl WeightInfo for () { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -735,11 +804,11 @@ impl WeightInfo for () { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `3435` + // Measured: `3468` // Estimated: `8877` - // Minimum execution time: 204_124_000 picoseconds. - Weight::from_parts(207_910_000, 8877) - .saturating_add(RocksDbWeight::get().reads(17_u64)) + // Minimum execution time: 197_466_000 picoseconds. + Weight::from_parts(201_356_000, 8877) + .saturating_add(RocksDbWeight::get().reads(18_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) @@ -758,6 +827,8 @@ impl WeightInfo for () { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -770,11 +841,11 @@ impl WeightInfo for () { /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) fn bond_extra_other() -> Weight { // Proof Size summary in bytes: - // Measured: `3500` + // Measured: `3533` // Estimated: `8877` - // Minimum execution time: 240_342_000 picoseconds. - Weight::from_parts(245_735_000, 8877) - .saturating_add(RocksDbWeight::get().reads(18_u64)) + // Minimum execution time: 232_623_000 picoseconds. + Weight::from_parts(236_970_000, 8877) + .saturating_add(RocksDbWeight::get().reads(19_u64)) .saturating_add(RocksDbWeight::get().writes(14_u64)) } /// Storage: `NominationPools::ClaimPermissions` (r:1 w:0) @@ -793,8 +864,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 81_054_000 picoseconds. - Weight::from_parts(83_324_000, 3719) + // Minimum execution time: 77_992_000 picoseconds. + Weight::from_parts(79_927_000, 3719) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -818,6 +889,8 @@ impl WeightInfo for () { /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -832,11 +905,11 @@ impl WeightInfo for () { /// Proof: `NominationPools::CounterForSubPoolsStorage` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `3622` + // Measured: `3655` // Estimated: `27847` - // Minimum execution time: 188_835_000 picoseconds. - Weight::from_parts(192_565_000, 27847) - .saturating_add(RocksDbWeight::get().reads(20_u64)) + // Minimum execution time: 182_368_000 picoseconds. + Weight::from_parts(185_387_000, 27847) + .saturating_add(RocksDbWeight::get().reads(21_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) @@ -847,6 +920,8 @@ impl WeightInfo for () { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -858,13 +933,13 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1848` + // Measured: `1881` // Estimated: `4764` - // Minimum execution time: 73_556_000 picoseconds. - Weight::from_parts(76_075_881, 4764) - // Standard Error: 1_419 - .saturating_add(Weight::from_parts(54_476, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Minimum execution time: 72_179_000 picoseconds. + Weight::from_parts(75_031_092, 4764) + // Standard Error: 1_487 + .saturating_add(Weight::from_parts(56_741, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -879,6 +954,8 @@ impl WeightInfo for () { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -896,13 +973,13 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2238` + // Measured: `2271` // Estimated: `27847` - // Minimum execution time: 144_177_000 picoseconds. - Weight::from_parts(148_686_524, 27847) - // Standard Error: 2_475 - .saturating_add(Weight::from_parts(77_460, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(12_u64)) + // Minimum execution time: 137_277_000 picoseconds. + Weight::from_parts(143_537_793, 27847) + // Standard Error: 3_049 + .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -919,6 +996,8 @@ impl WeightInfo for () { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::SlashingSpans` (r:1 w:0) /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:2 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:2 w:1) @@ -954,14 +1033,14 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2525` + // Measured: `2558` // Estimated: `27847` - // Minimum execution time: 255_957_000 picoseconds. - Weight::from_parts(264_206_788, 27847) - // Standard Error: 4_229 - .saturating_add(Weight::from_parts(3_064, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(24_u64)) - .saturating_add(RocksDbWeight::get().writes(20_u64)) + // Minimum execution time: 242_522_000 picoseconds. + Weight::from_parts(250_740_608, 27847) + // Standard Error: 4_517 + .saturating_add(Weight::from_parts(13_231, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(25_u64)) + .saturating_add(RocksDbWeight::get().writes(21_u64)) } /// Storage: `NominationPools::LastPoolId` (r:1 w:1) /// Proof: `NominationPools::LastPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -983,12 +1062,14 @@ impl WeightInfo for () { /// Proof: `NominationPools::MaxPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:1) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:2 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:2 w:1) @@ -1009,11 +1090,11 @@ impl WeightInfo for () { /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `1284` + // Measured: `1317` // Estimated: `8538` - // Minimum execution time: 193_527_000 picoseconds. - Weight::from_parts(197_140_000, 8538) - .saturating_add(RocksDbWeight::get().reads(24_u64)) + // Minimum execution time: 182_740_000 picoseconds. + Weight::from_parts(188_820_000, 8538) + .saturating_add(RocksDbWeight::get().reads(25_u64)) .saturating_add(RocksDbWeight::get().writes(17_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) @@ -1049,12 +1130,12 @@ impl WeightInfo for () { /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1976` + // Measured: `2009` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 86_054_000 picoseconds. - Weight::from_parts(88_743_932, 4556) - // Standard Error: 12_699 - .saturating_add(Weight::from_parts(1_829_097, 0).saturating_mul(n.into())) + // Minimum execution time: 83_649_000 picoseconds. + Weight::from_parts(85_754_306, 4556) + // Standard Error: 12_757 + .saturating_add(Weight::from_parts(1_616_356, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -1068,10 +1149,10 @@ impl WeightInfo for () { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_state() -> Weight { // Proof Size summary in bytes: - // Measured: `1434` + // Measured: `1467` // Estimated: `4556` - // Minimum execution time: 34_544_000 picoseconds. - Weight::from_parts(35_910_000, 4556) + // Minimum execution time: 34_594_000 picoseconds. + Weight::from_parts(36_173_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1086,10 +1167,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 14_111_000 picoseconds. - Weight::from_parts(15_204_218, 3735) - // Standard Error: 226 - .saturating_add(Weight::from_parts(1_291, 0).saturating_mul(n.into())) + // Minimum execution time: 13_945_000 picoseconds. + Weight::from_parts(14_764_062, 3735) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_406, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1109,8 +1190,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_524_000 picoseconds. - Weight::from_parts(4_882_000, 0) + // Minimum execution time: 4_523_000 picoseconds. + Weight::from_parts(4_727_000, 0) .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -1119,8 +1200,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 17_975_000 picoseconds. - Weight::from_parts(18_549_000, 3719) + // Minimum execution time: 17_124_000 picoseconds. + Weight::from_parts(17_718_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1148,10 +1229,10 @@ impl WeightInfo for () { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `2143` + // Measured: `2176` // Estimated: `4556` - // Minimum execution time: 81_574_000 picoseconds. - Weight::from_parts(83_519_000, 4556) + // Minimum execution time: 78_293_000 picoseconds. + Weight::from_parts(81_177_000, 4556) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1167,8 +1248,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 35_015_000 picoseconds. - Weight::from_parts(36_159_000, 3719) + // Minimum execution time: 33_105_000 picoseconds. + Weight::from_parts(34_106_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1180,8 +1261,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 17_775_000 picoseconds. - Weight::from_parts(18_358_000, 3719) + // Minimum execution time: 16_710_000 picoseconds. + Weight::from_parts(17_269_000, 3719) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1191,8 +1272,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_997_000 picoseconds. - Weight::from_parts(18_041_000, 3719) + // Minimum execution time: 16_557_000 picoseconds. + Weight::from_parts(17_431_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1202,8 +1283,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 17_000_000 picoseconds. - Weight::from_parts(17_807_000, 3719) + // Minimum execution time: 16_723_000 picoseconds. + Weight::from_parts(17_155_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1215,8 +1296,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_803_000 picoseconds. - Weight::from_parts(15_401_000, 3702) + // Minimum execution time: 14_667_000 picoseconds. + Weight::from_parts(15_242_000, 3702) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1232,8 +1313,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 69_759_000 picoseconds. - Weight::from_parts(71_985_000, 3719) + // Minimum execution time: 64_219_000 picoseconds. + Weight::from_parts(66_718_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1249,9 +1330,56 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 73_829_000 picoseconds. - Weight::from_parts(75_966_000, 4764) + // Minimum execution time: 70_284_000 picoseconds. + Weight::from_parts(71_375_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + fn apply_slash() -> Weight { + // Proof Size summary in bytes: + // Measured: `694` + // Estimated: `3702` + // Minimum execution time: 13_403_000 picoseconds. + Weight::from_parts(14_064_000, 3702) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + fn apply_slash_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `732` + // Estimated: `3702` + // Minimum execution time: 14_419_000 picoseconds. + Weight::from_parts(15_004_000, 3702) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + fn pool_migrate() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 759_000 picoseconds. + Weight::from_parts(819_000, 0) + } + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::BondedPools` (r:1 w:0) + /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::SubPoolsStorage` (r:1 w:0) + /// Proof: `NominationPools::SubPoolsStorage` (`max_values`: None, `max_size`: Some(24382), added: 26857, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn migrate_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `1648` + // Estimated: `27847` + // Minimum execution time: 36_192_000 picoseconds. + Weight::from_parts(37_038_000, 27847) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + } } diff --git a/substrate/frame/nomination-pools/test-delegate-stake/Cargo.toml b/substrate/frame/nomination-pools/test-delegate-stake/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ea8eb20696931f8c45edc6f67e4d5af49412eccd --- /dev/null +++ b/substrate/frame/nomination-pools/test-delegate-stake/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "pallet-nomination-pools-test-delegate-stake" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +homepage = "https://substrate.io" +repository.workspace = true +description = "FRAME nomination pools pallet tests with the staking pallet" +publish = false + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } +scale-info = { version = "2.11.1", features = ["derive"] } + +sp-runtime = { path = "../../../primitives/runtime" } +sp-io = { path = "../../../primitives/io" } +sp-std = { path = "../../../primitives/std" } +sp-staking = { path = "../../../primitives/staking" } +sp-core = { path = "../../../primitives/core" } + +frame-system = { path = "../../system" } +frame-support = { path = "../../support" } +frame-election-provider-support = { path = "../../election-provider-support" } + +pallet-timestamp = { path = "../../timestamp" } +pallet-balances = { path = "../../balances" } +pallet-staking = { path = "../../staking" } +pallet-delegated-staking = { path = "../../delegated-staking" } +pallet-bags-list = { path = "../../bags-list" } +pallet-staking-reward-curve = { path = "../../staking/reward-curve" } +pallet-nomination-pools = { path = ".." } + +sp-tracing = { path = "../../../primitives/tracing" } +log = { workspace = true, default-features = true } diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d3235760ed23b06d0e7f0beb5530a3f77c5aee61 --- /dev/null +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -0,0 +1,1158 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +mod mock; + +use frame_support::{ + assert_noop, assert_ok, + traits::{fungible::InspectHold, Currency}, +}; +use mock::*; +use pallet_nomination_pools::{ + BondExtra, BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, + PoolMembers, PoolState, +}; +use pallet_staking::{ + CurrentEra, Error as StakingError, Event as StakingEvent, Payee, RewardDestination, +}; + +use pallet_delegated_staking::{Error as DelegatedStakingError, Event as DelegatedStakingEvent}; + +use sp_runtime::{bounded_btree_map, traits::Zero}; + +#[test] +fn pool_lifecycle_e2e() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::minimum_balance(), 5); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + // have the pool nominate. + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + ] + ); + + // have two members join + assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true }, + ] + ); + + // pool goes into destroying + assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying)); + + // depositor cannot unbond yet. + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(10), 10, 50), + PoolsError::::MinimumBondNotMet, + ); + + // now the members want to unbond. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + + assert_eq!(PoolMembers::::get(20).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(20).unwrap().points, 0); + assert_eq!(PoolMembers::::get(21).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(21).unwrap().points, 0); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying }, + PoolsEvent::Unbonded { member: 20, pool_id: 1, points: 10, balance: 10, era: 3 }, + PoolsEvent::Unbonded { member: 21, pool_id: 1, points: 10, balance: 10, era: 3 }, + ] + ); + + // depositor cannot still unbond + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(10), 10, 50), + PoolsError::::MinimumBondNotMet, + ); + + for e in 1..BondingDuration::get() { + CurrentEra::::set(Some(e)); + assert_noop!( + Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0), + PoolsError::::CannotWithdrawAny + ); + } + + // members are now unlocked. + CurrentEra::::set(Some(BondingDuration::get())); + + // depositor cannot still unbond + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(10), 10, 50), + PoolsError::::MinimumBondNotMet, + ); + + // but members can now withdraw. + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0)); + assert!(PoolMembers::::get(20).is_none()); + assert!(PoolMembers::::get(21).is_none()); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 20 },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 20, pool_id: 1, points: 10, balance: 10 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 20 }, + PoolsEvent::Withdrawn { member: 21, pool_id: 1, points: 10, balance: 10 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 21 }, + ] + ); + + // as soon as all members have left, the depositor can try to unbond, but since the + // min-nominator intention is set, they must chill first. + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(10), 10, 50), + pallet_staking::Error::::InsufficientBond + ); + + assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Chilled { stash: POOL1_BONDED }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 50 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }] + ); + + // waiting another bonding duration: + CurrentEra::::set(Some(BondingDuration::get() * 2)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 1)); + + // pools is fully destroyed now. + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 50 },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 10, pool_id: 1, points: 50, balance: 50 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 10 }, + PoolsEvent::Destroyed { pool_id: 1 } + ] + ); + }) +} + +#[test] +fn pool_chill_e2e() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::minimum_balance(), 5); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + // have the pool nominate. + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + ] + ); + + // have two members join + assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true }, + ] + ); + + // in case depositor does not have more than `MinNominatorBond` staked, we can end up in + // situation where a member unbonding would cause pool balance to drop below + // `MinNominatorBond` and hence not allowed. This can happen if the `MinNominatorBond` is + // increased after the pool is created. + assert_ok!(Staking::set_staking_configs( + RuntimeOrigin::root(), + pallet_staking::ConfigOp::Set(55), // minimum nominator bond + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + )); + + // members can unbond as long as total stake of the pool is above min nominator bond + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10),); + assert_eq!(PoolMembers::::get(20).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(20).unwrap().points, 0); + + // this member cannot unbond since it will cause `pool stake < MinNominatorBond` + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(21), 21, 10), + StakingError::::InsufficientBond, + ); + + // members can call `chill` permissionlessly now + assert_ok!(Pools::chill(RuntimeOrigin::signed(20), 1)); + + // now another member can unbond. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + assert_eq!(PoolMembers::::get(21).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(21).unwrap().points, 0); + + // nominator can not resume nomination until depositor have enough stake + assert_noop!( + Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]), + PoolsError::::MinimumBondNotMet, + ); + + // other members joining pool does not affect the depositor's ability to resume nomination + assert_ok!(Pools::join(RuntimeOrigin::signed(22), 10, 1)); + + assert_noop!( + Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]), + PoolsError::::MinimumBondNotMet, + ); + + // depositor can bond extra stake + assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::FreeBalance(10))); + + // `chill` can not be called permissionlessly anymore + assert_noop!( + Pools::chill(RuntimeOrigin::signed(20), 1), + PoolsError::::NotNominator, + ); + + // now nominator can resume nomination + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + // skip to make the unbonding period end. + CurrentEra::::set(Some(BondingDuration::get())); + + // members can now withdraw. + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Chilled { stash: POOL1_BONDED }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, // other member bonding + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, // depositor bond extra + StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 20 }, + ] + ); + }) +} + +#[test] +fn pool_slash_e2e() { + new_test_ext().execute_with(|| { + ExistentialDeposit::set(1); + assert_eq!(Balances::minimum_balance(), 1); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true }, + ] + ); + + assert_eq!( + Payee::::get(POOL1_BONDED), + Some(RewardDestination::Account(POOL1_REWARD)) + ); + + // have two members join + assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), 20, 1)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 20 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 20 } + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 20, joined: true }, + ] + ); + + // now let's progress a bit. + CurrentEra::::set(Some(1)); + + // 20 / 80 of the total funds are unlocked, and safe from any further slash. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 } + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 }, + PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: 10, points: 10, era: 4 } + ] + ); + + CurrentEra::::set(Some(2)); + + // note: depositor cannot fully unbond at this point. + // these funds will still get slashed. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 5 }, + PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: 10, points: 10, era: 5 }, + PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: 10, points: 10, era: 5 }, + ] + ); + + // At this point, 20 are safe from slash, 30 are unlocking but vulnerable to slash, and and + // another 30 are active and vulnerable to slash. Let's slash half of them. + pallet_staking::slashing::do_slash::( + &POOL1_BONDED, + 30, + &mut Default::default(), + &mut Default::default(), + 2, // slash era 2, affects chunks at era 5 onwards. + ); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 30 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + // 30 has been slashed to 15 (15 slash) + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 5, balance: 15 }, + // 30 has been slashed to 15 (15 slash) + PoolsEvent::PoolSlashed { pool_id: 1, balance: 15 } + ] + ); + + CurrentEra::::set(Some(3)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + + assert_eq!( + PoolMembers::::get(21).unwrap(), + PoolMember { + pool_id: 1, + points: 0, + last_recorded_reward_counter: Zero::zero(), + // the 10 points unlocked just now correspond to 5 points in the unbond pool. + unbonding_eras: bounded_btree_map!(5 => 10, 6 => 5) + } + ); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 5 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: 5, points: 5, era: 6 }] + ); + + // now we start withdrawing. we do it all at once, at era 6 where 20 and 21 are fully free. + CurrentEra::::set(Some(6)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0)); + + assert_eq!( + pool_events_since_last_call(), + vec![ + // 20 had unbonded 10 safely, and 10 got slashed by half. + PoolsEvent::Withdrawn { member: 20, pool_id: 1, balance: 10 + 5, points: 20 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 20 }, + // 21 unbonded all of it after the slash + PoolsEvent::Withdrawn { member: 21, pool_id: 1, balance: 5 + 5, points: 15 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 21 } + ] + ); + assert_eq!( + staking_events_since_last_call(), + // a 10 (un-slashed) + 10/2 (slashed) balance from 10 has also been unlocked + vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 15 + 10 + 15 }] + ); + + // now, finally, we can unbond the depositor further than their current limit. + assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 20)); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying }, + PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 10, balance: 10, era: 9 } + ] + ); + + CurrentEra::::set(Some(9)); + assert_eq!( + PoolMembers::::get(10).unwrap(), + PoolMember { + pool_id: 1, + points: 0, + last_recorded_reward_counter: Zero::zero(), + unbonding_eras: bounded_btree_map!(4 => 10, 5 => 10, 9 => 10) + } + ); + // withdraw the depositor, they should lose 12 balance in total due to slash. + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0)); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 10 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 10, pool_id: 1, balance: 10 + 15, points: 30 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 10 }, + PoolsEvent::Destroyed { pool_id: 1 } + ] + ); + }); +} + +#[test] +fn pool_slash_proportional() { + // a typical example where 3 pool members unbond in era 99, 100, and 101, and a slash that + // happened in era 100 should only affect the latter two. + new_test_ext().execute_with(|| { + ExistentialDeposit::set(1); + BondingDuration::set(28); + assert_eq!(Balances::minimum_balance(), 1); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }] + ); + assert_eq!( + delegated_staking_events_since_last_call(), + vec![DelegatedStakingEvent::Delegated { + agent: POOL1_BONDED, + delegator: 10, + amount: 40 + }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true }, + ] + ); + + // have two members join + let bond = 20; + assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), bond, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(22), bond, 1)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }, + ] + ); + assert_eq!( + delegated_staking_events_since_last_call(), + vec![ + DelegatedStakingEvent::Delegated { + agent: POOL1_BONDED, + delegator: 20, + amount: bond + }, + DelegatedStakingEvent::Delegated { + agent: POOL1_BONDED, + delegator: 21, + amount: bond + }, + DelegatedStakingEvent::Delegated { + agent: POOL1_BONDED, + delegator: 22, + amount: bond + } + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: bond, joined: true }, + PoolsEvent::Bonded { member: 22, pool_id: 1, bonded: bond, joined: true }, + ] + ); + + // now let's progress a lot. + CurrentEra::::set(Some(99)); + + // and unbond + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond)); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 20, + pool_id: 1, + balance: bond, + points: bond, + era: 127 + }] + ); + + CurrentEra::::set(Some(100)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, bond)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 21, + pool_id: 1, + balance: bond, + points: bond, + era: 128 + }] + ); + + CurrentEra::::set(Some(101)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(22), 22, bond)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 22, + pool_id: 1, + balance: bond, + points: bond, + era: 129 + }] + ); + + // Apply a slash that happened in era 100. This is typically applied with a delay. + // Of the total 100, 50 is slashed. + assert_eq!(BondedPools::::get(1).unwrap().points, 40); + pallet_staking::slashing::do_slash::( + &POOL1_BONDED, + 50, + &mut Default::default(), + &mut Default::default(), + 100, + ); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + // This era got slashed 12.5, which rounded up to 13. + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 128, balance: 7 }, + // This era got slashed 12 instead of 12.5 because an earlier chunk got 0.5 more + // slashed, and 12 is all the remaining slash + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 129, balance: 8 }, + // Bonded pool got slashed for 25, remaining 15 in it. + PoolsEvent::PoolSlashed { pool_id: 1, balance: 15 } + ] + ); + + // 21's balance in the pool is slashed. + assert_eq!(PoolMembers::::get(21).unwrap().total_balance(), 7); + // But their actual balance is still unslashed. + assert_eq!(Balances::total_balance_on_hold(&21), bond); + // apply slash permissionlessly. + assert_ok!(Pools::apply_slash(RuntimeOrigin::signed(10), 21)); + // member balance is slashed. + assert_eq!(Balances::total_balance_on_hold(&21), 7); + + assert_eq!( + delegated_staking_events_since_last_call(), + vec![DelegatedStakingEvent::Slashed { + agent: POOL1_BONDED, + delegator: 21, + amount: bond - 7 + }] + ); + + // 22 balance isn't slashed yet as well. + assert_eq!(PoolMembers::::get(22).unwrap().total_balance(), 8); + assert_eq!(Balances::total_balance_on_hold(&22), bond); + + // they try to withdraw. This should slash them. + CurrentEra::::set(Some(129)); + let pre_balance = Balances::free_balance(&22); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(22), 22, 0)); + // all balance should be released. + assert_eq!(Balances::total_balance_on_hold(&22), 0); + assert_eq!(Balances::free_balance(&22), pre_balance + 8); + + assert_eq!( + delegated_staking_events_since_last_call(), + vec![ + DelegatedStakingEvent::Slashed { + agent: POOL1_BONDED, + delegator: 22, + amount: bond - 8 + }, + DelegatedStakingEvent::Released { agent: POOL1_BONDED, delegator: 22, amount: 8 }, + ] + ); + }); +} + +#[test] +fn pool_slash_non_proportional_only_bonded_pool() { + // A typical example where a pool member unbonds in era 99, and they can get away with a slash + // that happened in era 100, as long as the pool has enough active bond to cover the slash. If + // everything else in the slashing/staking system works, this should always be the case. + // Nonetheless, `ledger.slash` has been written such that it will slash greedily from any chunk + // if it runs out of chunks that it thinks should be affected by the slash. + new_test_ext().execute_with(|| { + ExistentialDeposit::set(1); + BondingDuration::set(28); + assert_eq!(Balances::minimum_balance(), 1); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true }, + ] + ); + + // have two members join + let bond = 20; + assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }] + ); + + // progress and unbond. + CurrentEra::::set(Some(99)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 20, + pool_id: 1, + balance: bond, + points: bond, + era: 127 + }] + ); + + // slash for 30. This will be deducted only from the bonded pool. + CurrentEra::::set(Some(100)); + assert_eq!(BondedPools::::get(1).unwrap().points, 40); + pallet_staking::slashing::do_slash::( + &POOL1_BONDED, + 30, + &mut Default::default(), + &mut Default::default(), + 100, + ); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 30 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::PoolSlashed { pool_id: 1, balance: 10 }] + ); + }); +} + +#[test] +fn pool_slash_non_proportional_bonded_pool_and_chunks() { + // An uncommon example where even though some funds are unlocked such that they should not be + // affected by a slash, we still slash out of them. This should not happen at all. If a + // nomination has unbonded, from the next era onwards, their exposure will drop, so if an era + // happens in that era, then their share of that slash should naturally be less, such that only + // their active ledger stake is enough to compensate it. + new_test_ext().execute_with(|| { + ExistentialDeposit::set(1); + BondingDuration::set(28); + assert_eq!(Balances::minimum_balance(), 1); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true }, + ] + ); + + // have two members join + let bond = 20; + assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }] + ); + + // progress and unbond. + CurrentEra::::set(Some(99)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond)); + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 20, + pool_id: 1, + balance: bond, + points: bond, + era: 127 + }] + ); + + // slash 50. This will be deducted only from the bonded pool and one of the unbonding pools. + CurrentEra::::set(Some(100)); + assert_eq!(BondedPools::::get(1).unwrap().points, 40); + pallet_staking::slashing::do_slash::( + &POOL1_BONDED, + 50, + &mut Default::default(), + &mut Default::default(), + 100, + ); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + // out of 20, 10 was taken. + PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 127, balance: 10 }, + // out of 40, all was taken. + PoolsEvent::PoolSlashed { pool_id: 1, balance: 0 } + ] + ); + }); +} +#[test] +fn pool_migration_e2e() { + new_test_ext().execute_with(|| { + LegacyAdapter::set(true); + assert_eq!(Balances::minimum_balance(), 5); + assert_eq!(Staking::current_era(), None); + + // create the pool with TransferStake strategy. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + // have the pool nominate. + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + ] + ); + + // have three members join + let pre_20 = Balances::free_balance(20); + assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); + let pre_21 = Balances::free_balance(21); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1)); + let pre_22 = Balances::free_balance(22); + assert_ok!(Pools::join(RuntimeOrigin::signed(22), 10, 1)); + + // verify members balance is moved to pool. + assert_eq!(Balances::free_balance(20), pre_20 - 10); + assert_eq!(Balances::free_balance(21), pre_21 - 10); + assert_eq!(Balances::free_balance(22), pre_22 - 10); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true }, + PoolsEvent::Bonded { member: 22, pool_id: 1, bonded: 10, joined: true }, + ] + ); + + CurrentEra::::set(Some(2)); + // 20 is partially unbonding + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5)); + + CurrentEra::::set(Some(3)); + // 21 is fully unbonding + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 5 }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: 5, points: 5, era: 5 }, + PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: 10, points: 10, era: 6 }, + ] + ); + + // with `TransferStake`, we can't migrate. + assert_noop!( + Pools::migrate_pool_to_delegate_stake(RuntimeOrigin::signed(10), 1), + PoolsError::::NotSupported + ); + + // we reset the adapter to `DelegateStake`. + LegacyAdapter::set(false); + + // cannot migrate the member delegation unless pool is migrated first. + assert_noop!( + Pools::migrate_delegation(RuntimeOrigin::signed(10), 20), + PoolsError::::PoolNotMigrated + ); + + // migrate the pool. + assert_ok!(Pools::migrate_pool_to_delegate_stake(RuntimeOrigin::signed(10), 1)); + + // migrate again does not work. + assert_noop!( + Pools::migrate_pool_to_delegate_stake(RuntimeOrigin::signed(10), 1), + PoolsError::::PoolAlreadyMigrated + ); + + // unclaimed delegations to the pool are stored in this account. + let proxy_delegator_1 = DelegatedStaking::generate_proxy_delegator(POOL1_BONDED); + + assert_eq!( + delegated_staking_events_since_last_call(), + vec![DelegatedStakingEvent::Delegated { + agent: POOL1_BONDED, + delegator: proxy_delegator_1, + amount: 50 + 10 * 3 + }] + ); + + // move to era 5 when 20 can withdraw unbonded funds. + CurrentEra::::set(Some(5)); + // Unbond works even without claiming delegation. Lets unbond 22. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(22), 22, 5)); + + // withdraw fails for 20 before claiming delegation + assert_noop!( + Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 10), + DelegatedStakingError::::NotDelegator + ); + + let pre_claim_balance_20 = Balances::total_balance(&20); + assert_eq!(Balances::total_balance_on_hold(&20), 0); + + // migrate delegation for 20. This is permissionless and can be called by anyone. + assert_ok!(Pools::migrate_delegation(RuntimeOrigin::signed(10), 20)); + + // tokens moved to 20's account and held there. + assert_eq!(Balances::total_balance(&20), pre_claim_balance_20 + 10); + assert_eq!(Balances::total_balance_on_hold(&20), 10); + + // withdraw works now + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 5)); + + // balance unlocked in 20's account + assert_eq!(Balances::total_balance_on_hold(&20), 5); + assert_eq!(Balances::total_balance(&20), pre_claim_balance_20 + 10); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 5 }, + StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 5 } + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Unbonded { member: 22, pool_id: 1, balance: 5, points: 5, era: 8 }, + PoolsEvent::Withdrawn { member: 20, pool_id: 1, balance: 5, points: 5 }, + ] + ); + assert_eq!( + delegated_staking_events_since_last_call(), + vec![ + DelegatedStakingEvent::MigratedDelegation { + agent: POOL1_BONDED, + delegator: 20, + amount: 10 + }, + DelegatedStakingEvent::Released { agent: POOL1_BONDED, delegator: 20, amount: 5 } + ] + ); + + // MIGRATE 21 + let pre_migrate_balance_21 = Balances::total_balance(&21); + assert_eq!(Balances::total_balance_on_hold(&21), 0); + + // migrate delegation for 21. + assert_ok!(Pools::migrate_delegation(RuntimeOrigin::signed(10), 21)); + + // tokens moved to 21's account and held there. + assert_eq!(Balances::total_balance(&21), pre_migrate_balance_21 + 10); + assert_eq!(Balances::total_balance_on_hold(&21), 10); + + // withdraw fails since 21 only unbonds at era 6. + assert_noop!( + Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 10), + PoolsError::::CannotWithdrawAny + ); + + // go to era when 21 can unbond + CurrentEra::::set(Some(6)); + + // withdraw works now + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 10)); + + // all balance unlocked in 21's account + assert_eq!(Balances::total_balance_on_hold(&21), 0); + assert_eq!(Balances::total_balance(&21), pre_migrate_balance_21 + 10); + + // MIGRATE 22 + let pre_migrate_balance_22 = Balances::total_balance(&22); + assert_eq!(Balances::total_balance_on_hold(&22), 0); + + // migrate delegation for 22. + assert_ok!(Pools::migrate_delegation(RuntimeOrigin::signed(10), 22)); + + // tokens moved to 22's account and held there. + assert_eq!(Balances::total_balance(&22), pre_migrate_balance_22 + 10); + assert_eq!(Balances::total_balance_on_hold(&22), 10); + + // withdraw fails since 22 only unbonds at era 8. + assert_noop!( + Pools::withdraw_unbonded(RuntimeOrigin::signed(22), 22, 5), + PoolsError::::CannotWithdrawAny + ); + + // go to era when 22 can unbond + CurrentEra::::set(Some(10)); + + // withdraw works now + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(22), 22, 10)); + + // balance of 5 unlocked in 22's account + assert_eq!(Balances::total_balance_on_hold(&22), 10 - 5); + + // assert events for 21 and 22. + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 5 } + ] + ); + + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 21, pool_id: 1, balance: 10, points: 10 }, + // 21 was fully unbonding and removed from pool. + PoolsEvent::MemberRemoved { member: 21, pool_id: 1 }, + PoolsEvent::Withdrawn { member: 22, pool_id: 1, balance: 5, points: 5 }, + ] + ); + assert_eq!( + delegated_staking_events_since_last_call(), + vec![ + DelegatedStakingEvent::MigratedDelegation { + agent: POOL1_BONDED, + delegator: 21, + amount: 10 + }, + DelegatedStakingEvent::Released { agent: POOL1_BONDED, delegator: 21, amount: 10 }, + DelegatedStakingEvent::MigratedDelegation { + agent: POOL1_BONDED, + delegator: 22, + amount: 10 + }, + DelegatedStakingEvent::Released { agent: POOL1_BONDED, delegator: 22, amount: 5 } + ] + ); + }) +} diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/mock.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..1c0a0166fd9a9d25bac8252106a35383c11a1f9c --- /dev/null +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/mock.rs @@ -0,0 +1,406 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use frame_election_provider_support::VoteWeight; +use frame_support::{ + assert_ok, derive_impl, + pallet_prelude::*, + parameter_types, + traits::{ConstU64, ConstU8}, + PalletId, +}; +use frame_system::EnsureRoot; +use pallet_nomination_pools::{adapter::StakeStrategyType, BondType}; +use sp_runtime::{ + traits::{Convert, IdentityLookup}, + BuildStorage, FixedU128, Perbill, +}; + +type AccountId = u128; +type Nonce = u32; +type BlockNumber = u64; +type Balance = u128; + +pub(crate) type T = Runtime; + +pub(crate) const POOL1_BONDED: AccountId = 20318131474730217858575332831085u128; +pub(crate) const POOL1_REWARD: AccountId = 20397359637244482196168876781421u128; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Nonce = Nonce; + type RuntimeCall = RuntimeCall; + type Hash = sp_core::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_timestamp::Config for Runtime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<5>; + type WeightInfo = (); +} + +parameter_types! { + pub static ExistentialDeposit: Balance = 5; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<1>; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = (); +} + +pallet_staking_reward_curve::build! { + const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + +parameter_types! { + pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; + pub static BondingDuration: u32 = 3; +} + +impl pallet_staking::Config for Runtime { + type Currency = Balances; + type CurrencyBalance = Balance; + type UnixTime = pallet_timestamp::Pallet; + type CurrencyToVote = (); + type RewardRemainder = (); + type RuntimeEvent = RuntimeEvent; + type Slash = (); + type Reward = (); + type SessionsPerEra = (); + type SlashDeferDuration = (); + type AdminOrigin = frame_system::EnsureRoot; + type BondingDuration = BondingDuration; + type SessionInterface = (); + type EraPayout = pallet_staking::ConvertCurve; + type NextNewSession = (); + type MaxExposurePageSize = ConstU32<64>; + type ElectionProvider = + frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, ())>; + type GenesisElectionProvider = Self::ElectionProvider; + type VoterList = VoterList; + type TargetList = pallet_staking::UseValidatorsMap; + type NominationsQuota = pallet_staking::FixedNominationsQuota<16>; + type MaxUnlockingChunks = ConstU32<32>; + type MaxControllersInDeprecationBatch = ConstU32<100>; + type HistoryDepth = ConstU32<84>; + type EventListeners = (Pools, DelegatedStaking); + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; + type WeightInfo = (); + type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; +} + +parameter_types! { + pub static BagThresholds: &'static [VoteWeight] = &[10, 20, 30, 40, 50, 60, 1_000, 2_000, 10_000]; +} + +type VoterBagsListInstance = pallet_bags_list::Instance1; +impl pallet_bags_list::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type BagThresholds = BagThresholds; + type ScoreProvider = Staking; + type Score = VoteWeight; +} + +pub struct BalanceToU256; +impl Convert for BalanceToU256 { + fn convert(n: Balance) -> sp_core::U256 { + n.into() + } +} + +pub struct U256ToBalance; +impl Convert for U256ToBalance { + fn convert(n: sp_core::U256) -> Balance { + n.try_into().unwrap() + } +} + +parameter_types! { + pub const PostUnbondingPoolsWindow: u32 = 10; + pub const PoolsPalletId: PalletId = PalletId(*b"py/nopls"); + pub static LegacyAdapter: bool = false; +} + +pub struct MockAdapter; +type DelegateStake = + pallet_nomination_pools::adapter::DelegateStake; +type TransferStake = pallet_nomination_pools::adapter::TransferStake; +impl pallet_nomination_pools::adapter::StakeStrategy for MockAdapter { + type Balance = Balance; + type AccountId = AccountId; + type CoreStaking = Staking; + + fn strategy_type() -> StakeStrategyType { + if LegacyAdapter::get() { + return TransferStake::strategy_type() + } + DelegateStake::strategy_type() + } + fn transferable_balance(pool_account: &Self::AccountId) -> Self::Balance { + if LegacyAdapter::get() { + return TransferStake::transferable_balance(pool_account) + } + DelegateStake::transferable_balance(pool_account) + } + + fn total_balance(pool_account: &Self::AccountId) -> Self::Balance { + if LegacyAdapter::get() { + return TransferStake::total_balance(pool_account) + } + DelegateStake::total_balance(pool_account) + } + + fn member_delegation_balance(member_account: &Self::AccountId) -> Self::Balance { + if LegacyAdapter::get() { + return TransferStake::member_delegation_balance(member_account) + } + DelegateStake::member_delegation_balance(member_account) + } + + fn pledge_bond( + who: &Self::AccountId, + pool_account: &Self::AccountId, + reward_account: &Self::AccountId, + amount: Self::Balance, + bond_type: BondType, + ) -> DispatchResult { + if LegacyAdapter::get() { + return TransferStake::pledge_bond(who, pool_account, reward_account, amount, bond_type) + } + DelegateStake::pledge_bond(who, pool_account, reward_account, amount, bond_type) + } + + fn member_withdraw( + who: &Self::AccountId, + pool_account: &Self::AccountId, + amount: Self::Balance, + num_slashing_spans: u32, + ) -> DispatchResult { + if LegacyAdapter::get() { + return TransferStake::member_withdraw(who, pool_account, amount, num_slashing_spans) + } + DelegateStake::member_withdraw(who, pool_account, amount, num_slashing_spans) + } + + fn has_pending_slash(pool_account: &Self::AccountId) -> bool { + if LegacyAdapter::get() { + return TransferStake::has_pending_slash(pool_account) + } + DelegateStake::has_pending_slash(pool_account) + } + + fn member_slash( + who: &Self::AccountId, + pool_account: &Self::AccountId, + amount: Self::Balance, + maybe_reporter: Option, + ) -> DispatchResult { + if LegacyAdapter::get() { + return TransferStake::member_slash(who, pool_account, amount, maybe_reporter) + } + DelegateStake::member_slash(who, pool_account, amount, maybe_reporter) + } + + fn migrate_nominator_to_agent( + agent: &Self::AccountId, + reward_account: &Self::AccountId, + ) -> DispatchResult { + if LegacyAdapter::get() { + return TransferStake::migrate_nominator_to_agent(agent, reward_account) + } + DelegateStake::migrate_nominator_to_agent(agent, reward_account) + } + + fn migrate_delegation( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + ) -> DispatchResult { + if LegacyAdapter::get() { + return TransferStake::migrate_delegation(agent, delegator, value) + } + DelegateStake::migrate_delegation(agent, delegator, value) + } +} +impl pallet_nomination_pools::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type Currency = Balances; + type RuntimeFreezeReason = RuntimeFreezeReason; + type RewardCounter = FixedU128; + type BalanceToU256 = BalanceToU256; + type U256ToBalance = U256ToBalance; + type StakeAdapter = MockAdapter; + type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; + type MaxMetadataLen = ConstU32<256>; + type MaxUnbonding = ConstU32<8>; + type MaxPointsToBalance = ConstU8<10>; + type PalletId = PoolsPalletId; + type AdminOrigin = EnsureRoot; +} + +parameter_types! { + pub const DelegatedStakingPalletId: PalletId = PalletId(*b"py/dlstk"); + pub const SlashRewardFraction: Perbill = Perbill::from_percent(1); +} +impl pallet_delegated_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = DelegatedStakingPalletId; + type Currency = Balances; + type OnSlash = (); + type SlashRewardFraction = SlashRewardFraction; + type RuntimeHoldReason = RuntimeHoldReason; + type CoreStaking = Staking; +} +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Runtime { + System: frame_system, + Timestamp: pallet_timestamp, + Balances: pallet_balances, + Staking: pallet_staking, + VoterList: pallet_bags_list::, + Pools: pallet_nomination_pools, + DelegatedStaking: pallet_delegated_staking, + } +); + +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let _ = pallet_nomination_pools::GenesisConfig:: { + min_join_bond: 2, + min_create_bond: 2, + max_pools: Some(3), + max_members_per_pool: Some(5), + max_members: Some(3 * 5), + global_max_commission: Some(Perbill::from_percent(90)), + } + .assimilate_storage(&mut storage) + .unwrap(); + + let _ = pallet_balances::GenesisConfig:: { + balances: vec![(10, 100), (20, 100), (21, 100), (22, 100)], + } + .assimilate_storage(&mut storage) + .unwrap(); + + let mut ext = sp_io::TestExternalities::from(storage); + + ext.execute_with(|| { + // for events to be deposited. + frame_system::Pallet::::set_block_number(1); + + // set some limit for nominations. + assert_ok!(Staking::set_staking_configs( + RuntimeOrigin::root(), + pallet_staking::ConfigOp::Set(10), // minimum nominator bond + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + )); + }); + + ext +} + +parameter_types! { + static ObservedEventsPools: usize = 0; + static ObservedEventsStaking: usize = 0; + static ObservedEventsBalances: usize = 0; + static ObservedEventsDelegatedStaking: usize = 0; +} + +pub(crate) fn pool_events_since_last_call() -> Vec> { + let events = System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| if let RuntimeEvent::Pools(inner) = e { Some(inner) } else { None }) + .collect::>(); + let already_seen = ObservedEventsPools::get(); + ObservedEventsPools::set(events.len()); + events.into_iter().skip(already_seen).collect() +} + +pub(crate) fn staking_events_since_last_call() -> Vec> { + let events = System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| if let RuntimeEvent::Staking(inner) = e { Some(inner) } else { None }) + .collect::>(); + let already_seen = ObservedEventsStaking::get(); + ObservedEventsStaking::set(events.len()); + events.into_iter().skip(already_seen).collect() +} + +pub(crate) fn delegated_staking_events_since_last_call( +) -> Vec> { + let events = System::events() + .into_iter() + .map(|r| r.event) + .filter_map( + |e| if let RuntimeEvent::DelegatedStaking(inner) = e { Some(inner) } else { None }, + ) + .collect::>(); + let already_seen = ObservedEventsDelegatedStaking::get(); + ObservedEventsDelegatedStaking::set(events.len()); + events.into_iter().skip(already_seen).collect() +} diff --git a/substrate/frame/nomination-pools/test-staking/Cargo.toml b/substrate/frame/nomination-pools/test-transfer-stake/Cargo.toml similarity index 89% rename from substrate/frame/nomination-pools/test-staking/Cargo.toml rename to substrate/frame/nomination-pools/test-transfer-stake/Cargo.toml index 130a27752bf37768d34bcbc1012f51524c2df277..5f9bc9af3a214eb3d82da11786c93bf462565a26 100644 --- a/substrate/frame/nomination-pools/test-staking/Cargo.toml +++ b/substrate/frame/nomination-pools/test-transfer-stake/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-nomination-pools-test-staking" +name = "pallet-nomination-pools-test-transfer-stake" version = "1.0.0" authors.workspace = true edition.workspace = true @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } scale-info = { version = "2.11.1", features = ["derive"] } sp-runtime = { path = "../../../primitives/runtime" } diff --git a/substrate/frame/nomination-pools/test-staking/src/lib.rs b/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs similarity index 90% rename from substrate/frame/nomination-pools/test-staking/src/lib.rs rename to substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs index d84e09e32ba353267e3a2629a372bd189137454d..aa91350259000b810eb63a0036754517eeb8421d 100644 --- a/substrate/frame/nomination-pools/test-staking/src/lib.rs +++ b/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs @@ -193,6 +193,95 @@ fn pool_lifecycle_e2e() { }) } +#[test] +fn destroy_pool_with_erroneous_consumer() { + new_test_ext().execute_with(|| { + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + // expect consumers on pool account to be 2 (staking lock and an explicit inc by staking). + assert_eq!(frame_system::Pallet::::consumers(&POOL1_BONDED), 2); + + // increment consumer by 1 reproducing the erroneous consumer bug. + // refer https://github.com/paritytech/polkadot-sdk/issues/4440. + assert_ok!(frame_system::Pallet::::inc_consumers(&POOL1_BONDED)); + assert_eq!(frame_system::Pallet::::consumers(&POOL1_BONDED), 3); + + // have the pool nominate. + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + ] + ); + + // pool goes into destroying + assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying)); + + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying },] + ); + + // move to era 1 + CurrentEra::::set(Some(1)); + + // depositor need to chill before unbonding + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(10), 10, 50), + pallet_staking::Error::::InsufficientBond + ); + + assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); + assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Chilled { stash: POOL1_BONDED }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 50 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![PoolsEvent::Unbonded { + member: 10, + pool_id: 1, + points: 50, + balance: 50, + era: 1 + 3 + }] + ); + + // waiting bonding duration: + CurrentEra::::set(Some(1 + 3)); + // this should work even with an extra consumer count on pool account. + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 1)); + + // pools is fully destroyed now. + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 50 },] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Withdrawn { member: 10, pool_id: 1, points: 50, balance: 50 }, + PoolsEvent::MemberRemoved { pool_id: 1, member: 10 }, + PoolsEvent::Destroyed { pool_id: 1 } + ] + ); + }) +} + #[test] fn pool_chill_e2e() { new_test_ext().execute_with(|| { diff --git a/substrate/frame/nomination-pools/test-staking/src/mock.rs b/substrate/frame/nomination-pools/test-transfer-stake/src/mock.rs similarity index 98% rename from substrate/frame/nomination-pools/test-staking/src/mock.rs rename to substrate/frame/nomination-pools/test-transfer-stake/src/mock.rs index 93a05ddfae990108c7277c2448ff1470ae11d2ae..0970570453b469138774eeb783914990deb0938b 100644 --- a/substrate/frame/nomination-pools/test-staking/src/mock.rs +++ b/substrate/frame/nomination-pools/test-transfer-stake/src/mock.rs @@ -180,7 +180,7 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type Staking = Staking; + type StakeAdapter = pallet_nomination_pools::adapter::TransferStake; type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; type MaxMetadataLen = ConstU32<256>; type MaxUnbonding = ConstU32<8>; diff --git a/substrate/frame/offences/Cargo.toml b/substrate/frame/offences/Cargo.toml index f8efc88bafc1aa3ec4bceb9150d62268499d62b3..a59ef9334f0bc3cba6a92943a1cbbdbe4d3c94d1 100644 --- a/substrate/frame/offences/Cargo.toml +++ b/substrate/frame/offences/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/offences/benchmarking/Cargo.toml b/substrate/frame/offences/benchmarking/Cargo.toml index 07905a1e0aa42d2aa859046b595569e275fe778a..bbd918a2883f30afb82310424375eb3ed5b5a8e8 100644 --- a/substrate/frame/offences/benchmarking/Cargo.toml +++ b/substrate/frame/offences/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../../benchmarking", default-features = false } frame-election-provider-support = { path = "../../election-provider-support", default-features = false } diff --git a/substrate/frame/offences/src/mock.rs b/substrate/frame/offences/src/mock.rs index 9a3120e41eaa0ae04ef4d211868c53782e3a4cbf..1725f4158d3338c4484676fcacf22be12cd4d321 100644 --- a/substrate/frame/offences/src/mock.rs +++ b/substrate/frame/offences/src/mock.rs @@ -24,7 +24,7 @@ use crate::Config; use codec::Encode; use frame_support::{ derive_impl, parameter_types, - traits::{ConstU32, ConstU64}, + traits::ConstU32, weights::{constants::RocksDbWeight, Weight}, }; use sp_core::H256; @@ -88,7 +88,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/paged-list/Cargo.toml b/substrate/frame/paged-list/Cargo.toml index 26f3d7e48ced011697194abe734f87bee84756ee..f550e694349468efcca9bacf51242d378b64ba64 100644 --- a/substrate/frame/paged-list/Cargo.toml +++ b/substrate/frame/paged-list/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } docify = "0.2.8" scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/paged-list/src/mock.rs b/substrate/frame/paged-list/src/mock.rs index 5d06170aae7f991ae1e0b77c530272cbd5ef14dd..e086b4ba2b27b300b63711dbc6436bb7974a2423 100644 --- a/substrate/frame/paged-list/src/mock.rs +++ b/substrate/frame/paged-list/src/mock.rs @@ -20,10 +20,7 @@ #![cfg(feature = "std")] use crate::{paged_list::StoragePagedListMeta, Config, ListPrefix}; -use frame_support::{ - derive_impl, - traits::{ConstU16, ConstU64}, -}; +use frame_support::{derive_impl, traits::ConstU16}; use sp_core::H256; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, @@ -56,7 +53,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/parameters/Cargo.toml b/substrate/frame/parameters/Cargo.toml index b718b391019a701194678e819a1c823371e15231..c4d6d189d2d2c2a33a428cdcf3290c629464662b 100644 --- a/substrate/frame/parameters/Cargo.toml +++ b/substrate/frame/parameters/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Acala Developers", "Parity Technologies "] edition.workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } paste = { version = "1.0.14", default-features = false } serde = { features = ["derive"], optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/preimage/Cargo.toml b/substrate/frame/preimage/Cargo.toml index d67fc7bead04c4dc01aca6494d823c786d69715c..d420accbd6d914816d00a57879d7187f0d0d4ead 100644 --- a/substrate/frame/preimage/Cargo.toml +++ b/substrate/frame/preimage/Cargo.toml @@ -12,7 +12,7 @@ description = "FRAME pallet for storing preimages of hashes" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/proxy/Cargo.toml b/substrate/frame/proxy/Cargo.toml index 0a3b39e471d429f6bc5cfdec203aa085d8f6144e..fcebbb5f3e8a077c8505f333b073d384fb1646b2 100644 --- a/substrate/frame/proxy/Cargo.toml +++ b/substrate/frame/proxy/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/ranked-collective/Cargo.toml b/substrate/frame/ranked-collective/Cargo.toml index 0a6595807750388d3a99016276f69d57772bbba7..05ce76cad2bbe133a77e9c318ce8f32a57f3a659 100644 --- a/substrate/frame/ranked-collective/Cargo.toml +++ b/substrate/frame/ranked-collective/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/recovery/Cargo.toml b/substrate/frame/recovery/Cargo.toml index 43608de37fc3c08ecb9a266388c2b2b8b07d0255..2fd63597da9caf7ede188eb4a0e70a7d809bae05 100644 --- a/substrate/frame/recovery/Cargo.toml +++ b/substrate/frame/recovery/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/referenda/Cargo.toml b/substrate/frame/referenda/Cargo.toml index f4e0171443aa5181e13866edf07a98e6d1b0bf8e..dde522ff89b59a647e87dd8436cb32bf1bb0274f 100644 --- a/substrate/frame/referenda/Cargo.toml +++ b/substrate/frame/referenda/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] assert_matches = { version = "1.5", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/remark/Cargo.toml b/substrate/frame/remark/Cargo.toml index e746b0382aea105009861aa14d4a9d9c63940556..d251aacfb5b2c204a29d3098b41cba4f0317b3ca 100644 --- a/substrate/frame/remark/Cargo.toml +++ b/substrate/frame/remark/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/root-offences/Cargo.toml b/substrate/frame/root-offences/Cargo.toml index f4d83c237b9cb55a81a2ab027934dd9021981d6f..e7317d737fac125e5ebbafa2be46b0426014bd6e 100644 --- a/substrate/frame/root-offences/Cargo.toml +++ b/substrate/frame/root-offences/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } pallet-session = { path = "../session", default-features = false, features = ["historical"] } diff --git a/substrate/frame/root-testing/Cargo.toml b/substrate/frame/root-testing/Cargo.toml index bf14516ee32281558cbfba28d23f1e9f8526350a..74a3b8f479fa30df155de60d306251a7f8e7e694 100644 --- a/substrate/frame/root-testing/Cargo.toml +++ b/substrate/frame/root-testing/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } diff --git a/substrate/frame/safe-mode/Cargo.toml b/substrate/frame/safe-mode/Cargo.toml index b6b7e5a67e481a75914207410afe64a8c5b38280..7ecbdb6eeda5b16d35be7a98885ba0a027fbb89a 100644 --- a/substrate/frame/safe-mode/Cargo.toml +++ b/substrate/frame/safe-mode/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } docify = "0.2.8" frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/safe-mode/src/mock.rs b/substrate/frame/safe-mode/src/mock.rs index fbfc16f4aa2881b25db9b27c3be3c53973a925ab..0beb911267dc5265bdf14cd1f46afff27b422e55 100644 --- a/substrate/frame/safe-mode/src/mock.rs +++ b/substrate/frame/safe-mode/src/mock.rs @@ -47,7 +47,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; diff --git a/substrate/frame/salary/Cargo.toml b/substrate/frame/salary/Cargo.toml index 8c77edcb173a03ed4ed8a8c039c3e670d4bf02ce..25911269a95ddd3b51e639f56c10a647d321ba77 100644 --- a/substrate/frame/salary/Cargo.toml +++ b/substrate/frame/salary/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/sassafras/Cargo.toml b/substrate/frame/sassafras/Cargo.toml index 888b1d8f31fc587a063a6323b2789454a461cef6..82fb9a1d8c5f1bd57073d9212003f6f35da42178 100644 --- a/substrate/frame/sassafras/Cargo.toml +++ b/substrate/frame/sassafras/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -scale-codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +scale-codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } @@ -29,7 +29,7 @@ sp-runtime = { path = "../../primitives/runtime", default-features = false } sp-std = { path = "../../primitives/std", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" sp-core = { path = "../../primitives/core" } sp-crypto-hashing = { path = "../../primitives/crypto/hashing" } diff --git a/substrate/frame/scheduler/Cargo.toml b/substrate/frame/scheduler/Cargo.toml index 40a71736447076d10fd6d8f668a019581f5911f3..e851f876112e8829a7914b18f5695436040ebbb8 100644 --- a/substrate/frame/scheduler/Cargo.toml +++ b/substrate/frame/scheduler/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/scored-pool/Cargo.toml b/substrate/frame/scored-pool/Cargo.toml index 92b70e01b9ab7e37d0274b434b357eb654773e83..f25bd1f1769ba458c8ea8c88ac9d0e18ce8fde2e 100644 --- a/substrate/frame/scored-pool/Cargo.toml +++ b/substrate/frame/scored-pool/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } diff --git a/substrate/frame/session/Cargo.toml b/substrate/frame/session/Cargo.toml index 86814f8276e7bed8625f726b17d5ea18c6cf604f..42ea957ac1581fa8434d94a0737597d82f4b74e5 100644 --- a/substrate/frame/session/Cargo.toml +++ b/substrate/frame/session/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2.2" log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } diff --git a/substrate/frame/session/benchmarking/Cargo.toml b/substrate/frame/session/benchmarking/Cargo.toml index a00fbd8f6fdf5452b1e225332efaac7f0d09adfb..a306f9015c02913da0f2ebf96a252a86f4333c51 100644 --- a/substrate/frame/session/benchmarking/Cargo.toml +++ b/substrate/frame/session/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } rand = { version = "0.8.5", default-features = false, features = ["std_rng"] } frame-benchmarking = { path = "../../benchmarking", default-features = false } frame-support = { path = "../../support", default-features = false } @@ -28,7 +28,7 @@ sp-session = { path = "../../../primitives/session", default-features = false } sp-std = { path = "../../../primitives/std", default-features = false } [dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } scale-info = "2.11.1" frame-election-provider-support = { path = "../../election-provider-support" } pallet-balances = { path = "../../balances" } diff --git a/substrate/frame/society/Cargo.toml b/substrate/frame/society/Cargo.toml index 3d99ddba392bcee045d122e6b898552d0f5e9b75..ed7fea523bffbd15a4da83e16f167ba239ecfca8 100644 --- a/substrate/frame/society/Cargo.toml +++ b/substrate/frame/society/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { workspace = true } -rand_chacha = { version = "0.2", default-features = false } +rand_chacha = { version = "0.3.1", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } sp-std = { path = "../../primitives/std", default-features = false } sp-io = { path = "../../primitives/io", default-features = false } diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index 90c446808daff46c544048b3e841569a249953aa..f6507cd02c71ae5542836119821fc29070a24f6a 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -363,5 +363,15 @@ pub mod deps { #[cfg(feature = "runtime")] pub use sp_offchain; #[cfg(feature = "runtime")] + pub use sp_storage; + #[cfg(feature = "runtime")] pub use sp_version; + + #[cfg(feature = "runtime-benchmarks")] + pub use frame_benchmarking; + #[cfg(feature = "runtime-benchmarks")] + pub use frame_system_benchmarking; + + #[cfg(feature = "frame-try-runtime")] + pub use frame_try_runtime; } diff --git a/substrate/frame/staking/Cargo.toml b/substrate/frame/staking/Cargo.toml index 4fd0cedbae63fb3c484549c2f4388f912e7a428d..22df746d667ab477dc576c6c085bbf1bf1675fb6 100644 --- a/substrate/frame/staking/Cargo.toml +++ b/substrate/frame/staking/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { features = ["alloc", "derive"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } @@ -37,7 +37,7 @@ log = { workspace = true } # Optional imports for benchmarking frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } -rand_chacha = { version = "0.2", default-features = false, optional = true } +rand_chacha = { version = "0.3.1", default-features = false, optional = true } [dev-dependencies] pallet-balances = { path = "../balances" } @@ -50,7 +50,7 @@ pallet-bags-list = { path = "../bags-list" } substrate-test-utils = { path = "../../test-utils" } frame-benchmarking = { path = "../benchmarking" } frame-election-provider-support = { path = "../election-provider-support" } -rand_chacha = { version = "0.2" } +rand_chacha = { version = "0.3.1" } [features] default = ["std"] diff --git a/substrate/frame/staking/reward-curve/src/lib.rs b/substrate/frame/staking/reward-curve/src/lib.rs index 1986357edabe20cca94d0d0e26e1bee54e08a0ac..cfb8b896f9394ad06223da2097a91b620fcf30d4 100644 --- a/substrate/frame/staking/reward-curve/src/lib.rs +++ b/substrate/frame/staking/reward-curve/src/lib.rs @@ -88,7 +88,13 @@ pub fn build(input: TokenStream) -> TokenStream { let ident = syn::Ident::new(&sp_runtime, Span::call_site()); quote!( #[doc(hidden)] pub use #ident as _sp_runtime; ) }, - Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(), + Err(e) => match crate_name("polkadot-sdk") { + Ok(FoundCrate::Name(polkadot_sdk)) => { + let ident = syn::Ident::new(&polkadot_sdk, Span::call_site()); + quote!( #[doc(hidden)] pub use #ident::sp_runtime as _sp_runtime; ) + }, + _ => syn::Error::new(Span::call_site(), e).to_compile_error(), + }, }; let const_name = input.ident; diff --git a/substrate/frame/staking/runtime-api/Cargo.toml b/substrate/frame/staking/runtime-api/Cargo.toml index 50a19be92da8e6be4ddaf8fe29e649ee7b59c256..19da2f24ff00e80321e20506b2fe13a0ddd71978 100644 --- a/substrate/frame/staking/runtime-api/Cargo.toml +++ b/substrate/frame/staking/runtime-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } sp-api = { default-features = false, path = "../../../primitives/api" } sp-staking = { default-features = false, path = "../../../primitives/staking" } diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 67a86b86226cfb1aa5da4c8bca794f315f348009..294918376d82ce5a8473a5353cea0dc5cdd1ba50 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -35,7 +35,7 @@ use frame_support::{ defensive, ensure, traits::{Defensive, LockableCurrency}, }; -use sp_staking::StakingAccount; +use sp_staking::{StakingAccount, StakingInterface}; use sp_std::prelude::*; use crate::{ diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs index 692e62acfdff503c515344434c5155ebd7622d13..053ecdef2b00b7bb900443153f63e64f51d89252 100644 --- a/substrate/frame/staking/src/lib.rs +++ b/substrate/frame/staking/src/lib.rs @@ -361,7 +361,7 @@ pub type BalanceOf = ::CurrencyBalance; type PositiveImbalanceOf = <::Currency as Currency< ::AccountId, >>::PositiveImbalance; -type NegativeImbalanceOf = <::Currency as Currency< +pub type NegativeImbalanceOf = <::Currency as Currency< ::AccountId, >>::NegativeImbalance; @@ -376,7 +376,7 @@ pub struct ActiveEraInfo { /// /// Start can be none if start hasn't been set for the era yet, /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. - start: Option, + pub start: Option, } /// Reward points of an era. Used to split era total payout between validators. diff --git a/substrate/frame/staking/src/migrations.rs b/substrate/frame/staking/src/migrations.rs index 510252be26c93e95e640af601ad8efdfd8801383..b2ddf77004f95ecf86df6d177cdb6af454947657 100644 --- a/substrate/frame/staking/src/migrations.rs +++ b/substrate/frame/staking/src/migrations.rs @@ -370,7 +370,7 @@ pub mod v10 { StorageVersion::::put(ObsoleteReleases::V10_0_0); log!(info, "MigrateToV10 executed successfully"); - T::DbWeight::get().reads_writes(1, 1) + T::DbWeight::get().reads_writes(1, 2) } else { log!(warn, "MigrateToV10 should be removed."); T::DbWeight::get().reads(1) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 5b2a55303e2c855a814f0d4f9705fb7d89b2767c..90374451a3a5266362699e6fc55e957a552ba157 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -198,8 +198,9 @@ impl Pallet { } let new_total = ledger.total; + let ed = T::Currency::minimum_balance(); let used_weight = - if ledger.unlocking.is_empty() && ledger.active < T::Currency::minimum_balance() { + if ledger.unlocking.is_empty() && (ledger.active < ed || ledger.active.is_zero()) { // This account must have called `unbond()` with some value that caused the active // portion to fall below existential deposit + will have no more unlocking chunks // left. We can now safely remove all staking-related information. @@ -1160,11 +1161,6 @@ impl Pallet { ) -> Exposure> { EraInfo::::get_full_exposure(era, account) } - - /// Whether `who` is a virtual staker whose funds are managed by another pallet. - pub(crate) fn is_virtual_staker(who: &T::AccountId) -> bool { - VirtualStakers::::contains_key(who) - } } impl Pallet { @@ -1884,6 +1880,11 @@ impl StakingInterface for Pallet { } } + /// Whether `who` is a virtual staker whose funds are managed by another pallet. + fn is_virtual_staker(who: &T::AccountId) -> bool { + VirtualStakers::::contains_key(who) + } + fn slash_reward_fraction() -> Perbill { SlashRewardFraction::::get() } diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 16ad510c562bff4590fa1b7ebc7b3daf3145a2a4..284a801a0f050eb79672feb2e1167e5d14f033a5 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -39,6 +39,7 @@ use sp_runtime::{ use sp_staking::{ EraIndex, Page, SessionIndex, StakingAccount::{self, Controller, Stash}, + StakingInterface, }; use sp_std::prelude::*; @@ -938,7 +939,8 @@ pub mod pallet { /// - 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. + /// unless the `origin` falls below _existential deposit_ (or equal to 0) and gets removed + /// as dust. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::bond())] pub fn bond( @@ -1615,6 +1617,7 @@ pub mod pallet { /// /// 1. the `total_balance` of the stash is below existential deposit. /// 2. or, the `ledger.total` of the stash is below existential deposit. + /// 3. or, existential deposit is zero and either `total_balance` or `ledger.total` is zero. /// /// The former can happen in cases like a slash; the latter when a fully unbonded account /// is still receiving staking rewards in `RewardDestination::Staked`. @@ -1640,8 +1643,13 @@ pub mod pallet { ensure!(!Self::is_virtual_staker(&stash), Error::::VirtualStakerNotAllowed); let ed = T::Currency::minimum_balance(); - let reapable = T::Currency::total_balance(&stash) < ed || - Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default() < ed; + let origin_balance = T::Currency::total_balance(&stash); + let ledger_total = + Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default(); + let reapable = origin_balance < ed || + origin_balance.is_zero() || + ledger_total < ed || + ledger_total.is_zero(); ensure!(reapable, Error::::FundedTarget); // Remove all staking-related information and lock. diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs index f831f625957d4c495fce3b239e68faed737cb3ab..1fe608cd3358bb8d7ab113ee96d720df4998c759 100644 --- a/substrate/frame/staking/src/slashing.rs +++ b/substrate/frame/staking/src/slashing.rs @@ -64,7 +64,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; -use sp_staking::EraIndex; +use sp_staking::{EraIndex, StakingInterface}; use sp_std::vec::Vec; /// The proportion of the slashing reward to be paid out on the first slashing detection. diff --git a/substrate/frame/staking/src/testing_utils.rs b/substrate/frame/staking/src/testing_utils.rs index 28e08230d701d6cc477c840311b274d0535a88bf..d4938ea43ebe2800b3894a21e17f93e45d591ff5 100644 --- a/substrate/frame/staking/src/testing_utils.rs +++ b/substrate/frame/staking/src/testing_utils.rs @@ -77,7 +77,8 @@ pub fn create_stash_controller( destination: RewardDestination, ) -> Result<(T::AccountId, T::AccountId), &'static str> { let staker = create_funded_user::("stash", n, balance_factor); - let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + let amount = + T::Currency::minimum_balance().max(1u64.into()) * (balance_factor / 10).max(1).into(); Staking::::bond(RawOrigin::Signed(staker.clone()).into(), amount, destination)?; Ok((staker.clone(), staker)) } diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 3cb51604aa6bb1fc7abe06af069d666e70b223c6..76afa3333cb465b9f7f9e119871730f31fcd6720 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -1931,6 +1931,44 @@ fn reap_stash_works() { }); } +#[test] +fn reap_stash_works_with_existential_deposit_zero() { + ExtBuilder::default() + .existential_deposit(0) + .balance_factor(10) + .build_and_execute(|| { + // given + assert_eq!(Balances::balance_locked(STAKING_ID, &11), 10 * 1000); + assert_eq!(Staking::bonded(&11), Some(11)); + + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + assert!(>::contains_key(&11)); + + // stash is not reapable + assert_noop!( + Staking::reap_stash(RuntimeOrigin::signed(20), 11, 0), + Error::::FundedTarget + ); + + // no easy way to cause an account to go below ED, we tweak their staking ledger + // instead. + Ledger::::insert(11, StakingLedger::::new(11, 0)); + + // reap-able + assert_ok!(Staking::reap_stash(RuntimeOrigin::signed(20), 11, 0)); + + // then + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + // lock is removed. + assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0); + }); +} + #[test] fn switching_roles() { // Test that it should be possible to switch between roles (nominator, validator, idle) with @@ -6953,6 +6991,59 @@ mod staking_interface { }); } + #[test] + fn do_withdraw_unbonded_can_kill_stash_with_existential_deposit_zero() { + ExtBuilder::default() + .existential_deposit(0) + .nominate(false) + .build_and_execute(|| { + // Initial state of 11 + assert_eq!(Staking::bonded(&11), Some(11)); + assert_eq!( + Staking::ledger(11.into()).unwrap(), + StakingLedgerInspect { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![], + } + ); + assert_eq!( + Staking::eras_stakers(active_era(), &11), + Exposure { total: 1000, own: 1000, others: vec![] } + ); + + // Unbond all of the funds in stash. + Staking::chill(RuntimeOrigin::signed(11)).unwrap(); + Staking::unbond(RuntimeOrigin::signed(11), 1000).unwrap(); + assert_eq!( + Staking::ledger(11.into()).unwrap(), + StakingLedgerInspect { + stash: 11, + total: 1000, + active: 0, + unlocking: bounded_vec![UnlockChunk { value: 1000, era: 3 }], + legacy_claimed_rewards: bounded_vec![], + }, + ); + + // trigger future era. + mock::start_active_era(3); + + // withdraw unbonded + assert_ok!(Staking::withdraw_unbonded(RuntimeOrigin::signed(11), 0)); + + // empty stash has been reaped + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + assert!(!>::contains_key(&11)); + // lock is removed. + assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0); + }); + } + #[test] fn status() { ExtBuilder::default().build_and_execute(|| { diff --git a/substrate/frame/state-trie-migration/Cargo.toml b/substrate/frame/state-trie-migration/Cargo.toml index 613308c308e1f15eace901af1a192202f1aa8cad..0870989d81f15df54cec9c41a0fa408edb45af36 100644 --- a/substrate/frame/state-trie-migration/Cargo.toml +++ b/substrate/frame/state-trie-migration/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index 5c54c27966cd6951309ff320d942fac1ba15e9c7..4ec649f9080d463dcf72dbb96e9a34ce49124af0 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -1103,11 +1103,7 @@ mod benchmarks { mod mock { use super::*; use crate as pallet_state_trie_migration; - use frame_support::{ - derive_impl, parameter_types, - traits::{ConstU32, Hooks}, - weights::Weight, - }; + use frame_support::{derive_impl, parameter_types, traits::Hooks, weights::Weight}; use frame_system::{EnsureRoot, EnsureSigned}; use sp_core::{ storage::{ChildInfo, StateVersion}, @@ -1134,7 +1130,6 @@ mod mock { #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; - type BlockHashCount = ConstU32<250>; type AccountData = pallet_balances::AccountData; } diff --git a/substrate/frame/statement/Cargo.toml b/substrate/frame/statement/Cargo.toml index 92bc32191ab84d41e9dd18ef5f3863d2c5502edd..989f0c330fc10b19bde46d92d853fcbdef2b463a 100644 --- a/substrate/frame/statement/Cargo.toml +++ b/substrate/frame/statement/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } diff --git a/substrate/frame/sudo/Cargo.toml b/substrate/frame/sudo/Cargo.toml index 805f46a77f2eb0c3f7433a83659972a9d7da65c7..fcbb00087e26c7b08a00227c142a2565b2c0c04b 100644 --- a/substrate/frame/sudo/Cargo.toml +++ b/substrate/frame/sudo/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index ecdd93826327798a76b36a54dc6ad0a2b0106c24..a6c4fd6ee309ec4fc07495b59df341b854dfb1a9 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -16,9 +16,9 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = { version = "6.1", default-features = false } +array-bytes = { version = "6.2.2", default-features = false } serde = { features = ["alloc", "derive"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 9f8727f7adef58b68876dadc8907877c886d2d5d..b04af63de81174d02592c6d7caa51ad902c10ca8 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -21,7 +21,7 @@ proc-macro = true derive-syn-parse = "0.2.0" Inflector = "0.11.4" cfg-expr = "0.15.5" -itertools = "0.10.3" +itertools = "0.11" proc-macro2 = "1.0.56" quote = { workspace = true } syn = { features = ["full", "visit-mut"], workspace = true } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 53f01329d1815d280031574ca232a166e7f8148e..e812ac071b2c9a2cf2e8ef199c2e1d656b7f0494 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1249,7 +1249,6 @@ pub fn import_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { /// /// * The macro generates a type alias for each pallet to their `Pallet`. E.g. `type System = /// frame_system::Pallet` -#[cfg(feature = "experimental")] #[proc_macro_attribute] pub fn runtime(attr: TokenStream, item: TokenStream) -> TokenStream { runtime::runtime(attr, item) diff --git a/substrate/frame/support/procedural/src/pallet/expand/storage.rs b/substrate/frame/support/procedural/src/pallet/expand/storage.rs index 937b068cfabd14e04b05177be2f0242eccd3abec..3cc8a843e3b1669aa054040a49101ee4ae8d3f5f 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/storage.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/storage.rs @@ -854,7 +854,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { for #pallet_ident<#type_use_gen> #completed_where_clause { fn try_decode_entire_state() -> Result> { - let pallet_name = <::PalletInfo as frame_support::traits::PalletInfo> + let pallet_name = <::PalletInfo as #frame_support::traits::PalletInfo> ::name::<#pallet_ident<#type_use_gen>>() .expect("Every active pallet has a name in the runtime; qed"); diff --git a/substrate/frame/support/procedural/src/runtime/mod.rs b/substrate/frame/support/procedural/src/runtime/mod.rs index aaae579eb086638f1bfacf02105a8fcd0e3d01b5..1d4242cd122eb798d82494ef2f4d630571f2d518 100644 --- a/substrate/frame/support/procedural/src/runtime/mod.rs +++ b/substrate/frame/support/procedural/src/runtime/mod.rs @@ -200,8 +200,6 @@ //! +----------------------+ //! ``` -#![cfg(feature = "experimental")] - pub use parse::Def; use proc_macro::TokenStream; use syn::spanned::Spanned; diff --git a/substrate/frame/support/procedural/tools/src/lib.rs b/substrate/frame/support/procedural/tools/src/lib.rs index 8952cd6011ff5bb717a9e731d09525d160d95739..ea53335a88fd4565e41680e2393b9affb248c975 100644 --- a/substrate/frame/support/procedural/tools/src/lib.rs +++ b/substrate/frame/support/procedural/tools/src/lib.rs @@ -70,6 +70,8 @@ pub fn is_using_frame_crate(path: &syn::Path) -> bool { pub fn generate_access_from_frame_or_crate(def_crate: &str) -> Result { if let Some(path) = get_frame_crate_path(def_crate) { Ok(path) + } else if let Some(path) = get_sdk_crate_path(def_crate) { + Ok(path) } else { let ident = match crate_name(def_crate) { Ok(FoundCrate::Itself) => { @@ -95,6 +97,13 @@ pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream pub use #path as hidden_include; } ) + } else if let Some(path) = get_sdk_crate_path(def_crate) { + quote::quote!( + #[doc(hidden)] + mod #mod_name { + pub use #path as hidden_include; + } + ) } else { match crate_name(def_crate) { Ok(FoundCrate::Itself) => quote!(), @@ -128,6 +137,15 @@ fn get_frame_crate_path(def_crate: &str) -> Option { } } +fn get_sdk_crate_path(def_crate: &str) -> Option { + if let Ok(FoundCrate::Name(name)) = crate_name(&"polkadot-sdk") { + let path = format!("{}::{}", name, def_crate.to_string()).replace("-", "_"); + Some(syn::parse_str::(&path).expect("is a valid path; qed")) + } else { + None + } +} + // fn to remove white spaces around string types // (basically whitespaces around tokens) pub fn clean_type_string(input: &str) -> String { diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 7eddea1259d7d040e57084232feb53eb2b6b1270..8ae1f56b4d686e6d6aa637aac1f6f2a0973e6157 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -508,7 +508,6 @@ pub use frame_support_procedural::{ construct_runtime, match_and_insert, transactional, PalletError, RuntimeDebugNoBound, }; -#[cfg(feature = "experimental")] pub use frame_support_procedural::runtime; #[doc(hidden)] diff --git a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/inspect_mutate.rs b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/inspect_mutate.rs index 732742cca9b54aaf08b9bf42a1898709e556e693..fb52eb7037dbdbe3f0cbcfe66deb9c743ddf378d 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/inspect_mutate.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/inspect_mutate.rs @@ -166,9 +166,10 @@ where // Test: Burn an exact amount from the account let amount_to_burn = T::Balance::from(5); + let preservation = Preservation::Expendable; let precision = Precision::Exact; let force = Fortitude::Polite; - T::burn_from(&account, amount_to_burn, precision, force).unwrap(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap(); // Verify: The balance and total issuance should be reduced by the burned amount assert_eq!(T::balance(&account), initial_balance - amount_to_burn); @@ -209,10 +210,11 @@ where // Test: Burn a best effort amount from the account that is greater than the reducible balance let amount_to_burn = reducible_balance + 5.into(); + let preservation = Preservation::Expendable; let precision = Precision::BestEffort; assert!(amount_to_burn > reducible_balance); assert!(amount_to_burn > T::balance(&account)); - T::burn_from(&account, amount_to_burn, precision, force).unwrap(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap(); // Verify: The balance and total issuance should be reduced by the reducible_balance assert_eq!(T::balance(&account), initial_balance - reducible_balance); @@ -248,9 +250,10 @@ where // Verify: Burn an amount greater than the account's balance with Exact precision returns Err let amount_to_burn = initial_balance + 10.into(); + let preservation = Preservation::Expendable; let precision = Precision::Exact; let force = Fortitude::Polite; - T::burn_from(&account, amount_to_burn, precision, force).unwrap_err(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap_err(); // Verify: The balance and total issuance should remain unchanged assert_eq!(T::balance(&account), initial_balance); diff --git a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/mutate.rs b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/mutate.rs index 95b5256bb4912269b9ad7c40ba637f966035c56b..b17ce6f518c0303058c6918f46a54e03d8c3188f 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/mutate.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/mutate.rs @@ -137,9 +137,10 @@ where // Test: Burn an exact amount from the account let amount_to_burn = T::Balance::from(5); + let preservation = Preservation::Expendable; let precision = Precision::Exact; let force = Fortitude::Polite; - T::burn_from(&account, amount_to_burn, precision, force).unwrap(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap(); // Verify: The balance and total issuance should be reduced by the burned amount assert_eq!(T::balance(&account), initial_balance - amount_to_burn); @@ -174,10 +175,11 @@ where // Test: Burn a best effort amount from the account that is greater than the reducible // balance let amount_to_burn = reducible_balance + 5.into(); + let preservation = Preservation::Expendable; let precision = Precision::BestEffort; assert!(amount_to_burn > reducible_balance); assert!(amount_to_burn > T::balance(&account)); - T::burn_from(&account, amount_to_burn, precision, force).unwrap(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap(); // Verify: The balance and total issuance should be reduced by the reducible_balance assert_eq!(T::balance(&account), initial_balance - reducible_balance); @@ -207,9 +209,10 @@ where // Verify: Burn an amount greater than the account's balance with Exact precision returns // Err let amount_to_burn = initial_balance + 10.into(); + let preservation = Preservation::Expendable; let precision = Precision::Exact; let force = Fortitude::Polite; - T::burn_from(&account, amount_to_burn, precision, force).unwrap_err(); + T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap_err(); // Verify: The balance and total issuance should remain unchanged assert_eq!(T::balance(&account), initial_balance); diff --git a/substrate/frame/support/src/traits/tokens/fungible/item_of.rs b/substrate/frame/support/src/traits/tokens/fungible/item_of.rs index 5374cc52bab72a25270606e89f97a6f035f3a704..2aa53d622dbff7280cb4f2b742f490249c73ca69 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/item_of.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/item_of.rs @@ -235,10 +235,18 @@ impl< fn burn_from( who: &AccountId, amount: Self::Balance, + preservation: Preservation, precision: Precision, force: Fortitude, ) -> Result { - >::burn_from(A::get(), who, amount, precision, force) + >::burn_from( + A::get(), + who, + amount, + preservation, + precision, + force, + ) } fn shelve(who: &AccountId, amount: Self::Balance) -> Result { >::shelve(A::get(), who, amount) diff --git a/substrate/frame/support/src/traits/tokens/fungible/regular.rs b/substrate/frame/support/src/traits/tokens/fungible/regular.rs index 4ed31dcf9fb1f099ebc576ae981d289613775b60..c46614be4734c659d50619fde3734a34be14783e 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/regular.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/regular.rs @@ -254,19 +254,23 @@ where Ok(actual) } - /// Decrease the balance of `who` by at least `amount`, possibly slightly more in the case of - /// minimum-balance requirements, burning the tokens. If that isn't possible then an `Err` is - /// returned and nothing is changed. If successful, the amount of tokens reduced is returned. + /// Attempt to decrease the balance of `who`, burning the tokens. + /// The actual amount burned is derived from the `amount`, `preservation`, `precision` and + /// `force`, and might end up being more, less or equal to the `amount` specified. + /// + /// If the burn isn't possible then an `Err` is returned and nothing is changed. + /// If successful, the amount of tokens reduced is returned. fn burn_from( who: &AccountId, amount: Self::Balance, + preservation: Preservation, precision: Precision, force: Fortitude, ) -> Result { - let actual = Self::reducible_balance(who, Expendable, force).min(amount); + let actual = Self::reducible_balance(who, preservation, force).min(amount); ensure!(actual == amount || precision == BestEffort, TokenError::FundsUnavailable); Self::total_issuance().checked_sub(&actual).ok_or(ArithmeticError::Overflow)?; - let actual = Self::decrease_balance(who, actual, BestEffort, Expendable, force)?; + let actual = Self::decrease_balance(who, actual, BestEffort, preservation, force)?; Self::set_total_issuance(Self::total_issuance().saturating_sub(actual)); Self::done_burn_from(who, actual); Ok(actual) @@ -342,7 +346,8 @@ where fn set_balance(who: &AccountId, amount: Self::Balance) -> Self::Balance { let b = Self::balance(who); if b > amount { - Self::burn_from(who, b - amount, BestEffort, Force).map(|d| b.saturating_sub(d)) + Self::burn_from(who, b - amount, Expendable, BestEffort, Force) + .map(|d| b.saturating_sub(d)) } else { Self::mint_into(who, amount - b).map(|d| b.saturating_add(d)) } diff --git a/substrate/frame/support/src/traits/tokens/fungible/union_of.rs b/substrate/frame/support/src/traits/tokens/fungible/union_of.rs index db44b2f43a4e4b461c9ce4bc934e4ed1b927f55a..63791b05223701ae8c689f00c4769cb510c6e208 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/union_of.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/union_of.rs @@ -442,14 +442,26 @@ impl< asset: Self::AssetId, who: &AccountId, amount: Self::Balance, + preservation: Preservation, precision: Precision, force: Fortitude, ) -> Result { match Criterion::convert(asset) { - Left(()) => - >::burn_from(who, amount, precision, force), - Right(a) => - >::burn_from(a, who, amount, precision, force), + Left(()) => >::burn_from( + who, + amount, + preservation, + precision, + force, + ), + Right(a) => >::burn_from( + a, + who, + amount, + preservation, + precision, + force, + ), } } fn shelve( diff --git a/substrate/frame/support/src/traits/tokens/fungibles/regular.rs b/substrate/frame/support/src/traits/tokens/fungibles/regular.rs index b30e0ae3a2a3657c1a2685fa413ff120803ae187..946c4756cff6035a7619cf859cb1d71d520b4298 100644 --- a/substrate/frame/support/src/traits/tokens/fungibles/regular.rs +++ b/substrate/frame/support/src/traits/tokens/fungibles/regular.rs @@ -283,16 +283,17 @@ where asset: Self::AssetId, who: &AccountId, amount: Self::Balance, + preservation: Preservation, precision: Precision, force: Fortitude, ) -> Result { - let actual = Self::reducible_balance(asset.clone(), who, Expendable, force).min(amount); + let actual = Self::reducible_balance(asset.clone(), who, preservation, force).min(amount); ensure!(actual == amount || precision == BestEffort, TokenError::FundsUnavailable); Self::total_issuance(asset.clone()) .checked_sub(&actual) .ok_or(ArithmeticError::Overflow)?; let actual = - Self::decrease_balance(asset.clone(), who, actual, BestEffort, Expendable, force)?; + Self::decrease_balance(asset.clone(), who, actual, BestEffort, preservation, force)?; Self::set_total_issuance( asset.clone(), Self::total_issuance(asset.clone()).saturating_sub(actual), @@ -392,7 +393,8 @@ where fn set_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance) -> Self::Balance { let b = Self::balance(asset.clone(), who); if b > amount { - Self::burn_from(asset, who, b - amount, BestEffort, Force).map(|d| b.saturating_sub(d)) + Self::burn_from(asset, who, b - amount, Expendable, BestEffort, Force) + .map(|d| b.saturating_sub(d)) } else { Self::mint_into(asset, who, amount - b).map(|d| b.saturating_add(d)) } diff --git a/substrate/frame/support/src/traits/tokens/fungibles/union_of.rs b/substrate/frame/support/src/traits/tokens/fungibles/union_of.rs index 2c7d4bab7baa65be59fb74d6b2238d83775fcd56..f4259a78f0a25ae15c7413be07df0bc299342122 100644 --- a/substrate/frame/support/src/traits/tokens/fungibles/union_of.rs +++ b/substrate/frame/support/src/traits/tokens/fungibles/union_of.rs @@ -389,14 +389,27 @@ impl< asset: Self::AssetId, who: &AccountId, amount: Self::Balance, + preservation: Preservation, precision: Precision, force: Fortitude, ) -> Result { match Criterion::convert(asset) { - Left(a) => - >::burn_from(a, who, amount, precision, force), - Right(a) => - >::burn_from(a, who, amount, precision, force), + Left(a) => >::burn_from( + a, + who, + amount, + preservation, + precision, + force, + ), + Right(a) => >::burn_from( + a, + who, + amount, + preservation, + precision, + force, + ), } } fn shelve( diff --git a/substrate/frame/support/test/Cargo.toml b/substrate/frame/support/test/Cargo.toml index 88124e0a43b9cc10438e01e44d98e9f9130ca56c..6e861ad769cf71d0c1200b2039f28217a558b335 100644 --- a/substrate/frame/support/test/Cargo.toml +++ b/substrate/frame/support/test/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] static_assertions = "1.1.0" serde = { features = ["derive"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } sp-api = { path = "../../../primitives/api", default-features = false } diff --git a/substrate/frame/support/test/compile_pass/Cargo.toml b/substrate/frame/support/test/compile_pass/Cargo.toml index 3f52b4664b187675afd7bd13c4c96db62523a73b..37c069247e1875b547baa047c71a7895c686abe6 100644 --- a/substrate/frame/support/test/compile_pass/Cargo.toml +++ b/substrate/frame/support/test/compile_pass/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } renamed-frame-support = { package = "frame-support", path = "../..", default-features = false } renamed-frame-system = { package = "frame-system", path = "../../../system", default-features = false } diff --git a/substrate/frame/support/test/pallet/Cargo.toml b/substrate/frame/support/test/pallet/Cargo.toml index 7a20c3f2730629e709eb78c650b0ca4ca0d3e964..8607339a2b054530404499c23a402c2a673e2b5a 100644 --- a/substrate/frame/support/test/pallet/Cargo.toml +++ b/substrate/frame/support/test/pallet/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["derive"], workspace = true } frame-support = { path = "../..", default-features = false } diff --git a/substrate/frame/support/test/stg_frame_crate/Cargo.toml b/substrate/frame/support/test/stg_frame_crate/Cargo.toml index 554c81ab43decf222b516bf8bbd7660cab399eaf..5b97db60c00bb7c8b5b40dfa9f823fcc27b73d95 100644 --- a/substrate/frame/support/test/stg_frame_crate/Cargo.toml +++ b/substrate/frame/support/test/stg_frame_crate/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } frame = { package = "polkadot-sdk-frame", path = "../../..", default-features = false, features = ["experimental", "runtime"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 96504b7ce77525331aa55abf670df9b53bb1ad76..b28cae2ddefab062666fc6ba1334deb2b02ce9a8 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -107,7 +107,7 @@ note: required because it appears within the type `RuntimeEvent` 28 | | } | |_^ note: required by a bound in `EncodeLike` - --> $CARGO/parity-scale-codec-3.6.5/src/encode_like.rs + --> $CARGO/parity-scale-codec-3.6.12/src/encode_like.rs | | pub trait EncodeLike: Sized + Encode {} | ^^^^^ required by this bound in `EncodeLike` @@ -137,7 +137,7 @@ note: required because it appears within the type `RuntimeEvent` 28 | | } | |_^ note: required by a bound in `Decode` - --> $CARGO/parity-scale-codec-3.6.5/src/codec.rs + --> $CARGO/parity-scale-codec-3.6.12/src/codec.rs | | pub trait Decode: Sized { | ^^^^^ required by this bound in `Decode` @@ -286,7 +286,7 @@ note: required because it appears within the type `RuntimeCall` 28 | | } | |_^ note: required by a bound in `EncodeLike` - --> $CARGO/parity-scale-codec-3.6.5/src/encode_like.rs + --> $CARGO/parity-scale-codec-3.6.12/src/encode_like.rs | | pub trait EncodeLike: Sized + Encode {} | ^^^^^ required by this bound in `EncodeLike` @@ -317,7 +317,7 @@ note: required because it appears within the type `RuntimeCall` 28 | | } | |_^ note: required by a bound in `Decode` - --> $CARGO/parity-scale-codec-3.6.5/src/codec.rs + --> $CARGO/parity-scale-codec-3.6.12/src/codec.rs | | pub trait Decode: Sized { | ^^^^^ required by this bound in `Decode` diff --git a/substrate/frame/support/test/tests/final_keys.rs b/substrate/frame/support/test/tests/final_keys.rs index a777c20a1e98f7a38c4a4cc4dead81e5565b6ebc..64f56d5200354c8957d2d10915bc49d820e1c4cb 100644 --- a/substrate/frame/support/test/tests/final_keys.rs +++ b/substrate/frame/support/test/tests/final_keys.rs @@ -19,7 +19,7 @@ use codec::Encode; use frame_support::{derive_impl, storage::unhashed, StoragePrefixedMap}; use frame_system::pallet_prelude::BlockNumberFor; -use sp_core::{sr25519, ConstU32}; +use sp_core::sr25519; use sp_io::{ hashing::{blake2_128, twox_128, twox_64}, TestExternalities, @@ -213,7 +213,6 @@ frame_support::construct_runtime!( impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/genesisconfig.rs b/substrate/frame/support/test/tests/genesisconfig.rs index a82425cf6befe3c014543943ffb6a72e9f00770b..0673bcfdff3ca036d7be863ff1b169e3471ddb9e 100644 --- a/substrate/frame/support/test/tests/genesisconfig.rs +++ b/substrate/frame/support/test/tests/genesisconfig.rs @@ -17,7 +17,7 @@ use frame_support::derive_impl; use frame_system::pallet_prelude::BlockNumberFor; -use sp_core::{sr25519, ConstU32}; +use sp_core::sr25519; use sp_runtime::{ generic, traits::{BlakeTwo256, Verify}, @@ -83,7 +83,6 @@ frame_support::construct_runtime!( impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/instance.rs b/substrate/frame/support/test/tests/instance.rs index 332f5725e055eb2aa9ca70dff987f021a76d41ba..30b8338bc5c7052a6a50474cd44e46a7202ed77e 100644 --- a/substrate/frame/support/test/tests/instance.rs +++ b/substrate/frame/support/test/tests/instance.rs @@ -293,7 +293,6 @@ frame_support::construct_runtime!( impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/issue2219.rs b/substrate/frame/support/test/tests/issue2219.rs index 1542c4a6c434cec98547c533ba3f3530a5aff853..20c2773406ff111ebd03d08a89924ddf30cccdba 100644 --- a/substrate/frame/support/test/tests/issue2219.rs +++ b/substrate/frame/support/test/tests/issue2219.rs @@ -165,7 +165,6 @@ pub type Block = generic::Block; impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU64<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/origin.rs b/substrate/frame/support/test/tests/origin.rs index a25c575cc5177a4511dec8a8b24918ffde6da8d3..4f14bda184c867b54aa10246a995943835abf375 100644 --- a/substrate/frame/support/test/tests/origin.rs +++ b/substrate/frame/support/test/tests/origin.rs @@ -23,7 +23,6 @@ use frame_support::{ derive_impl, traits::{Contains, OriginTrait}, }; -use sp_core::ConstU32; use sp_runtime::{generic, traits::BlakeTwo256}; mod nested { @@ -174,7 +173,6 @@ frame_support::construct_runtime!( impl frame_system::Config for RuntimeOriginTest { type BaseCallFilter = BaseCallFilter; type Block = Block; - type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index f41e606ad7c3e927e9719afccde3d5e0266509e0..c441d4c371af0926a0508025ae5473c77fb98346 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -705,7 +705,6 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs index c79cdf93e97dc5a2f257ab9ba62a5d26e078b53f..dfe4caa476d3b9e1fa2a1024adb48eea5cdf9be9 100644 --- a/substrate/frame/support/test/tests/pallet_instance.rs +++ b/substrate/frame/support/test/tests/pallet_instance.rs @@ -308,7 +308,6 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs index 6c71b544426512c54a4320452204b0a4b62e7764..326f3530e26ecc75c30420f5e1f4575f381fbf08 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support::{derive_impl, traits::ConstU32}; +use frame_support::derive_impl; mod common; @@ -29,7 +29,6 @@ pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs index 79828119742c106763b97096ffaed85acf7381da..4149c4880cca29585d5d4dc45ec190f34e90d858 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support::{derive_impl, traits::ConstU32}; +use frame_support::derive_impl; mod common; @@ -29,7 +29,6 @@ pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs b/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs index e4ea094d0692e2f39167da014e3c3185d997ac08..3386632c13a2af834651d765aecfa723c1d4d5f9 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs +++ b/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs @@ -82,7 +82,6 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); diff --git a/substrate/frame/support/test/tests/runtime.rs b/substrate/frame/support/test/tests/runtime.rs index 7c2a8139a1345a4903766970a13bbf955aeef7c8..1f4d9110a24fc4e8f18fec0f1d7e2b714f920fa4 100644 --- a/substrate/frame/support/test/tests/runtime.rs +++ b/substrate/frame/support/test/tests/runtime.rs @@ -27,7 +27,7 @@ use frame_support::{ }; use frame_system::limits::{BlockLength, BlockWeights}; use scale_info::TypeInfo; -use sp_core::{sr25519, ConstU64}; +use sp_core::sr25519; use sp_runtime::{ generic, traits::{BlakeTwo256, ValidateUnsigned, Verify}, @@ -351,7 +351,6 @@ impl frame_system::Config for Runtime { type PalletInfo = PalletInfo; type OnSetCode = (); type Block = Block; - type BlockHashCount = ConstU64<10>; } impl module1::Config for Runtime { diff --git a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs index 4c7012dca14979f0ed7f560bdc339146a676caa3..5b74cc172c6eb8ed057284ef9dd4c2f91fbf8d7c 100644 --- a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs +++ b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs @@ -27,7 +27,7 @@ use frame_support::{ }; use frame_system::limits::{BlockLength, BlockWeights}; use scale_info::TypeInfo; -use sp_core::{sr25519, ConstU64}; +use sp_core::sr25519; use sp_runtime::{ generic, traits::{BlakeTwo256, ValidateUnsigned, Verify}, @@ -351,7 +351,6 @@ impl frame_system::Config for Runtime { type PalletInfo = PalletInfo; type OnSetCode = (); type Block = Block; - type BlockHashCount = ConstU64<10>; } impl module1::Config for Runtime { diff --git a/substrate/frame/support/test/tests/runtime_metadata.rs b/substrate/frame/support/test/tests/runtime_metadata.rs index 819ec176d2b13c3fb5c90290339ef328a4c523ff..48e4d975eb083ec38baf6521cac1891b1e5e3d82 100644 --- a/substrate/frame/support/test/tests/runtime_metadata.rs +++ b/substrate/frame/support/test/tests/runtime_metadata.rs @@ -42,7 +42,6 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/support/test/tests/storage_layers.rs b/substrate/frame/support/test/tests/storage_layers.rs index caa125153e9dc597f8ca859e2e5dd6ac16618992..0e8ef668531816c736cf4edb6807b612fcfe85b5 100644 --- a/substrate/frame/support/test/tests/storage_layers.rs +++ b/substrate/frame/support/test/tests/storage_layers.rs @@ -78,7 +78,6 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; diff --git a/substrate/frame/support/test/tests/storage_transaction.rs b/substrate/frame/support/test/tests/storage_transaction.rs index a5bbfd24ab09a8084f58ad47e342174454133ef2..7f66a43b9afd735166847e2eb9c320a220458079 100644 --- a/substrate/frame/support/test/tests/storage_transaction.rs +++ b/substrate/frame/support/test/tests/storage_transaction.rs @@ -24,7 +24,7 @@ use frame_support::{ storage::{with_transaction, TransactionOutcome::*}, transactional, }; -use sp_core::{sr25519, ConstU32}; +use sp_core::sr25519; use sp_io::TestExternalities; use sp_runtime::{ generic, @@ -91,7 +91,6 @@ frame_support::construct_runtime!( impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/support/test/tests/versioned_migration.rs b/substrate/frame/support/test/tests/versioned_migration.rs index e7d146940cb92f31020e8b27fe014983f50396f0..c83dd6b71de9b3c72ee8c3f9b00cd81fecb0dfde 100644 --- a/substrate/frame/support/test/tests/versioned_migration.rs +++ b/substrate/frame/support/test/tests/versioned_migration.rs @@ -27,7 +27,6 @@ use frame_support::{ weights::constants::RocksDbWeight, }; use frame_system::Config; -use sp_core::ConstU64; use sp_runtime::BuildStorage; type Block = frame_system::mocking::MockBlock; @@ -75,7 +74,6 @@ construct_runtime!( impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; - type BlockHashCount = ConstU64<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/system/Cargo.toml b/substrate/frame/system/Cargo.toml index 16b3b946e22125e6d844020a4a94b788dc4aa270..a2a8970814b0a7c7c2c3f5ba9536371236c16bbd 100644 --- a/substrate/frame/system/Cargo.toml +++ b/substrate/frame/system/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] cfg-if = "1.0" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive", "serde"] } serde = { features = ["alloc", "derive"], workspace = true } @@ -31,7 +31,7 @@ sp-weights = { path = "../../primitives/weights", default-features = false, feat docify = "0.2.8" [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" sp-externalities = { path = "../../primitives/externalities" } substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } diff --git a/substrate/frame/system/benches/bench.rs b/substrate/frame/system/benches/bench.rs index 87c5581b2a3409f511f0a8f83a7c7aeae7e7b2c6..b3029630409f6afab1a6895e8ce918b931b6a80f 100644 --- a/substrate/frame/system/benches/bench.rs +++ b/substrate/frame/system/benches/bench.rs @@ -16,10 +16,7 @@ // limitations under the License. use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use frame_support::{ - derive_impl, - traits::{ConstU32, ConstU64}, -}; +use frame_support::{derive_impl, traits::ConstU32}; use sp_core::H256; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, @@ -75,7 +72,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/substrate/frame/system/benchmarking/Cargo.toml b/substrate/frame/system/benchmarking/Cargo.toml index 473a6bb132d741cf9485868201f114234be9f5d8..022f0ffce6b5ee23168db0ccaad1da5ea767ddf3 100644 --- a/substrate/frame/system/benchmarking/Cargo.toml +++ b/substrate/frame/system/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../../benchmarking", default-features = false } frame-support = { path = "../../support", default-features = false } diff --git a/substrate/frame/system/rpc/runtime-api/Cargo.toml b/substrate/frame/system/rpc/runtime-api/Cargo.toml index 70e66769a8b3de7c87e2350367ea4477d10d3776..b134cc3b617308265222d9dec6669dbbacf7f566 100644 --- a/substrate/frame/system/rpc/runtime-api/Cargo.toml +++ b/substrate/frame/system/rpc/runtime-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } sp-api = { path = "../../../../primitives/api", default-features = false } [features] diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index 7504a814aef13b0230e1067c0d95e0104ad74275..894ab72eb593b02324e5fabc37a4035efecaac5e 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -142,7 +142,7 @@ mod tests { crate::Account::::insert( 1, crate::AccountInfo { - nonce: 1, + nonce: 1u64.into(), consumers: 0, providers: 1, sufficients: 0, @@ -153,20 +153,20 @@ mod tests { let len = 0_usize; // stale assert_noop!( - CheckNonce::(0).validate(&1, CALL, &info, len), + CheckNonce::(0u64.into()).validate(&1, CALL, &info, len), InvalidTransaction::Stale ); assert_noop!( - CheckNonce::(0).pre_dispatch(&1, CALL, &info, len), + CheckNonce::(0u64.into()).pre_dispatch(&1, CALL, &info, len), InvalidTransaction::Stale ); // correct - assert_ok!(CheckNonce::(1).validate(&1, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&1, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).validate(&1, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).pre_dispatch(&1, CALL, &info, len)); // future - assert_ok!(CheckNonce::(5).validate(&1, CALL, &info, len)); + assert_ok!(CheckNonce::(5u64.into()).validate(&1, CALL, &info, len)); assert_noop!( - CheckNonce::(5).pre_dispatch(&1, CALL, &info, len), + CheckNonce::(5u64.into()).pre_dispatch(&1, CALL, &info, len), InvalidTransaction::Future ); }) @@ -178,7 +178,7 @@ mod tests { crate::Account::::insert( 2, crate::AccountInfo { - nonce: 1, + nonce: 1u64.into(), consumers: 0, providers: 1, sufficients: 0, @@ -188,7 +188,7 @@ mod tests { crate::Account::::insert( 3, crate::AccountInfo { - nonce: 1, + nonce: 1u64.into(), consumers: 0, providers: 0, sufficients: 1, @@ -199,19 +199,19 @@ mod tests { let len = 0_usize; // Both providers and sufficients zero assert_noop!( - CheckNonce::(1).validate(&1, CALL, &info, len), + CheckNonce::(1u64.into()).validate(&1, CALL, &info, len), InvalidTransaction::Payment ); assert_noop!( - CheckNonce::(1).pre_dispatch(&1, CALL, &info, len), + CheckNonce::(1u64.into()).pre_dispatch(&1, CALL, &info, len), InvalidTransaction::Payment ); // Non-zero providers - assert_ok!(CheckNonce::(1).validate(&2, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&2, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).validate(&2, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).pre_dispatch(&2, CALL, &info, len)); // Non-zero sufficients - assert_ok!(CheckNonce::(1).validate(&3, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&3, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).validate(&3, CALL, &info, len)); + assert_ok!(CheckNonce::(1u64.into()).pre_dispatch(&3, CALL, &info, len)); }) } } diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs index 70d1e75633278c665f4c06ca22f02a96668ef964..5d6c68989ed53bfec6d95f80f5c9b149aa4c3063 100644 --- a/substrate/frame/system/src/extensions/check_weight.rs +++ b/substrate/frame/system/src/extensions/check_weight.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{limits::BlockWeights, Config, Pallet, LOG_TARGET}; +use crate::{limits::BlockWeights, Config, DispatchClass, Pallet, LOG_TARGET}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, PostDispatchInfo}, @@ -64,17 +64,6 @@ where } } - /// Checks if the current extrinsic can fit into the block with respect to block weight limits. - /// - /// Upon successes, it returns the new block weight as a `Result`. - fn check_block_weight( - info: &DispatchInfoOf, - ) -> Result { - let maximum_weight = T::BlockWeights::get(); - let all_weight = Pallet::::block_weight(); - calculate_consumed_weight::(maximum_weight, all_weight, info) - } - /// 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`. @@ -113,7 +102,12 @@ where len: usize, ) -> Result<(), TransactionValidityError> { let next_len = Self::check_block_length(info, len)?; - let next_weight = Self::check_block_weight(info)?; + + let all_weight = Pallet::::block_weight(); + let maximum_weight = T::BlockWeights::get(); + let next_weight = + calculate_consumed_weight::(&maximum_weight, all_weight, info)?; + check_combined_proof_size::(info, &maximum_weight, next_len, &next_weight)?; Self::check_extrinsic_weight(info)?; crate::AllExtrinsicsLen::::put(next_len); @@ -136,8 +130,41 @@ where } } +/// Check that the combined extrinsic length and proof size together do not exceed the PoV limit. +pub fn check_combined_proof_size( + info: &DispatchInfoOf, + maximum_weight: &BlockWeights, + next_len: u32, + next_weight: &crate::ConsumedWeight, +) -> Result<(), TransactionValidityError> +where + Call: Dispatchable, +{ + // This extra check ensures that the extrinsic length does not push the + // PoV over the limit. + let total_pov_size = next_weight.total().proof_size().saturating_add(next_len as u64); + if total_pov_size > maximum_weight.max_block.proof_size() { + log::debug!( + target: LOG_TARGET, + "Extrinsic exceeds total pov size. Still including if mandatory. size: {}kb, limit: {}kb, is_mandatory: {}", + total_pov_size as f64/1024.0, + maximum_weight.max_block.proof_size() as f64/1024.0, + info.class == DispatchClass::Mandatory + ); + return match info.class { + // Allow mandatory extrinsics + DispatchClass::Mandatory => Ok(()), + _ => Err(InvalidTransaction::ExhaustsResources.into()), + }; + } + Ok(()) +} + +/// Checks if the current extrinsic can fit into the block with respect to block weight limits. +/// +/// Upon successes, it returns the new block weight as a `Result`. pub fn calculate_consumed_weight( - maximum_weight: BlockWeights, + maximum_weight: &BlockWeights, mut all_weight: crate::ConsumedWeight, info: &DispatchInfoOf, ) -> Result @@ -172,7 +199,7 @@ where "Exceeded the per-class allowance.", ); - return Err(InvalidTransaction::ExhaustsResources.into()) + return Err(InvalidTransaction::ExhaustsResources.into()); }, // There is no `max_total` limit (`None`), // or we are below the limit. @@ -190,7 +217,7 @@ where "Total block weight is exceeded.", ); - return Err(InvalidTransaction::ExhaustsResources.into()) + return Err(InvalidTransaction::ExhaustsResources.into()); }, // There is either no limit in reserved pool (`None`), // or we are below the limit. @@ -742,17 +769,171 @@ mod tests { // when assert_ok!(calculate_consumed_weight::<::RuntimeCall>( - maximum_weight.clone(), + &maximum_weight, all_weight.clone(), - &mandatory1 + &mandatory1, )); assert_err!( calculate_consumed_weight::<::RuntimeCall>( - maximum_weight, + &maximum_weight, all_weight, - &mandatory2 + &mandatory2, + ), + InvalidTransaction::ExhaustsResources + ); + } + + #[test] + fn maximum_proof_size_includes_length() { + let maximum_weight = BlockWeights::builder() + .base_block(Weight::zero()) + .for_class(DispatchClass::non_mandatory(), |w| { + w.base_extrinsic = Weight::zero(); + w.max_total = Some(Weight::from_parts(20, 10)); + }) + .for_class(DispatchClass::Mandatory, |w| { + w.base_extrinsic = Weight::zero(); + w.reserved = Some(Weight::from_parts(5, 10)); + w.max_total = None; + }) + .build_or_panic(); + + assert_eq!(maximum_weight.max_block, Weight::from_parts(20, 10)); + + let info = DispatchInfo { class: DispatchClass::Normal, ..Default::default() }; + let mandatory = DispatchInfo { class: DispatchClass::Mandatory, ..Default::default() }; + // We have 10 reftime and 5 proof size left over. + let next_weight = crate::ConsumedWeight::new(|class| match class { + DispatchClass::Normal => Weight::from_parts(10, 5), + DispatchClass::Operational => Weight::from_parts(0, 0), + DispatchClass::Mandatory => Weight::zero(), + }); + + // Simple checks for the length + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 0, + &next_weight + )); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 5, + &next_weight + )); + assert_err!( + check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 6, + &next_weight + ), + InvalidTransaction::ExhaustsResources + ); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &mandatory, + &maximum_weight, + 6, + &next_weight + )); + + // We have 10 reftime and 0 proof size left over. + let next_weight = crate::ConsumedWeight::new(|class| match class { + DispatchClass::Normal => Weight::from_parts(10, 10), + DispatchClass::Operational => Weight::from_parts(0, 0), + DispatchClass::Mandatory => Weight::zero(), + }); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 0, + &next_weight + )); + assert_err!( + check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 1, + &next_weight ), InvalidTransaction::ExhaustsResources ); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &mandatory, + &maximum_weight, + 1, + &next_weight + )); + + // We have 10 reftime and 2 proof size left over. + // Used weight is spread across dispatch classes this time. + let next_weight = crate::ConsumedWeight::new(|class| match class { + DispatchClass::Normal => Weight::from_parts(10, 5), + DispatchClass::Operational => Weight::from_parts(0, 3), + DispatchClass::Mandatory => Weight::zero(), + }); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 0, + &next_weight + )); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 2, + &next_weight + )); + assert_err!( + check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 3, + &next_weight + ), + InvalidTransaction::ExhaustsResources + ); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &mandatory, + &maximum_weight, + 3, + &next_weight + )); + + // Ref time is over the limit. Should not happen, but we should make sure that it is + // ignored. + let next_weight = crate::ConsumedWeight::new(|class| match class { + DispatchClass::Normal => Weight::from_parts(30, 5), + DispatchClass::Operational => Weight::from_parts(0, 0), + DispatchClass::Mandatory => Weight::zero(), + }); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 0, + &next_weight + )); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 5, + &next_weight + )); + assert_err!( + check_combined_proof_size::<::RuntimeCall>( + &info, + &maximum_weight, + 6, + &next_weight + ), + InvalidTransaction::ExhaustsResources + ); + assert_ok!(check_combined_proof_size::<::RuntimeCall>( + &mandatory, + &maximum_weight, + 6, + &next_weight + )); } } diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 30df4dcfd43e9058cb3acc1a8f9b1863bf925e11..84d00a1e917ec033d4fe534f932236db76569625 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -262,7 +262,19 @@ pub mod pallet { /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`]. pub mod config_preludes { use super::{inject_runtime_type, DefaultConfig}; - use frame_support::derive_impl; + use frame_support::{derive_impl, traits::Get}; + + /// A predefined adapter that covers `BlockNumberFor` for `Config::Block::BlockNumber` of + /// the types `u32`, `u64`, and `u128`. + /// + /// NOTE: Avoids overriding `BlockHashCount` when using `mocking::{MockBlock, MockBlockU32, + /// MockBlockU128}`. + pub struct TestBlockHashCount>(sp_std::marker::PhantomData); + impl, C: Get> Get for TestBlockHashCount { + fn get() -> I { + C::get().into() + } + } /// Provides a viable default config that can be used with /// [`derive_impl`](`frame_support::derive_impl`) to derive a testing pallet config @@ -300,7 +312,7 @@ pub mod pallet { #[inject_runtime_type] type RuntimeTask = (); type BaseCallFilter = frame_support::traits::Everything; - type BlockHashCount = frame_support::traits::ConstU64<10>; + type BlockHashCount = TestBlockHashCount>; type OnSetCode = (); type SingleBlockMigrations = (); type MultiBlockMigrator = (); @@ -397,7 +409,7 @@ pub mod pallet { /// Maximum number of block number to block hash mappings to keep (oldest pruned first). /// Using 256 as default. - type BlockHashCount = frame_support::traits::ConstU32<256>; + type BlockHashCount = TestBlockHashCount>; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); @@ -1780,7 +1792,7 @@ impl Pallet { "[{:?}] {} extrinsics, length: {} (normal {}%, op: {}%, mandatory {}%) / normal weight:\ {} ({}%) op weight {} ({}%) / mandatory weight {} ({}%)", Self::block_number(), - Self::extrinsic_index().unwrap_or_default(), + Self::extrinsic_count(), Self::all_extrinsics_len(), sp_runtime::Percent::from_rational( Self::all_extrinsics_len(), diff --git a/substrate/frame/system/src/mock.rs b/substrate/frame/system/src/mock.rs index e1959e572e99cae45dcdf4960139298defbf81b2..fff848b3b0e50bde09527856f76c6ae3c84f6ea7 100644 --- a/substrate/frame/system/src/mock.rs +++ b/substrate/frame/system/src/mock.rs @@ -17,7 +17,7 @@ use crate::{self as frame_system, *}; use frame_support::{derive_impl, parameter_types}; -use sp_runtime::{BuildStorage, Perbill}; +use sp_runtime::{type_with_default::TypeWithDefault, BuildStorage, Perbill}; type Block = mocking::MockBlock; @@ -78,6 +78,14 @@ impl OnKilledAccount for RecordKilled { } } +#[derive(Debug, TypeInfo)] +pub struct DefaultNonceProvider; +impl Get for DefaultNonceProvider { + fn get() -> u64 { + System::block_number() + } +} + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl Config for Test { type BlockWeights = RuntimeBlockWeights; @@ -87,6 +95,7 @@ impl Config for Test { type AccountData = u32; type OnKilledAccount = RecordKilled; type MultiBlockMigrator = MockedMigrator; + type Nonce = TypeWithDefault; } parameter_types! { diff --git a/substrate/frame/system/src/tests.rs b/substrate/frame/system/src/tests.rs index b889b5ca046efe557e7706870c11febce8a358b2..b2cd017e1e206d9bf0f486bc964a4514789dcadc 100644 --- a/substrate/frame/system/src/tests.rs +++ b/substrate/frame/system/src/tests.rs @@ -21,14 +21,14 @@ use frame_support::{ dispatch::{Pays, PostDispatchInfo, WithPostDispatchInfo}, traits::{OnRuntimeUpgrade, WhitelistedStorageKeys}, }; -use std::collections::BTreeSet; - use mock::{RuntimeOrigin, *}; use sp_core::{hexdisplay::HexDisplay, H256}; use sp_runtime::{ traits::{BlakeTwo256, Header}, DispatchError, DispatchErrorWithPostInfo, }; +use std::collections::BTreeSet; +use substrate_test_runtime_client::WasmExecutor; #[test] fn check_whitelist() { @@ -102,7 +102,13 @@ fn stored_map_works() { assert_eq!( Account::::get(0), - AccountInfo { nonce: 0, providers: 1, consumers: 0, sufficients: 0, data: 42 } + AccountInfo { + nonce: 0u64.into(), + providers: 1, + consumers: 0, + sufficients: 0, + data: 42 + } ); assert_ok!(System::inc_consumers(&0)); @@ -126,26 +132,26 @@ fn provider_ref_handover_to_self_sufficient_ref_works() { new_test_ext().execute_with(|| { assert_eq!(System::inc_providers(&0), IncRefStatus::Created); System::inc_account_nonce(&0); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // a second reference coming and going doesn't change anything. assert_eq!(System::inc_sufficients(&0), IncRefStatus::Existed); assert_eq!(System::dec_sufficients(&0), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // a provider reference coming and going doesn't change anything. assert_eq!(System::inc_providers(&0), IncRefStatus::Existed); assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // decreasing the providers with a self-sufficient present should not delete the account assert_eq!(System::inc_sufficients(&0), IncRefStatus::Existed); assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // decreasing the sufficients should delete the account assert_eq!(System::dec_sufficients(&0), DecRefStatus::Reaped); - assert_eq!(System::account_nonce(&0), 0); + assert_eq!(System::account_nonce(&0), 0u64.into()); }); } @@ -154,26 +160,26 @@ fn self_sufficient_ref_handover_to_provider_ref_works() { new_test_ext().execute_with(|| { assert_eq!(System::inc_sufficients(&0), IncRefStatus::Created); System::inc_account_nonce(&0); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // a second reference coming and going doesn't change anything. assert_eq!(System::inc_providers(&0), IncRefStatus::Existed); assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // a sufficient reference coming and going doesn't change anything. assert_eq!(System::inc_sufficients(&0), IncRefStatus::Existed); assert_eq!(System::dec_sufficients(&0), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // decreasing the sufficients with a provider present should not delete the account assert_eq!(System::inc_providers(&0), IncRefStatus::Existed); assert_eq!(System::dec_sufficients(&0), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); // decreasing the providers should delete the account assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Reaped); - assert_eq!(System::account_nonce(&0), 0); + assert_eq!(System::account_nonce(&0), 0u64.into()); }); } @@ -182,7 +188,7 @@ fn sufficient_cannot_support_consumer() { new_test_ext().execute_with(|| { assert_eq!(System::inc_sufficients(&0), IncRefStatus::Created); System::inc_account_nonce(&0); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); assert_noop!(System::inc_consumers(&0), DispatchError::NoProviders); assert_eq!(System::inc_providers(&0), IncRefStatus::Existed); @@ -198,18 +204,18 @@ fn provider_required_to_support_consumer() { assert_eq!(System::inc_providers(&0), IncRefStatus::Created); System::inc_account_nonce(&0); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); assert_eq!(System::inc_providers(&0), IncRefStatus::Existed); assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Exists); - assert_eq!(System::account_nonce(&0), 1); + assert_eq!(System::account_nonce(&0), 1u64.into()); assert_ok!(System::inc_consumers(&0)); assert_noop!(System::dec_providers(&0), DispatchError::ConsumerRemaining); System::dec_consumers(&0); assert_eq!(System::dec_providers(&0).unwrap(), DecRefStatus::Reaped); - assert_eq!(System::account_nonce(&0), 0); + assert_eq!(System::account_nonce(&0), 0u64.into()); }); } @@ -653,7 +659,7 @@ fn assert_runtime_updated_digest(num: usize) { #[test] fn set_code_with_real_wasm_blob() { - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = WasmExecutor::default(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(executor)); ext.execute_with(|| { @@ -679,7 +685,7 @@ fn set_code_with_real_wasm_blob() { fn set_code_rejects_during_mbm() { Ongoing::set(true); - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = substrate_test_runtime_client::WasmExecutor::default(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(executor)); ext.execute_with(|| { @@ -699,7 +705,7 @@ fn set_code_rejects_during_mbm() { #[test] fn set_code_via_authorization_works() { - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = substrate_test_runtime_client::WasmExecutor::default(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(executor)); ext.execute_with(|| { @@ -739,7 +745,7 @@ fn set_code_via_authorization_works() { #[test] fn runtime_upgraded_with_set_storage() { - let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let executor = substrate_test_runtime_client::WasmExecutor::default(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(executor)); ext.execute_with(|| { @@ -858,3 +864,20 @@ fn last_runtime_upgrade_spec_version_usage() { } } } + +#[test] +fn test_default_account_nonce() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + assert_eq!(System::account_nonce(&1), 2u64.into()); + + System::inc_account_nonce(&1); + assert_eq!(System::account_nonce(&1), 3u64.into()); + + System::set_block_number(5); + assert_eq!(System::account_nonce(&1), 3u64.into()); + + Account::::remove(&1); + assert_eq!(System::account_nonce(&1), 5u64.into()); + }); +} diff --git a/substrate/frame/timestamp/Cargo.toml b/substrate/frame/timestamp/Cargo.toml index da49b29c89b78f26b3f5eee35e81b7d2dacf8bb8..93ce09611b55dc49746ad5e99fa98b21cf25ea6d 100644 --- a/substrate/frame/timestamp/Cargo.toml +++ b/substrate/frame/timestamp/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/tips/Cargo.toml b/substrate/frame/tips/Cargo.toml index a2acf0638ffb0717ece5c132009b983c86ef2072..bcd54461406ead0f1bd67ab427c023d91b63fa0e 100644 --- a/substrate/frame/tips/Cargo.toml +++ b/substrate/frame/tips/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["derive"], optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/transaction-payment/Cargo.toml b/substrate/frame/transaction-payment/Cargo.toml index 24e5a714f0fe3aee0a5c2d74d3d837e8b969cdb1..4f7da9ae46fabe7b4dcb92bd40eab2ea339175a8 100644 --- a/substrate/frame/transaction-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml index fef9afdee05f37cbd2999b1bbfecb07f2601d3bd..177621d9adbd102369fe0466cf962441f7591e42 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml @@ -23,7 +23,7 @@ frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } pallet-asset-conversion = { path = "../../asset-conversion", default-features = false } pallet-transaction-payment = { path = "..", default-features = false } -codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } [dev-dependencies] diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index 9a2b22b817096916193db338df62269415ec7a52..0cafb35d52e1c85e3a24a72869319da712298500 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -100,7 +100,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml index fc4f1aecc15ee910ef90ffd18b39173d5de096e9..a4a8efad869c84ef9fe8b905ae5c38a9ed94b614 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -28,7 +28,7 @@ pallet-transaction-payment = { path = "..", default-features = false } frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true } # Other dependencies -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index b04d4ffd9e0b794f56fd7be0219f8150f45e7078..f27fcd53fecd2d9006314c18155d9b4ac89d7eca 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -86,7 +86,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/transaction-payment/rpc/Cargo.toml b/substrate/frame/transaction-payment/rpc/Cargo.toml index 6d7f632af82813050d4c0523dcd61dc27ea512f1..2c9f814460f7cd1502779cc1645c0379611dc3d5 100644 --- a/substrate/frame/transaction-payment/rpc/Cargo.toml +++ b/substrate/frame/transaction-payment/rpc/Cargo.toml @@ -16,8 +16,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +codec = { package = "parity-scale-codec", version = "3.6.12" } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } pallet-transaction-payment-rpc-runtime-api = { path = "runtime-api" } sp-api = { path = "../../../primitives/api" } sp-blockchain = { path = "../../../primitives/blockchain" } diff --git a/substrate/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/substrate/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 913dccc05c496807a7698dd3445eaaba5431002a..6c0241ec5c03c4ceb757620d6ae4f528e379c74e 100644 --- a/substrate/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/substrate/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } pallet-transaction-payment = { path = "../..", default-features = false } sp-api = { path = "../../../../primitives/api", default-features = false } sp-runtime = { path = "../../../../primitives/runtime", default-features = false } diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/Cargo.toml b/substrate/frame/transaction-payment/skip-feeless-payment/Cargo.toml index 8a6ee09f8dd0a4d17566ef573f242e9762cf6b1e..4d32a5123cf3fc0ef1322cedca7d2c8ef65ba51a 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/skip-feeless-payment/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } # Other dependencies -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } [features] diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index c1bb05ab5c7eb8e03c49e5f8d789276de296bba9..1ef95128f2a840a2349728d5576560067b45bb34 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -85,7 +85,6 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/transaction-storage/Cargo.toml b/substrate/frame/transaction-storage/Cargo.toml index 31741cf32d83edfeaa10d06060c79df07f2b50c9..bf647ca13ec1cf355e35bc9307239979ba8c8460 100644 --- a/substrate/frame/transaction-storage/Cargo.toml +++ b/substrate/frame/transaction-storage/Cargo.toml @@ -16,8 +16,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = { version = "6.1", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +array-bytes = { version = "6.2.2", optional = true } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/transaction-storage/src/mock.rs b/substrate/frame/transaction-storage/src/mock.rs index f1e9e0591f6f521bad4fda1cb4ae4aa879efc483..73174b73dbacc7c803ad947c3108165688832767 100644 --- a/substrate/frame/transaction-storage/src/mock.rs +++ b/substrate/frame/transaction-storage/src/mock.rs @@ -23,7 +23,7 @@ use crate::{ }; use frame_support::{ derive_impl, - traits::{ConstU32, ConstU64, OnFinalize, OnInitialize}, + traits::{ConstU32, OnFinalize, OnInitialize}, }; use sp_runtime::{traits::IdentityLookup, BuildStorage}; @@ -44,7 +44,6 @@ impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; type AccountId = u64; - type BlockHashCount = ConstU64<250>; type Lookup = IdentityLookup; } diff --git a/substrate/frame/treasury/Cargo.toml b/substrate/frame/treasury/Cargo.toml index 34037338a52bac4d18130e6a3c88b3c3a5d3dc60..c93272af11d4664495cac40984f99fbc60b23f11 100644 --- a/substrate/frame/treasury/Cargo.toml +++ b/substrate/frame/treasury/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } diff --git a/substrate/frame/try-runtime/Cargo.toml b/substrate/frame/try-runtime/Cargo.toml index 15c8ca5d27a71f9d4172d5d8bd31808d7badcc3b..e4e5f1940b25b67a97ef6026daa13a83cab791a4 100644 --- a/substrate/frame/try-runtime/Cargo.toml +++ b/substrate/frame/try-runtime/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } frame-support = { path = "../support", default-features = false } sp-api = { path = "../../primitives/api", default-features = false } sp-runtime = { path = "../../primitives/runtime", default-features = false } diff --git a/substrate/frame/tx-pause/Cargo.toml b/substrate/frame/tx-pause/Cargo.toml index 5f028179037d1214aadb460fa464b79f55c05a23..e44bb90dd7f8438673f7b5a23b1e7b1c15da03b5 100644 --- a/substrate/frame/tx-pause/Cargo.toml +++ b/substrate/frame/tx-pause/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } docify = "0.2.8" frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/tx-pause/src/mock.rs b/substrate/frame/tx-pause/src/mock.rs index 5206023838b95290d1a153b37074dccb0b5635d9..7245fe7d5d72a68b1ff00078ea11a755f206744e 100644 --- a/substrate/frame/tx-pause/src/mock.rs +++ b/substrate/frame/tx-pause/src/mock.rs @@ -33,9 +33,6 @@ use sp_runtime::{ BuildStorage, }; -parameter_types! { - pub const BlockHashCount: u64 = 250; -} #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = InsideBoth; @@ -50,7 +47,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; type Block = Block; - type BlockHashCount = BlockHashCount; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; diff --git a/substrate/frame/uniques/Cargo.toml b/substrate/frame/uniques/Cargo.toml index ee6af191d33f31142a109ad7b11b6d2ff1104759..65b727b40b254567d46bff7704b4f124b78820f0 100644 --- a/substrate/frame/uniques/Cargo.toml +++ b/substrate/frame/uniques/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } diff --git a/substrate/frame/utility/Cargo.toml b/substrate/frame/utility/Cargo.toml index 2ad575ed51ffe708b9369a81ea0a4aa5d50e600b..00e8be75a3de600eada40f33afd4af94156dd554 100644 --- a/substrate/frame/utility/Cargo.toml +++ b/substrate/frame/utility/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/frame/vesting/Cargo.toml b/substrate/frame/vesting/Cargo.toml index e71731e397788a956bd72a74e93b9ac10d0fd7a6..7372b84240364aff99bf4ecbe35929b219f8b50e 100644 --- a/substrate/frame/vesting/Cargo.toml +++ b/substrate/frame/vesting/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } log = { workspace = true } diff --git a/substrate/frame/whitelist/Cargo.toml b/substrate/frame/whitelist/Cargo.toml index 5c28fe29142c786621eee8fc4355983e990a8981..61bbb278019de8b4c012c460ab4d836cdf8a556d 100644 --- a/substrate/frame/whitelist/Cargo.toml +++ b/substrate/frame/whitelist/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } diff --git a/substrate/primitives/api/Cargo.toml b/substrate/primitives/api/Cargo.toml index 2f553819b1bc09b911ad3664aa555c661863a40b..f48480f398d00729a5fb10e0c9bcfba5d62f9776 100644 --- a/substrate/primitives/api/Cargo.toml +++ b/substrate/primitives/api/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } sp-api-proc-macro = { path = "proc-macro", default-features = false } sp-core = { path = "../core", default-features = false } sp-std = { path = "../std", default-features = false } diff --git a/substrate/primitives/api/proc-macro/src/utils.rs b/substrate/primitives/api/proc-macro/src/utils.rs index d90b56058648ba8653992c210586238028629689..36577670a40ce48df9ea805adb2fde5f02399599 100644 --- a/substrate/primitives/api/proc-macro/src/utils.rs +++ b/substrate/primitives/api/proc-macro/src/utils.rs @@ -40,6 +40,10 @@ pub fn generate_crate_access() -> TokenStream { let path = format!("{}::deps::sp_api::__private", name); let path = syn::parse_str::(&path).expect("is a valid path; qed"); quote!( #path ) + } else if let Ok(FoundCrate::Name(name)) = crate_name(&"polkadot-sdk") { + let path = format!("{}::sp_api::__private", name); + let path = syn::parse_str::(&path).expect("is a valid path; qed"); + quote!( #path ) } else { let err = Error::new(Span::call_site(), e).to_compile_error(); quote!( #err ) diff --git a/substrate/primitives/api/test/Cargo.toml b/substrate/primitives/api/test/Cargo.toml index 52a4bd7bda30b30978e15fa1277621fcdff14f59..b49f774161fd3f593872452a54e4f186a6743f6c 100644 --- a/substrate/primitives/api/test/Cargo.toml +++ b/substrate/primitives/api/test/Cargo.toml @@ -22,14 +22,14 @@ sp-tracing = { path = "../../tracing" } sp-runtime = { path = "../../runtime" } sp-consensus = { path = "../../consensus/common" } sc-block-builder = { path = "../../../client/block-builder" } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } sp-state-machine = { path = "../../state-machine" } trybuild = "1.0.88" rustversion = "1.0.6" scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" futures = "0.3.30" log = { workspace = true, default-features = true } sp-core = { path = "../../core" } diff --git a/substrate/primitives/api/test/tests/runtime_calls.rs b/substrate/primitives/api/test/tests/runtime_calls.rs index e66be7f9bf1a4b8ecb6619fe74035278e54ba7dc..5a524d1c7f4d3c6e31b2fee19e2af57e1c6365f8 100644 --- a/substrate/primitives/api/test/tests/runtime_calls.rs +++ b/substrate/primitives/api/test/tests/runtime_calls.rs @@ -122,9 +122,7 @@ fn record_proof_works() { // Use the proof backend to execute `execute_block`. let mut overlay = Default::default(); - let executor = NativeElseWasmExecutor::::new_with_wasm_executor( - WasmExecutor::builder().build(), - ); + let executor: WasmExecutor = WasmExecutor::builder().build(); execution_proof_check_on_trie_backend( &backend, &mut overlay, diff --git a/substrate/primitives/application-crypto/Cargo.toml b/substrate/primitives/application-crypto/Cargo.toml index 20e2be4d1552f4874dad7e0902ccd9c00a660976..cbb9f2133577b93234c052dba329ed1d5f453be7 100644 --- a/substrate/primitives/application-crypto/Cargo.toml +++ b/substrate/primitives/application-crypto/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { path = "../core", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["alloc", "derive"], workspace = true } sp-std = { path = "../std", default-features = false } diff --git a/substrate/primitives/arithmetic/Cargo.toml b/substrate/primitives/arithmetic/Cargo.toml index 16eae43c73fa60da63dd249f7934c70e805dd8f2..a9f2b80156f5ec121eea75abb389e02bbf99884e 100644 --- a/substrate/primitives/arithmetic/Cargo.toml +++ b/substrate/primitives/arithmetic/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", "max-encoded-len", ] } @@ -30,7 +30,7 @@ sp-std = { path = "../std", default-features = false } docify = "0.2.8" [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" primitive-types = "0.12.0" sp-crypto-hashing = { path = "../crypto/hashing" } rand = "0.8.5" diff --git a/substrate/primitives/authority-discovery/Cargo.toml b/substrate/primitives/authority-discovery/Cargo.toml index 88d93f40059625dd271b734c23fd635113dcbac9..72a8bb7fc47d0f76a49de45a3828424eb7a0a240 100644 --- a/substrate/primitives/authority-discovery/Cargo.toml +++ b/substrate/primitives/authority-discovery/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-api = { path = "../api", default-features = false } sp-application-crypto = { path = "../application-crypto", default-features = false } diff --git a/substrate/primitives/blockchain/Cargo.toml b/substrate/primitives/blockchain/Cargo.toml index e716b61bfeb1668a42434aed147fa0810a1b7dca..5e51a2d06ed7a8f1de6fda7b2b19bf49fa515e51 100644 --- a/substrate/primitives/blockchain/Cargo.toml +++ b/substrate/primitives/blockchain/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } futures = "0.3.30" log = { workspace = true, default-features = true } parking_lot = "0.12.1" diff --git a/substrate/primitives/blockchain/src/backend.rs b/substrate/primitives/blockchain/src/backend.rs index 7a09865f858d3faa4ec1ee1fd5a2beb84e9267d7..06e5b682964a4e7672575c9e8b5460d7acb2de96 100644 --- a/substrate/primitives/blockchain/src/backend.rs +++ b/substrate/primitives/blockchain/src/backend.rs @@ -21,14 +21,17 @@ use log::warn; use parking_lot::RwLock; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, Header as HeaderT, NumberFor, Saturating}, + traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}, Justifications, }; -use std::collections::btree_set::BTreeSet; +use std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use crate::header_metadata::HeaderMetadata; -use crate::error::{Error, Result}; +use crate::{ + error::{Error, Result}, + tree_route, TreeRoute, +}; /// Blockchain database header backend. Does not perform any validation. pub trait HeaderBackend: Send + Sync { @@ -89,62 +92,32 @@ pub trait HeaderBackend: Send + Sync { pub trait ForkBackend: HeaderMetadata + HeaderBackend + Send + Sync { - /// Best effort to get all the header hashes that are part of the provided forks - /// starting only from the fork heads. + /// Returns block hashes for provided fork heads. It skips the fork if when blocks are missing + /// (e.g. warp-sync) and internal `tree_route` function fails. /// - /// The function tries to reconstruct the route from the fork head to the canonical chain. - /// If any of the hashes on the route can't be found in the db, the function won't be able - /// to reconstruct the route anymore. In this case it will give up expanding the current fork, - /// move on to the next ones and at the end it will return an error that also contains - /// the partially expanded forks. + /// Example: + /// G --- A1 --- A2 --- A3 --- A4 ( < fork1 ) + /// \-----C4 --- C5 ( < fork2 ) + /// We finalize A3 and call expand_fork(C5). Result = (C5,C4). fn expand_forks( &self, fork_heads: &[Block::Hash], - ) -> std::result::Result, (BTreeSet, Error)> { - let mut missing_blocks = vec![]; + ) -> std::result::Result, Error> { let mut expanded_forks = BTreeSet::new(); for fork_head in fork_heads { - let mut route_head = *fork_head; - // Insert stale blocks hashes until canonical chain is reached. - // If we reach a block that is already part of the `expanded_forks` we can stop - // processing the fork. - while expanded_forks.insert(route_head) { - match self.header_metadata(route_head) { - Ok(meta) => { - // If the parent is part of the canonical chain or there doesn't exist a - // block hash for the parent number (bug?!), we can abort adding blocks. - let parent_number = meta.number.saturating_sub(1u32.into()); - match self.hash(parent_number) { - Ok(Some(parent_hash)) => - if parent_hash == meta.parent { - break - }, - Ok(None) | Err(_) => { - missing_blocks.push(BlockId::::Number(parent_number)); - break - }, - } - - route_head = meta.parent; - }, - Err(_e) => { - missing_blocks.push(BlockId::::Hash(route_head)); - break - }, - } + match tree_route(self, *fork_head, self.info().finalized_hash) { + Ok(tree_route) => { + for block in tree_route.retracted() { + expanded_forks.insert(block.hash); + } + continue + }, + Err(_) => { + // There are cases when blocks are missing (e.g. warp-sync). + }, } } - if !missing_blocks.is_empty() { - return Err(( - expanded_forks, - Error::UnknownBlocks(format!( - "Missing stale headers {:?} while expanding forks {:?}.", - fork_heads, missing_blocks - )), - )) - } - Ok(expanded_forks) } } @@ -172,14 +145,6 @@ pub trait Backend: /// Results must be ordered best (longest, highest) chain first. fn leaves(&self) -> Result>; - /// Returns displaced leaves after the given block would be finalized. - /// - /// The returned leaves do not contain the leaves from the same height as `block_number`. - fn displaced_leaves_after_finalizing( - &self, - block_number: NumberFor, - ) -> Result>; - /// Return hashes of all blocks that are children of the block with `parent_hash`. fn children(&self, parent_hash: Block::Hash) -> Result>; @@ -255,6 +220,67 @@ pub trait Backend: } fn block_indexed_body(&self, hash: Block::Hash) -> Result>>>; + + /// Returns all leaves that will be displaced after the block finalization. + fn displaced_leaves_after_finalizing( + &self, + finalized_block_hash: Block::Hash, + finalized_block_number: NumberFor, + ) -> std::result::Result, Error> { + let mut result = DisplacedLeavesAfterFinalization::default(); + + if finalized_block_number == Zero::zero() { + return Ok(result) + } + + // For each leaf determine whether it belongs to a non-canonical branch. + for leaf_hash in self.leaves()? { + let leaf_block_header = self.expect_header(leaf_hash)?; + let leaf_number = *leaf_block_header.number(); + + let leaf_tree_route = match tree_route(self, leaf_hash, finalized_block_hash) { + Ok(tree_route) => tree_route, + Err(Error::UnknownBlock(_)) => { + // Sometimes routes can't be calculated. E.g. after warp sync. + continue; + }, + Err(e) => Err(e)?, + }; + + // Is it a stale fork? + let needs_pruning = leaf_tree_route.common_block().hash != finalized_block_hash; + + if needs_pruning { + result.displaced_leaves.insert(leaf_hash, leaf_number); + result.tree_routes.insert(leaf_hash, leaf_tree_route); + } + } + + Ok(result) + } +} + +/// Result of [`Backend::displaced_leaves_after_finalizing`]. +#[derive(Clone, Debug)] +pub struct DisplacedLeavesAfterFinalization { + /// A collection of hashes and block numbers for displaced leaves. + pub displaced_leaves: BTreeMap>, + + /// A collection of tree routes from the leaves to finalized block. + pub tree_routes: BTreeMap>, +} + +impl Default for DisplacedLeavesAfterFinalization { + fn default() -> Self { + Self { displaced_leaves: Default::default(), tree_routes: Default::default() } + } +} + +impl DisplacedLeavesAfterFinalization { + /// Returns a collection of hashes for the displaced leaves. + pub fn hashes(&self) -> impl Iterator + '_ { + self.displaced_leaves.keys().cloned() + } } /// Blockchain info diff --git a/substrate/primitives/blockchain/src/header_metadata.rs b/substrate/primitives/blockchain/src/header_metadata.rs index ccd640c0567afc6c9f9341fca754471a15a2829c..27caaae71add1a440b8a772db131329c951befbc 100644 --- a/substrate/primitives/blockchain/src/header_metadata.rs +++ b/substrate/primitives/blockchain/src/header_metadata.rs @@ -97,7 +97,7 @@ pub fn lowest_common_ancestor + ?Sized>( } /// Compute a tree-route between two blocks. See tree-route docs for more details. -pub fn tree_route>( +pub fn tree_route + ?Sized>( backend: &T, from: Block::Hash, to: Block::Hash, diff --git a/substrate/primitives/consensus/aura/Cargo.toml b/substrate/primitives/consensus/aura/Cargo.toml index b689c84f158c7bddc1e845449654056b67e78b6f..a54499178171dab260e953dd1082d512d48f6df0 100644 --- a/substrate/primitives/consensus/aura/Cargo.toml +++ b/substrate/primitives/consensus/aura/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-api = { path = "../../api", default-features = false } sp-application-crypto = { path = "../../application-crypto", default-features = false } diff --git a/substrate/primitives/consensus/babe/Cargo.toml b/substrate/primitives/consensus/babe/Cargo.toml index 799d474aebe45e26a94392899251b054cd39d84b..46c032ba61a6067bd7cfa9f786706701c7e429c3 100644 --- a/substrate/primitives/consensus/babe/Cargo.toml +++ b/substrate/primitives/consensus/babe/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-api = { path = "../../api", default-features = false } diff --git a/substrate/primitives/consensus/beefy/Cargo.toml b/substrate/primitives/consensus/beefy/Cargo.toml index a16d943b91469d0d24ba6453e6b08a6385ec2f36..a682939a02f95064f8fed2fe7f6be0a9ad228ede 100644 --- a/substrate/primitives/consensus/beefy/Cargo.toml +++ b/substrate/primitives/consensus/beefy/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["alloc", "derive"], workspace = true } sp-api = { path = "../../api", default-features = false } @@ -30,7 +30,7 @@ strum = { version = "0.26.2", features = ["derive"], default-features = false } lazy_static = { version = "1.4.0", optional = true } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" w3f-bls = { version = "0.1.3", features = ["std"] } [features] diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs index 390c0ff71273ad4b9993a5a3e7be0265148a8c5b..f70434beab33c5942d2548d89ad4c889f04ce0f5 100644 --- a/substrate/primitives/consensus/beefy/src/lib.rs +++ b/substrate/primitives/consensus/beefy/src/lib.rs @@ -52,7 +52,10 @@ use core::fmt::{Debug, Display}; use scale_info::TypeInfo; use sp_application_crypto::{AppCrypto, AppPublic, ByteArray, RuntimeAppPublic}; use sp_core::H256; -use sp_runtime::traits::{Hash, Keccak256, NumberFor}; +use sp_runtime::{ + traits::{Hash, Keccak256, NumberFor}, + OpaqueValue, +}; /// Key type for BEEFY module. pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BEEFY; @@ -399,21 +402,7 @@ impl OnNewValidatorSet for () { /// the runtime API boundary this type is unknown and as such we keep this /// opaque representation, implementors of the runtime API will have to make /// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type. -#[derive(Decode, Encode, PartialEq, TypeInfo)] -pub struct OpaqueKeyOwnershipProof(Vec); -impl OpaqueKeyOwnershipProof { - /// Create a new `OpaqueKeyOwnershipProof` using the given encoded - /// representation. - pub fn new(inner: Vec) -> OpaqueKeyOwnershipProof { - OpaqueKeyOwnershipProof(inner) - } - - /// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key - /// ownership proof type. - pub fn decode(self) -> Option { - codec::Decode::decode(&mut &self.0[..]).ok() - } -} +pub type OpaqueKeyOwnershipProof = OpaqueValue; sp_api::decl_runtime_apis! { /// API necessary for BEEFY voters. diff --git a/substrate/primitives/consensus/grandpa/Cargo.toml b/substrate/primitives/consensus/grandpa/Cargo.toml index 6c228383d003fbafa879a88577b37609ce9d0278..f63f5f3122f41f76640dcebb8dca592f31268577 100644 --- a/substrate/primitives/consensus/grandpa/Cargo.toml +++ b/substrate/primitives/consensus/grandpa/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } grandpa = { package = "finality-grandpa", version = "0.16.2", default-features = false, features = ["derive-codec"] } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/primitives/consensus/grandpa/src/lib.rs b/substrate/primitives/consensus/grandpa/src/lib.rs index 75ed81894c259ad7102b9b98bb3e6e29bea4cdcd..5320c9434041ce5c6f235719e200ee4e4cba5c7d 100644 --- a/substrate/primitives/consensus/grandpa/src/lib.rs +++ b/substrate/primitives/consensus/grandpa/src/lib.rs @@ -31,7 +31,7 @@ use scale_info::TypeInfo; use sp_keystore::KeystorePtr; use sp_runtime::{ traits::{Header as HeaderT, NumberFor}, - ConsensusEngineId, RuntimeDebug, + ConsensusEngineId, OpaqueValue, RuntimeDebug, }; /// The log target to be used by client code. @@ -465,22 +465,7 @@ where /// the runtime API boundary this type is unknown and as such we keep this /// opaque representation, implementors of the runtime API will have to make /// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type. -#[derive(Decode, Encode, PartialEq, TypeInfo)] -pub struct OpaqueKeyOwnershipProof(Vec); - -impl OpaqueKeyOwnershipProof { - /// Create a new `OpaqueKeyOwnershipProof` using the given encoded - /// representation. - pub fn new(inner: Vec) -> OpaqueKeyOwnershipProof { - OpaqueKeyOwnershipProof(inner) - } - - /// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key - /// ownership proof type. - pub fn decode(self) -> Option { - codec::Decode::decode(&mut &self.0[..]).ok() - } -} +pub type OpaqueKeyOwnershipProof = OpaqueValue; sp_api::decl_runtime_apis! { /// APIs for integrating the GRANDPA finality gadget into runtimes. diff --git a/substrate/primitives/consensus/pow/Cargo.toml b/substrate/primitives/consensus/pow/Cargo.toml index 7a884f865fbeea0d6e7c0fd6a6699e0a5b513769..0700e2c4f8b9f1595ca820ab0cc3fe5e963dec91 100644 --- a/substrate/primitives/consensus/pow/Cargo.toml +++ b/substrate/primitives/consensus/pow/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } sp-api = { path = "../../api", default-features = false } sp-core = { path = "../../core", default-features = false } sp-runtime = { path = "../../runtime", default-features = false } diff --git a/substrate/primitives/consensus/sassafras/Cargo.toml b/substrate/primitives/consensus/sassafras/Cargo.toml index 50348054da0118ca52137a5f1c62040e6dd86bea..c8eb9b76b93b0e65de11aa65116353d1e429cfb7 100644 --- a/substrate/primitives/consensus/sassafras/Cargo.toml +++ b/substrate/primitives/consensus/sassafras/Cargo.toml @@ -18,7 +18,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -scale-codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } +scale-codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["derive"], optional = true, workspace = true } sp-api = { path = "../../api", default-features = false } diff --git a/substrate/primitives/consensus/slots/Cargo.toml b/substrate/primitives/consensus/slots/Cargo.toml index a8b12900617960f953726d1b4eac5bf585b1f6bf..dd519eab46475fb16f4768de2fab6138c5a059b4 100644 --- a/substrate/primitives/consensus/slots/Cargo.toml +++ b/substrate/primitives/consensus/slots/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-timestamp = { path = "../../timestamp", default-features = false } diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index 8437497b02bd10f7dbb254998db6a9989c79edc5..f931faf8bd043406d2d30943a594d94ad745ae05 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } log = { workspace = true } serde = { optional = true, features = ["alloc", "derive"], workspace = true } @@ -44,11 +44,11 @@ thiserror = { optional = true, workspace = true } tracing = { version = "0.1.29", optional = true } bitflags = "1.3" paste = "1.0.7" -itertools = { version = "0.10.3", optional = true } +itertools = { version = "0.11", optional = true } # full crypto -array-bytes = { version = "6.1" } -ed25519-zebra = { version = "3.1.0", default-features = false } +array-bytes = { version = "6.2.2" } +ed25519-zebra = { version = "4.0.3", default-features = false } blake2 = { version = "0.10.4", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"] } schnorrkel = { version = "0.11.4", features = ["preaudit_deprecated"], default-features = false } @@ -66,7 +66,7 @@ w3f-bls = { version = "0.1.3", default-features = false, optional = true } bandersnatch_vrfs = { git = "https://github.com/w3f/ring-vrf", rev = "e9782f9", default-features = false, features = ["substrate-curves"], optional = true } [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" serde_json = { workspace = true, default-features = true } lazy_static = "1.4.0" regex = "1.6.0" diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index a9494f2860b4c018d465eecb9eafe825e169292c..269b6bfcd8dcefc961aa10b1384d4cfe0bfdfd19 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -110,7 +110,9 @@ impl TraitPair for Pair { /// Returns true if the signature is good. fn verify>(sig: &Signature, message: M, public: &Public) -> bool { let Ok(public) = VerificationKey::try_from(public.as_slice()) else { return false }; - let Ok(signature) = ed25519_zebra::Signature::try_from(sig.as_ref()) else { return false }; + let Ok(signature) = ed25519_zebra::Signature::try_from(sig.as_slice()) else { + return false + }; public.verify(&signature, message.as_ref()).is_ok() } diff --git a/substrate/primitives/crypto/hashing/Cargo.toml b/substrate/primitives/crypto/hashing/Cargo.toml index 096650e231c8f218966883c503e21ba15e197d9b..1755164888bc9f846dd2ff587aaef5124dd8923d 100644 --- a/substrate/primitives/crypto/hashing/Cargo.toml +++ b/substrate/primitives/crypto/hashing/Cargo.toml @@ -24,7 +24,7 @@ sha3 = { version = "0.10.0", default-features = false } twox-hash = { version = "1.6.3", default-features = false, features = ["digest_0_10"] } [dev-dependencies] -criterion = "0.4.0" +criterion = "0.5.1" sp-crypto-hashing-proc-macro = { path = "proc-macro" } [[bench]] diff --git a/substrate/primitives/externalities/Cargo.toml b/substrate/primitives/externalities/Cargo.toml index 20fa3e3e397c23632a67ca86cecf1a593e48a0e2..3a0d0315e9178a0e54ba001064fb6feb65c1b731 100644 --- a/substrate/primitives/externalities/Cargo.toml +++ b/substrate/primitives/externalities/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } environmental = { version = "1.1.3", default-features = false } sp-storage = { path = "../storage", default-features = false } diff --git a/substrate/primitives/genesis-builder/Cargo.toml b/substrate/primitives/genesis-builder/Cargo.toml index 96e99553294120698ae69d70e9da609326fc3489..4fc8a0416fbe5f2ffdbd021dd42a3d072c61b241 100644 --- a/substrate/primitives/genesis-builder/Cargo.toml +++ b/substrate/primitives/genesis-builder/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bytes"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bytes"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } sp-api = { path = "../api", default-features = false } diff --git a/substrate/primitives/inherents/Cargo.toml b/substrate/primitives/inherents/Cargo.toml index c08ac459de530e55d0064561fe7171e811840c8f..c63aca801a0d7e513963b06d2ce4375f17194d3d 100644 --- a/substrate/primitives/inherents/Cargo.toml +++ b/substrate/primitives/inherents/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2.2" thiserror = { optional = true, workspace = true } diff --git a/substrate/primitives/io/Cargo.toml b/substrate/primitives/io/Cargo.toml index dddea4ffa232541023c91d354aa6fb2013332a98..abb16d163da060ae1d152276189157b77fb6970d 100644 --- a/substrate/primitives/io/Cargo.toml +++ b/substrate/primitives/io/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bytes = { version = "1.1.0", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bytes"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bytes"] } sp-core = { path = "../core", default-features = false } sp-crypto-hashing = { path = "../crypto/hashing", default-features = false } sp-keystore = { path = "../keystore", default-features = false, optional = true } diff --git a/substrate/primitives/keystore/Cargo.toml b/substrate/primitives/keystore/Cargo.toml index a34839358e18333154962f71e1957f9884a71a2f..313b9e1c0059cb86915ca6bfe60ddff21b2c2ffb 100644 --- a/substrate/primitives/keystore/Cargo.toml +++ b/substrate/primitives/keystore/Cargo.toml @@ -16,14 +16,14 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } parking_lot = { version = "0.12.1", default-features = false, optional = true } sp-core = { path = "../core", default-features = false } sp-externalities = { path = "../externalities", default-features = false } [dev-dependencies] rand = "0.8.5" -rand_chacha = "0.2.2" +rand_chacha = "0.3.1" [features] default = ["std"] diff --git a/substrate/primitives/merkle-mountain-range/Cargo.toml b/substrate/primitives/merkle-mountain-range/Cargo.toml index 891f893a0c96e5d10cdb953190a1830b31ef56e4..7b043355c723b0627b574284782a0252e0b536dc 100644 --- a/substrate/primitives/merkle-mountain-range/Cargo.toml +++ b/substrate/primitives/merkle-mountain-range/Cargo.toml @@ -15,10 +15,10 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } log = { workspace = true } -mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.5.2", default-features = false } +mmr-lib = { package = "polkadot-ckb-merkle-mountain-range", version = "0.7.0", default-features = false } serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-api = { path = "../api", default-features = false } sp-core = { path = "../core", default-features = false } @@ -27,7 +27,7 @@ sp-runtime = { path = "../runtime", default-features = false } thiserror = { optional = true, workspace = true } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" [features] default = ["std"] diff --git a/substrate/primitives/merkle-mountain-range/src/lib.rs b/substrate/primitives/merkle-mountain-range/src/lib.rs index c76d66bb08ea700bd6bcc1272d56310bda51881f..3740047e027829eb471a61244b460cdd58fe8cd5 100644 --- a/substrate/primitives/merkle-mountain-range/src/lib.rs +++ b/substrate/primitives/merkle-mountain-range/src/lib.rs @@ -352,15 +352,29 @@ impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3, E:4); /// An MMR proof data for a group of leaves. #[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] -pub struct Proof { +pub struct LeafProof { /// The indices of the leaves the proof is for. pub leaf_indices: Vec, /// Number of leaves in MMR, when the proof was generated. pub leaf_count: NodeIndex, - /// Proof elements (hashes of siblings of inner nodes on the path to the leaf). + /// Proof elements (hashes of siblings of inner nodes on the path to the leafs). pub items: Vec, } +/// An MMR ancestry proof for a prior mmr root. +#[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] +pub struct AncestryProof { + /// Peaks of the ancestor's mmr + pub prev_peaks: Vec, + /// Number of leaves in the ancestor's MMR. + pub prev_leaf_count: u64, + /// Number of leaves in MMR, when the proof was generated. + pub leaf_count: NodeIndex, + /// Proof elements + /// (positions and hashes of siblings of inner nodes on the path to the previous peaks). + pub items: Vec<(u64, Hash)>, +} + /// Merkle Mountain Range operation error. #[cfg_attr(feature = "std", derive(thiserror::Error))] #[derive(RuntimeDebug, codec::Encode, codec::Decode, PartialEq, Eq, TypeInfo)] @@ -437,14 +451,14 @@ sp_api::decl_runtime_apis! { fn generate_proof( block_numbers: Vec, best_known_block_number: Option - ) -> Result<(Vec, Proof), Error>; + ) -> Result<(Vec, LeafProof), Error>; /// Verify MMR proof against on-chain MMR for a batch of leaves. /// /// Note this function will use on-chain MMR root hash and check if the proof matches the hash. /// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the - /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the [Proof] - fn verify_proof(leaves: Vec, proof: Proof) -> Result<(), Error>; + /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the [LeafProof] + fn verify_proof(leaves: Vec, proof: LeafProof) -> Result<(), Error>; /// Verify MMR proof against given root hash for a batch of leaves. /// @@ -452,8 +466,8 @@ sp_api::decl_runtime_apis! { /// proof is verified against given MMR root hash. /// /// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the - /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the [Proof] - fn verify_proof_stateless(root: Hash, leaves: Vec, proof: Proof) + /// same position in both the `leaves` vector and the `leaf_indices` vector contained in the [LeafProof] + fn verify_proof_stateless(root: Hash, leaves: Vec, proof: LeafProof) -> Result<(), Error>; } } @@ -472,12 +486,12 @@ mod tests { type Test = DataOrHash; type TestCompact = Compact; - type TestProof = Proof<::Output>; + type TestProof = LeafProof<::Output>; #[test] fn should_encode_decode_proof() { // given - let proof: TestProof = Proof { + let proof: TestProof = LeafProof { leaf_indices: vec![5], leaf_count: 10, items: vec![ diff --git a/substrate/primitives/metadata-ir/Cargo.toml b/substrate/primitives/metadata-ir/Cargo.toml index ca8408d0ad97c0c5b880b8b60b59d693e7652b2f..90ecd1dfb13df810abbfd0ff460fa798a58e0033 100644 --- a/substrate/primitives/metadata-ir/Cargo.toml +++ b/substrate/primitives/metadata-ir/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/primitives/mixnet/Cargo.toml b/substrate/primitives/mixnet/Cargo.toml index 166609ad922c96aaa62cde3bc42156e125635686..ef32503000d95b2c3c2026c2bb8aeb1eedc573cc 100644 --- a/substrate/primitives/mixnet/Cargo.toml +++ b/substrate/primitives/mixnet/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-api = { default-features = false, path = "../api" } sp-application-crypto = { default-features = false, path = "../application-crypto" } diff --git a/substrate/primitives/npos-elections/Cargo.toml b/substrate/primitives/npos-elections/Cargo.toml index afa59af64d6d8599a9835f448f9a2031831dc694..2da74429a4813e8fd3d3834682a49acce5f950f3 100644 --- a/substrate/primitives/npos-elections/Cargo.toml +++ b/substrate/primitives/npos-elections/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-arithmetic = { path = "../arithmetic", default-features = false } diff --git a/substrate/primitives/runtime-interface/Cargo.toml b/substrate/primitives/runtime-interface/Cargo.toml index b4fab17eeb7c1872404cbc9d03bc775be6736fe9..f853a532515bb2d2406fe00e82e5803d4e7a056e 100644 --- a/substrate/primitives/runtime-interface/Cargo.toml +++ b/substrate/primitives/runtime-interface/Cargo.toml @@ -23,7 +23,7 @@ sp-std = { path = "../std", default-features = false } sp-tracing = { path = "../tracing", default-features = false } sp-runtime-interface-proc-macro = { path = "proc-macro" } sp-externalities = { path = "../externalities", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bytes"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["bytes"] } static_assertions = "1.0.0" primitive-types = { version = "0.12.0", default-features = false } sp-storage = { path = "../storage", default-features = false } diff --git a/substrate/primitives/runtime/Cargo.toml b/substrate/primitives/runtime/Cargo.toml index fb5fd60fbbfd90260127fc8ec9d3750badc4b5ba..4d298b7ce5e3df4169945092d6ca53e8b616a11a 100644 --- a/substrate/primitives/runtime/Cargo.toml +++ b/substrate/primitives/runtime/Cargo.toml @@ -17,11 +17,12 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] } either = { version = "1.5", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } +num-traits = { version = "0.2.17", default-features = false } paste = "1.0" rand = { version = "0.8.5", optional = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } @@ -54,6 +55,7 @@ std = [ "either/use_std", "hash256-std-hasher/std", "log/std", + "num-traits/std", "rand", "scale-info/std", "serde/std", diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs index 44bf3c969e5441245d1547e779195cdb68a83599..046909b9a38d732a80f5178d228090fe10939c8d 100644 --- a/substrate/primitives/runtime/src/lib.rs +++ b/substrate/primitives/runtime/src/lib.rs @@ -91,6 +91,7 @@ mod runtime_string; pub mod testing; pub mod traits; pub mod transaction_validity; +pub mod type_with_default; pub use crate::runtime_string::*; @@ -1008,6 +1009,21 @@ pub enum ExtrinsicInclusionMode { OnlyInherents, } +/// Simple blob that hold a value in an encoded form without committing to its type. +#[derive(Decode, Encode, PartialEq, TypeInfo)] +pub struct OpaqueValue(Vec); +impl OpaqueValue { + /// Create a new `OpaqueValue` using the given encoded representation. + pub fn new(inner: Vec) -> OpaqueValue { + OpaqueValue(inner) + } + + /// Try to decode this `OpaqueValue` into the given concrete type. + pub fn decode(&self) -> Option { + Decode::decode(&mut &self.0[..]).ok() + } +} + #[cfg(test)] mod tests { use crate::traits::BlakeTwo256; diff --git a/substrate/primitives/runtime/src/type_with_default.rs b/substrate/primitives/runtime/src/type_with_default.rs new file mode 100644 index 0000000000000000000000000000000000000000..1465393640dc103347f8687d3272402570a1903d --- /dev/null +++ b/substrate/primitives/runtime/src/type_with_default.rs @@ -0,0 +1,506 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Provides a type that wraps another type and provides a default value. + +use crate::traits::{Bounded, One, Zero}; +use codec::{Compact, CompactAs, Decode, Encode, HasCompact, MaxEncodedLen}; +use core::{ + fmt::Display, + marker::PhantomData, + ops::{ + Add, AddAssign, BitAnd, BitOr, BitXor, Deref, Div, DivAssign, Mul, MulAssign, Not, Rem, + RemAssign, Shl, Shr, Sub, SubAssign, + }, +}; +use num_traits::{ + CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, + Num, NumCast, PrimInt, Saturating, ToPrimitive, +}; +use scale_info::TypeInfo; +use sp_core::Get; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A type that wraps another type and provides a default value. +/// +/// Passes through arithmetical and many other operations to the inner value. +#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct TypeWithDefault>(T, PhantomData); + +impl> TypeWithDefault { + fn new(value: T) -> Self { + Self(value, PhantomData) + } +} + +impl> Clone for TypeWithDefault { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl> Copy for TypeWithDefault {} + +impl> PartialEq for TypeWithDefault { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl> Eq for TypeWithDefault {} + +impl> PartialOrd for TypeWithDefault { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl> Ord for TypeWithDefault { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl> Deref for TypeWithDefault { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl> Default for TypeWithDefault { + fn default() -> Self { + Self::new(D::get()) + } +} + +impl, D: Get> From for TypeWithDefault { + fn from(value: u16) -> Self { + Self::new(value.into()) + } +} + +impl, D: Get> From for TypeWithDefault { + fn from(value: u32) -> Self { + Self::new(value.into()) + } +} + +impl, D: Get> From for TypeWithDefault { + fn from(value: u64) -> Self { + Self::new(value.into()) + } +} + +impl> CheckedNeg for TypeWithDefault { + fn checked_neg(&self) -> Option { + self.0.checked_neg().map(Self::new) + } +} + +impl> CheckedRem for TypeWithDefault { + fn checked_rem(&self, rhs: &Self) -> Option { + self.0.checked_rem(&rhs.0).map(Self::new) + } +} + +impl> CheckedShr for TypeWithDefault { + fn checked_shr(&self, n: u32) -> Option { + self.0.checked_shr(n).map(Self::new) + } +} + +impl> CheckedShl for TypeWithDefault { + fn checked_shl(&self, n: u32) -> Option { + self.0.checked_shl(n).map(Self::new) + } +} + +impl, D: Get> Rem for TypeWithDefault { + type Output = Self; + fn rem(self, rhs: Self) -> Self { + Self::new(self.0 % rhs.0) + } +} + +impl, D: Get> Rem for TypeWithDefault { + type Output = Self; + fn rem(self, rhs: u32) -> Self { + Self::new(self.0 % (rhs.into())) + } +} + +impl, D: Get> Shr for TypeWithDefault { + type Output = Self; + fn shr(self, rhs: u32) -> Self { + Self::new(self.0 >> rhs) + } +} + +impl, D: Get> Shr for TypeWithDefault { + type Output = Self; + fn shr(self, rhs: usize) -> Self { + Self::new(self.0 >> rhs) + } +} + +impl, D: Get> Shl for TypeWithDefault { + type Output = Self; + fn shl(self, rhs: u32) -> Self { + Self::new(self.0 << rhs) + } +} + +impl, D: Get> Shl for TypeWithDefault { + type Output = Self; + fn shl(self, rhs: usize) -> Self { + Self::new(self.0 << rhs) + } +} + +impl> RemAssign for TypeWithDefault { + fn rem_assign(&mut self, rhs: Self) { + self.0 %= rhs.0 + } +} + +impl> DivAssign for TypeWithDefault { + fn div_assign(&mut self, rhs: Self) { + self.0 /= rhs.0 + } +} + +impl> MulAssign for TypeWithDefault { + fn mul_assign(&mut self, rhs: Self) { + self.0 *= rhs.0 + } +} + +impl> SubAssign for TypeWithDefault { + fn sub_assign(&mut self, rhs: Self) { + self.0 -= rhs.0 + } +} + +impl> AddAssign for TypeWithDefault { + fn add_assign(&mut self, rhs: Self) { + self.0 += rhs.0 + } +} + +impl, D: Get> From for TypeWithDefault { + fn from(value: u8) -> Self { + Self::new(value.into()) + } +} + +impl> Display for TypeWithDefault { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl, D: Get> TryFrom for TypeWithDefault { + type Error = >::Error; + fn try_from(n: u128) -> Result, Self::Error> { + T::try_from(n).map(Self::new) + } +} + +impl, D: Get> TryFrom for TypeWithDefault { + type Error = >::Error; + fn try_from(n: usize) -> Result, Self::Error> { + T::try_from(n).map(Self::new) + } +} + +impl, D: Get> TryFrom> for u8 { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl, D: Get> TryFrom> for u16 { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl, D: Get> TryFrom> for u32 { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl, D: Get> TryFrom> for u64 { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl, D: Get> TryFrom> for u128 { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl, D: Get> TryFrom> for usize { + type Error = >::Error; + fn try_from(value: TypeWithDefault) -> Result { + value.0.try_into() + } +} + +impl> Zero for TypeWithDefault { + fn zero() -> Self { + Self::new(T::zero()) + } + + fn is_zero(&self) -> bool { + self.0 == T::zero() + } +} + +impl> Bounded for TypeWithDefault { + fn min_value() -> Self { + Self::new(T::min_value()) + } + + fn max_value() -> Self { + Self::new(T::max_value()) + } +} + +impl> PrimInt for TypeWithDefault { + fn count_ones(self) -> u32 { + self.0.count_ones() + } + + fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + fn rotate_left(self, n: u32) -> Self { + Self::new(self.0.rotate_left(n)) + } + + fn rotate_right(self, n: u32) -> Self { + Self::new(self.0.rotate_right(n)) + } + + fn swap_bytes(self) -> Self { + Self::new(self.0.swap_bytes()) + } + + fn from_be(x: Self) -> Self { + Self::new(T::from_be(x.0)) + } + + fn from_le(x: Self) -> Self { + Self::new(T::from_le(x.0)) + } + + fn to_be(self) -> Self { + Self::new(self.0.to_be()) + } + + fn to_le(self) -> Self { + Self::new(self.0.to_le()) + } + + fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + fn signed_shl(self, n: u32) -> Self { + Self::new(self.0.signed_shl(n)) + } + + fn signed_shr(self, n: u32) -> Self { + Self::new(self.0.signed_shr(n)) + } + + fn unsigned_shl(self, n: u32) -> Self { + Self::new(self.0.unsigned_shl(n)) + } + + fn unsigned_shr(self, n: u32) -> Self { + Self::new(self.0.unsigned_shr(n)) + } + + fn pow(self, exp: u32) -> Self { + Self::new(self.0.pow(exp)) + } +} + +impl> Saturating for TypeWithDefault { + fn saturating_add(self, rhs: Self) -> Self { + Self::new(self.0.saturating_add(rhs.0)) + } + + fn saturating_sub(self, rhs: Self) -> Self { + Self::new(self.0.saturating_sub(rhs.0)) + } +} + +impl, D: Get> Div for TypeWithDefault { + type Output = Self; + fn div(self, rhs: Self) -> Self { + Self::new(self.0 / rhs.0) + } +} + +impl, D: Get> Mul for TypeWithDefault { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + Self::new(self.0 * rhs.0) + } +} + +impl> CheckedDiv for TypeWithDefault { + fn checked_div(&self, rhs: &Self) -> Option { + self.0.checked_div(&rhs.0).map(Self::new) + } +} + +impl> CheckedMul for TypeWithDefault { + fn checked_mul(&self, rhs: &Self) -> Option { + self.0.checked_mul(&rhs.0).map(Self::new) + } +} + +impl, D: Get> Sub for TypeWithDefault { + type Output = Self; + fn sub(self, rhs: Self) -> Self { + Self::new(self.0 - rhs.0) + } +} + +impl> CheckedSub for TypeWithDefault { + fn checked_sub(&self, rhs: &Self) -> Option { + self.0.checked_sub(&rhs.0).map(Self::new) + } +} + +impl, D: Get> Add for TypeWithDefault { + type Output = Self; + fn add(self, rhs: Self) -> Self { + Self::new(self.0 + rhs.0) + } +} + +impl> CheckedAdd for TypeWithDefault { + fn checked_add(&self, rhs: &Self) -> Option { + self.0.checked_add(&rhs.0).map(Self::new) + } +} + +impl, D: Get> BitAnd for TypeWithDefault { + type Output = Self; + fn bitand(self, rhs: Self) -> Self { + Self::new(self.0 & rhs.0) + } +} + +impl, D: Get> BitOr for TypeWithDefault { + type Output = Self; + fn bitor(self, rhs: Self) -> Self { + Self::new(self.0 | rhs.0) + } +} + +impl, D: Get> BitXor for TypeWithDefault { + type Output = Self; + fn bitxor(self, rhs: Self) -> Self { + Self::new(self.0 ^ rhs.0) + } +} + +impl> One for TypeWithDefault { + fn one() -> Self { + Self::new(T::one()) + } +} + +impl, D: Get> Not for TypeWithDefault { + type Output = Self; + fn not(self) -> Self { + Self::new(self.0.not()) + } +} + +impl> NumCast for TypeWithDefault { + fn from(n: P) -> Option { + ::from(n).map_or(None, |n| Some(Self::new(n))) + } +} + +impl> Num for TypeWithDefault { + type FromStrRadixErr = ::FromStrRadixErr; + + fn from_str_radix(s: &str, radix: u32) -> Result { + T::from_str_radix(s, radix).map(Self::new) + } +} + +impl> ToPrimitive for TypeWithDefault { + fn to_i64(&self) -> Option { + self.0.to_i64() + } + + fn to_u64(&self) -> Option { + self.0.to_u64() + } + + fn to_i128(&self) -> Option { + self.0.to_i128() + } + + fn to_u128(&self) -> Option { + self.0.to_u128() + } +} + +impl> From>> for TypeWithDefault { + fn from(c: Compact>) -> Self { + c.0 + } +} + +impl> CompactAs for TypeWithDefault { + type As = T; + + fn encode_as(&self) -> &Self::As { + &self.0 + } + + fn decode_from(val: Self::As) -> Result { + Ok(Self::new(val)) + } +} diff --git a/substrate/primitives/session/Cargo.toml b/substrate/primitives/session/Cargo.toml index 5314ccd6d965c44de5371a4fbc0888821e725236..9355ab420107147883b545467b31fcbf95be6191 100644 --- a/substrate/primitives/session/Cargo.toml +++ b/substrate/primitives/session/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-api = { path = "../api", default-features = false } sp-core = { path = "../core", default-features = false } diff --git a/substrate/primitives/staking/Cargo.toml b/substrate/primitives/staking/Cargo.toml index e380abb6a8c070a861b8a84db473a66173aeaacd..6e3ce4bca106fab44516780921d4f15ed34854cb 100644 --- a/substrate/primitives/staking/Cargo.toml +++ b/substrate/primitives/staking/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { features = ["alloc", "derive"], optional = true, workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2.2" diff --git a/substrate/primitives/staking/src/lib.rs b/substrate/primitives/staking/src/lib.rs index ad6cc6e2f4ffdd8241d951cdd8ec2a9faacc8254..28a61cd4331392d8682dc5491926318d250ebf82 100644 --- a/substrate/primitives/staking/src/lib.rs +++ b/substrate/primitives/staking/src/lib.rs @@ -285,6 +285,13 @@ pub trait StakingInterface { Self::status(who).map(|s| matches!(s, StakerStatus::Validator)).unwrap_or(false) } + /// Checks whether the staker is a virtual account. + /// + /// A virtual staker is an account whose locks are not managed by the [`StakingInterface`] + /// implementation but by an external pallet. See [`StakingUnchecked::virtual_bond`] for more + /// details. + fn is_virtual_staker(who: &Self::AccountId) -> bool; + /// Get the nominations of a stash, if they are a nominator, `None` otherwise. fn nominations(who: &Self::AccountId) -> Option> { match Self::status(who) { @@ -456,4 +463,129 @@ pub struct PagedExposureMetadata { pub page_count: Page, } +/// Trait to provide delegation functionality for stakers. +/// +/// Introduces two new terms to the staking system: +/// - `Delegator`: An account that delegates funds to an `Agent`. +/// - `Agent`: An account that receives delegated funds from `Delegators`. It can then use these +/// funds to participate in the staking system. It can never use its own funds to stake. They +/// (virtually bond)[`StakingUnchecked::virtual_bond`] into the staking system and can also be +/// termed as `Virtual Nominators`. +/// +/// The `Agent` is responsible for managing rewards and slashing for all the `Delegators` that +/// have delegated funds to it. +pub trait DelegationInterface { + /// Balance type used by the staking system. + type Balance: Sub + + Ord + + PartialEq + + Default + + Copy + + MaxEncodedLen + + FullCodec + + TypeInfo + + Saturating; + + /// AccountId type used by the staking system. + type AccountId: Clone + core::fmt::Debug; + + /// Effective balance of the `Agent` account. + /// + /// This takes into account any pending slashes to `Agent`. + fn agent_balance(agent: &Self::AccountId) -> Self::Balance; + + /// Returns the total amount of funds delegated by a `delegator`. + fn delegator_balance(delegator: &Self::AccountId) -> Self::Balance; + + /// Delegate funds to `Agent`. + /// + /// Only used for the initial delegation. Use [`Self::delegate_extra`] to add more delegation. + fn delegate( + delegator: &Self::AccountId, + agent: &Self::AccountId, + reward_account: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + /// Add more delegation to the `Agent`. + /// + /// If this is the first delegation, use [`Self::delegate`] instead. + fn delegate_extra( + delegator: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + /// Withdraw or revoke delegation to `Agent`. + /// + /// If there are `Agent` funds upto `amount` available to withdraw, then those funds would + /// be released to the `delegator` + fn withdraw_delegation( + delegator: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + num_slashing_spans: u32, + ) -> DispatchResult; + + /// Returns true if there are pending slashes posted to the `Agent` account. + /// + /// Slashes to `Agent` account are not immediate and are applied lazily. Since `Agent` + /// has an unbounded number of delegators, immediate slashing is not possible. + fn has_pending_slash(agent: &Self::AccountId) -> bool; + + /// Apply a pending slash to an `Agent` by slashing `value` from `delegator`. + /// + /// A reporter may be provided (if one exists) in order for the implementor to reward them, + /// if applicable. + fn delegator_slash( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + maybe_reporter: Option, + ) -> DispatchResult; +} + +/// Trait to provide functionality for direct stakers to migrate to delegation agents. +/// See [`DelegationInterface`] for more details on delegation. +pub trait DelegationMigrator { + /// Balance type used by the staking system. + type Balance: Sub + + Ord + + PartialEq + + Default + + Copy + + MaxEncodedLen + + FullCodec + + TypeInfo + + Saturating; + + /// AccountId type used by the staking system. + type AccountId: Clone + core::fmt::Debug; + + /// Migrate an existing `Nominator` to `Agent` account. + /// + /// The implementation should ensure the `Nominator` account funds are moved to an escrow + /// from which `Agents` can later release funds to its `Delegators`. + fn migrate_nominator_to_agent( + agent: &Self::AccountId, + reward_account: &Self::AccountId, + ) -> DispatchResult; + + /// Migrate `value` of delegation to `delegator` from a migrating agent. + /// + /// When a direct `Nominator` migrates to `Agent`, the funds are kept in escrow. This function + /// allows the `Agent` to release the funds to the `delegator`. + fn migrate_delegation( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + ) -> DispatchResult; + + /// Drop the `Agent` account and its associated delegators. + /// + /// Also removed from [`StakingUnchecked`] as a Virtual Staker. Useful for testing. + #[cfg(feature = "runtime-benchmarks")] + fn drop_agent(agent: &Self::AccountId); +} + sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $); diff --git a/substrate/primitives/state-machine/Cargo.toml b/substrate/primitives/state-machine/Cargo.toml index 63251bbd181d4b6ef63661e1b568d1929d619a3c..c383a17cb006e3c4433172aedde957465fbb569f 100644 --- a/substrate/primitives/state-machine/Cargo.toml +++ b/substrate/primitives/state-machine/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } parking_lot = { version = "0.12.1", optional = true } @@ -32,7 +32,7 @@ sp-trie = { path = "../trie", default-features = false } trie-db = { version = "0.29.0", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" pretty_assertions = "1.2.1" rand = "0.8.5" sp-runtime = { path = "../runtime" } diff --git a/substrate/primitives/statement-store/Cargo.toml b/substrate/primitives/statement-store/Cargo.toml index b36bff69a007c669724950ca94f2cebc859890ed..bb893b25dc443f617ab5c0dd3d0d22c94646b689 100644 --- a/substrate/primitives/statement-store/Cargo.toml +++ b/substrate/primitives/statement-store/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-core = { path = "../core", default-features = false } sp-crypto-hashing = { path = "../crypto/hashing", default-features = false } diff --git a/substrate/primitives/storage/Cargo.toml b/substrate/primitives/storage/Cargo.toml index acedc8d0004970fc10f5771ba4b4e2cb87a55198..c3318943d0d481a430da46502cdcb3a3c8aa22a7 100644 --- a/substrate/primitives/storage/Cargo.toml +++ b/substrate/primitives/storage/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } impl-serde = { version = "0.4.0", optional = true, default-features = false } ref-cast = "1.0.0" serde = { features = ["alloc", "derive"], optional = true, workspace = true } diff --git a/substrate/primitives/test-primitives/Cargo.toml b/substrate/primitives/test-primitives/Cargo.toml index 0513555431561a4adb12f5e2b373859df1272af2..b7be614860910eb63f12eadaa3676f69b0e65ada 100644 --- a/substrate/primitives/test-primitives/Cargo.toml +++ b/substrate/primitives/test-primitives/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["derive"], optional = true, workspace = true } sp-application-crypto = { path = "../application-crypto", default-features = false } diff --git a/substrate/primitives/timestamp/Cargo.toml b/substrate/primitives/timestamp/Cargo.toml index 5a1d4fcc985c520eede135b59d8fe5311fd8feac..c1bf9b3255eab83dea9eb9f80b93aa5440e816e1 100644 --- a/substrate/primitives/timestamp/Cargo.toml +++ b/substrate/primitives/timestamp/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } thiserror = { optional = true, workspace = true } sp-inherents = { path = "../inherents", default-features = false } sp-runtime = { path = "../runtime", default-features = false } diff --git a/substrate/primitives/tracing/Cargo.toml b/substrate/primitives/tracing/Cargo.toml index ce30302d4bb0a7166ceb820e72bdc1de0b31cbc3..8adec1670dc2da99c315f58dbc37a92a3cf947f5 100644 --- a/substrate/primitives/tracing/Cargo.toml +++ b/substrate/primitives/tracing/Cargo.toml @@ -21,7 +21,7 @@ features = ["with-tracing"] targets = ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"] [dependencies] -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = [ +codec = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = [ "derive", ] } tracing = { version = "0.1.29", default-features = false } diff --git a/substrate/primitives/transaction-storage-proof/Cargo.toml b/substrate/primitives/transaction-storage-proof/Cargo.toml index 6cce469d3f915786ef93ba0ee0e170a94d40fbeb..1e874c3595acd4723e34c0cb8568256ae2444317 100644 --- a/substrate/primitives/transaction-storage-proof/Cargo.toml +++ b/substrate/primitives/transaction-storage-proof/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = { version = "0.1.79", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-core = { path = "../core", optional = true, default-features = false } sp-inherents = { path = "../inherents", default-features = false } diff --git a/substrate/primitives/trie/Cargo.toml b/substrate/primitives/trie/Cargo.toml index 6469a59e0d10b2f598dd423976136481688bea7d..45459c180d40d076b0d7b59232e9dc76cd0b2d27 100644 --- a/substrate/primitives/trie/Cargo.toml +++ b/substrate/primitives/trie/Cargo.toml @@ -22,7 +22,7 @@ harness = false [dependencies] ahash = { version = "0.8.2", optional = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } hash-db = { version = "0.16.0", default-features = false } lazy_static = { version = "1.4.0", optional = true } memory-db = { version = "0.32.0", default-features = false } @@ -39,7 +39,7 @@ sp-externalities = { path = "../externalities", default-features = false } schnellru = { version = "0.2.1", optional = true } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" criterion = "0.5.1" trie-bench = "0.39.0" trie-standardmap = "0.16.0" diff --git a/substrate/primitives/version/Cargo.toml b/substrate/primitives/version/Cargo.toml index d686b0c75512dac9931c46ffb41c4e4a11522718..f8ef8f66c5355634dbb4a7e1f08adbdb2f035766 100644 --- a/substrate/primitives/version/Cargo.toml +++ b/substrate/primitives/version/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } impl-serde = { version = "0.4.0", default-features = false, optional = true } parity-wasm = { version = "0.45", optional = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/substrate/primitives/version/proc-macro/Cargo.toml b/substrate/primitives/version/proc-macro/Cargo.toml index f7abf88c9a67b7e3102d44254b520a9bbeb7a8a8..3abd5c0910694cf14a8885ecebf4cc855e9e8266 100644 --- a/substrate/primitives/version/proc-macro/Cargo.toml +++ b/substrate/primitives/version/proc-macro/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } proc-macro2 = "1.0.56" quote = { workspace = true } syn = { features = ["extra-traits", "fold", "full", "visit"], workspace = true } diff --git a/substrate/primitives/wasm-interface/Cargo.toml b/substrate/primitives/wasm-interface/Cargo.toml index 15a20fab5e5d83aa4635a38c43738a3007847481..a0c8342d2d3c5014527487faf187fc48fd5344e1 100644 --- a/substrate/primitives/wasm-interface/Cargo.toml +++ b/substrate/primitives/wasm-interface/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2.2" log = { optional = true, workspace = true, default-features = true } wasmtime = { version = "8.0.1", default-features = false, optional = true } diff --git a/substrate/primitives/weights/Cargo.toml b/substrate/primitives/weights/Cargo.toml index e73d4a702b42e4ac5b0cd0a37f1c15eb70bec5e2..d2d72a7cb019fa5ad5c8fd66a32e953f9076068f 100644 --- a/substrate/primitives/weights/Cargo.toml +++ b/substrate/primitives/weights/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bounded-collections = { version = "0.2.0", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["alloc", "derive"], workspace = true } smallvec = "1.11.0" diff --git a/substrate/scripts/ci/node-template-release/Cargo.toml b/substrate/scripts/ci/node-template-release/Cargo.toml index 4327b6857433f40482b21a91e116479ba05da121..8e3e6138b9a8dabdbd67589049e5273305d29a0a 100644 --- a/substrate/scripts/ci/node-template-release/Cargo.toml +++ b/substrate/scripts/ci/node-template-release/Cargo.toml @@ -21,4 +21,4 @@ glob = "0.3" tar = "0.4" tempfile = "3" toml_edit = "0.19" -itertools = "0.10" +itertools = "0.11" diff --git a/substrate/test-utils/cli/Cargo.toml b/substrate/test-utils/cli/Cargo.toml index d654a3aaa7258668c066657b27e3eb97deec6b19..87c595c66f3484cbbaa8d8a6d83ea09453ee99b9 100644 --- a/substrate/test-utils/cli/Cargo.toml +++ b/substrate/test-utils/cli/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-rpc-client = { path = "../../utils/frame/rpc/client" } sp-rpc = { path = "../../primitives/rpc" } assert_cmd = "2.0.10" -nix = "0.26.2" +nix = { version = "0.28.0", features = ["signal"] } regex = "1.7.3" tokio = { version = "1.22.0", features = ["full"] } node-primitives = { path = "../../bin/node/primitives" } diff --git a/substrate/test-utils/client/Cargo.toml b/substrate/test-utils/client/Cargo.toml index 4e4e65314fc3d0d1b6af4f0645c81e2a25835c68..5871f1bf5b4d05ad35f0998e7b4ab9fb3b953d58 100644 --- a/substrate/test-utils/client/Cargo.toml +++ b/substrate/test-utils/client/Cargo.toml @@ -16,9 +16,9 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } diff --git a/substrate/test-utils/client/src/lib.rs b/substrate/test-utils/client/src/lib.rs index d283b24f286aed743ba613f095f2cd319caba263..c07640653d560b54658ced8dc466398b6f291f77 100644 --- a/substrate/test-utils/client/src/lib.rs +++ b/substrate/test-utils/client/src/lib.rs @@ -24,7 +24,7 @@ pub mod client_ext; pub use self::client_ext::{BlockOrigin, ClientBlockImportExt, ClientExt}; pub use sc_client_api::{execution_extensions::ExecutionExtensions, BadBlocks, ForkBlocks}; pub use sc_client_db::{self, Backend, BlocksPruning}; -pub use sc_executor::{self, NativeElseWasmExecutor, WasmExecutionMethod, WasmExecutor}; +pub use sc_executor::{self, WasmExecutionMethod, WasmExecutor}; pub use sc_service::{client, RpcHandlers}; pub use sp_consensus; pub use sp_keyring::{ @@ -245,14 +245,8 @@ impl } } -impl - TestClientBuilder< - Block, - client::LocalCallExecutor>, - Backend, - G, - > where - D: sc_executor::NativeExecutionDispatch, +impl + TestClientBuilder>, Backend, G> { /// Build the test client with the given native executor. pub fn build_with_native_executor( @@ -261,21 +255,18 @@ impl ) -> ( client::Client< Backend, - client::LocalCallExecutor>, + client::LocalCallExecutor>, Block, RuntimeApi, >, sc_consensus::LongestChain, ) where - I: Into>>, - D: sc_executor::NativeExecutionDispatch + 'static, + I: Into>>, Backend: sc_client_api::backend::Backend + 'static, + H: sc_executor::HostFunctions, { - let mut executor = executor.into().unwrap_or_else(|| { - NativeElseWasmExecutor::new_with_wasm_executor(WasmExecutor::builder().build()) - }); - executor.disable_use_native(); + let executor = executor.into().unwrap_or_else(|| WasmExecutor::::builder().build()); let executor = LocalCallExecutor::new( self.backend.clone(), executor.clone(), diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml index 28c1b22f976b61e1ab287be5a2700a71be1de0f9..8733ff9fcebb36199c341cd6d90a96623212944c 100644 --- a/substrate/test-utils/runtime/Cargo.toml +++ b/substrate/test-utils/runtime/Cargo.toml @@ -21,7 +21,7 @@ sp-consensus-aura = { path = "../../primitives/consensus/aura", default-features sp-consensus-babe = { path = "../../primitives/consensus/babe", default-features = false, features = ["serde"] } sp-genesis-builder = { path = "../../primitives/genesis-builder", default-features = false } sp-block-builder = { path = "../../primitives/block-builder", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } sp-inherents = { path = "../../primitives/inherents", default-features = false } sp-keyring = { path = "../../primitives/keyring", default-features = false } @@ -37,6 +37,7 @@ sp-runtime = { path = "../../primitives/runtime", default-features = false, feat pallet-babe = { path = "../../frame/babe", default-features = false } pallet-balances = { path = "../../frame/balances", default-features = false } frame-executive = { path = "../../frame/executive", default-features = false } +frame-metadata-hash-extension = { path = "../../frame/metadata-hash-extension", default-features = false } frame-system = { path = "../../frame/system", default-features = false } frame-system-rpc-runtime-api = { path = "../../frame/system/rpc/runtime-api", default-features = false } pallet-timestamp = { path = "../../frame/timestamp", default-features = false } @@ -49,7 +50,7 @@ sp-state-machine = { path = "../../primitives/state-machine", default-features = sp-externalities = { path = "../../primitives/externalities", default-features = false } # 3rd party -array-bytes = { version = "6.1", optional = true } +array-bytes = { version = "6.2.2", optional = true } serde_json = { workspace = true, features = ["alloc"] } log = { workspace = true } hex-literal = { version = "0.4.1" } @@ -67,7 +68,7 @@ serde = { features = ["alloc", "derive"], workspace = true } serde_json = { features = ["alloc"], workspace = true } [build-dependencies] -substrate-wasm-builder = { path = "../../utils/wasm-builder", optional = true } +substrate-wasm-builder = { path = "../../utils/wasm-builder", optional = true, features = ["metadata-hash"] } [features] default = ["std"] @@ -76,6 +77,7 @@ std = [ "array-bytes", "codec/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", @@ -112,5 +114,6 @@ std = [ "substrate-wasm-builder", "trie-db/std", ] + # Special feature to disable logging disable-logging = ["sp-api/disable-logging"] diff --git a/substrate/test-utils/runtime/build.rs b/substrate/test-utils/runtime/build.rs index dd79ce2c5ae842ad7fc1c759a14fa8dedd200a1a..d38173fcfcb4eff6debb4b23c1341d334025d7ed 100644 --- a/substrate/test-utils/runtime/build.rs +++ b/substrate/test-utils/runtime/build.rs @@ -25,6 +25,7 @@ fn main() { // to this value by default. This is because some of our tests // (`restoration_of_globals`) depend on the stack-size. .append_to_rust_flags("-Clink-arg=-zstack-size=1048576") + .enable_metadata_hash("TOKEN", 10) .import_memory() .build(); } diff --git a/substrate/test-utils/runtime/client/src/lib.rs b/substrate/test-utils/runtime/client/src/lib.rs index 7428a7de3a096f343d28b39b618f353578649c74..435f3f5ebacb245ded18b6c258220744619e6d94 100644 --- a/substrate/test-utils/runtime/client/src/lib.rs +++ b/substrate/test-utils/runtime/client/src/lib.rs @@ -42,38 +42,18 @@ pub mod prelude { }; // Client structs pub use super::{ - Backend, ExecutorDispatch, LocalExecutorDispatch, NativeElseWasmExecutor, TestClient, - TestClientBuilder, WasmExecutionMethod, + Backend, ExecutorDispatch, TestClient, TestClientBuilder, WasmExecutionMethod, }; // Keyring pub use super::{AccountKeyring, Sr25519Keyring}; } -/// A unit struct which implements `NativeExecutionDispatch` feeding in the -/// hard-coded runtime. -pub struct LocalExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for LocalExecutorDispatch { - type ExtendHostFunctions = (); - - fn dispatch(method: &str, data: &[u8]) -> Option> { - substrate_test_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - substrate_test_runtime::native_version() - } -} - /// Test client database backend. pub type Backend = substrate_test_client::Backend; /// Test client executor. -pub type ExecutorDispatch = client::LocalCallExecutor< - substrate_test_runtime::Block, - Backend, - NativeElseWasmExecutor, ->; +pub type ExecutorDispatch = + client::LocalCallExecutor; /// Parameters of test-client builder with test-runtime. #[derive(Default)] @@ -113,14 +93,10 @@ pub type TestClientBuilder = substrate_test_client::TestClientBuilder< GenesisParameters, >; -/// Test client type with `LocalExecutorDispatch` and generic Backend. +/// Test client type with `WasmExecutor` and generic Backend. pub type Client = client::Client< B, - client::LocalCallExecutor< - substrate_test_runtime::Block, - B, - NativeElseWasmExecutor, - >, + client::LocalCallExecutor, substrate_test_runtime::Block, substrate_test_runtime::RuntimeApi, >; @@ -206,14 +182,8 @@ pub trait TestClientBuilderExt: Sized { } impl TestClientBuilderExt - for TestClientBuilder< - client::LocalCallExecutor< - substrate_test_runtime::Block, - B, - NativeElseWasmExecutor, - >, - B, - > where + for TestClientBuilder, B> +where B: sc_client_api::backend::Backend + 'static, { fn genesis_init_mut(&mut self) -> &mut GenesisParameters { @@ -238,6 +208,7 @@ pub fn new() -> Client { } /// Create a new native executor. -pub fn new_native_or_wasm_executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new_with_wasm_executor(WasmExecutor::builder().build()) +#[deprecated(note = "Switch to `WasmExecutor:default()`.")] +pub fn new_native_or_wasm_executor() -> WasmExecutor { + WasmExecutor::default() } diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs index e355e5d099ad5a01c74512f79d722fdf968af02e..5ae0d8f8f6eca2517b3a2c4db6fc8f4501744511 100644 --- a/substrate/test-utils/runtime/src/extrinsic.rs +++ b/substrate/test-utils/runtime/src/extrinsic.rs @@ -22,10 +22,11 @@ use crate::{ CheckSubstrateCall, Extrinsic, Nonce, Pair, RuntimeCall, SignedPayload, TransferData, }; use codec::Encode; +use frame_metadata_hash_extension::CheckMetadataHash; use frame_system::{CheckNonce, CheckWeight}; use sp_core::crypto::Pair as TraitPair; use sp_keyring::AccountKeyring; -use sp_runtime::{transaction_validity::TransactionPriority, Perbill}; +use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionPriority, Perbill}; /// Transfer used in test substrate pallet. Extrinsic is created and signed using this data. #[derive(Clone)] @@ -81,17 +82,23 @@ pub struct ExtrinsicBuilder { function: RuntimeCall, signer: Option, nonce: Option, + metadata_hash: Option<[u8; 32]>, } impl ExtrinsicBuilder { /// Create builder for given `RuntimeCall`. By default `Extrinsic` will be signed by `Alice`. pub fn new(function: impl Into) -> Self { - Self { function: function.into(), signer: Some(AccountKeyring::Alice.pair()), nonce: None } + Self { + function: function.into(), + signer: Some(AccountKeyring::Alice.pair()), + nonce: None, + metadata_hash: None, + } } /// Create builder for given `RuntimeCall`. `Extrinsic` will be unsigned. pub fn new_unsigned(function: impl Into) -> Self { - Self { function: function.into(), signer: None, nonce: None } + Self { function: function.into(), signer: None, nonce: None, metadata_hash: None } } /// Create builder for `pallet_call::bench_transfer` from given `TransferData`. @@ -105,6 +112,7 @@ impl ExtrinsicBuilder { Self { nonce: Some(transfer.nonce), signer: Some(transfer.from.clone()), + metadata_hash: None, ..Self::new(BalancesCall::transfer_allow_death { dest: transfer.to, value: transfer.amount, @@ -186,6 +194,12 @@ impl ExtrinsicBuilder { self } + /// Metadata hash to put into the signed data of the extrinsic. + pub fn metadata_hash(mut self, metadata_hash: [u8; 32]) -> Self { + self.metadata_hash = Some(metadata_hash); + self + } + /// Build `Extrinsic` using embedded parameters pub fn build(self) -> Extrinsic { if let Some(signer) = self.signer { @@ -193,9 +207,15 @@ impl ExtrinsicBuilder { CheckNonce::from(self.nonce.unwrap_or(0)), CheckWeight::new(), CheckSubstrateCall {}, + self.metadata_hash + .map(CheckMetadataHash::new_with_custom_hash) + .unwrap_or_else(|| CheckMetadataHash::new(false)), + ); + let raw_payload = SignedPayload::from_raw( + self.function.clone(), + extra.clone(), + extra.additional_signed().unwrap(), ); - let raw_payload = - SignedPayload::from_raw(self.function.clone(), extra.clone(), ((), (), ())); let signature = raw_payload.using_encoded(|e| signer.sign(e)); Extrinsic::new_signed(self.function, signer.public(), signature, extra) diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 370aa0034fcd10db18007050c8b0701810655ada..ab87db0e70065e0a9ab55bbe92bfa36e2238043f 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -149,7 +149,12 @@ pub type Signature = sr25519::Signature; pub type Pair = sp_core::sr25519::Pair; /// The SignedExtension to the basic transaction logic. -pub type SignedExtra = (CheckNonce, CheckWeight, CheckSubstrateCall); +pub type SignedExtra = ( + CheckNonce, + CheckWeight, + CheckSubstrateCall, + frame_metadata_hash_extension::CheckMetadataHash, +); /// The payload being signed in transactions. pub type SignedPayload = sp_runtime::generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. @@ -494,14 +499,14 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - unimplemented!() + OpaqueMetadata::new(Runtime::metadata().into()) } - fn metadata_at_version(_version: u32) -> Option { - unimplemented!() + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) } fn metadata_versions() -> alloc::vec::Vec { - unimplemented!() + Runtime::metadata_versions() } } diff --git a/substrate/test-utils/runtime/transaction-pool/Cargo.toml b/substrate/test-utils/runtime/transaction-pool/Cargo.toml index 9b52706c739915690c7f734c399a3071b30a3630..360e2b7b810d1f40d4ac4884eedb60266e41cc5c 100644 --- a/substrate/test-utils/runtime/transaction-pool/Cargo.toml +++ b/substrate/test-utils/runtime/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } futures = "0.3.30" parking_lot = "0.12.1" thiserror = { workspace = true } diff --git a/substrate/utils/binary-merkle-tree/Cargo.toml b/substrate/utils/binary-merkle-tree/Cargo.toml index a89006d94dc199951ffd5381ff7f51446a21acd6..fd35e6b1e1a25ada0e3cbd7012708a66b3f940f5 100644 --- a/substrate/utils/binary-merkle-tree/Cargo.toml +++ b/substrate/utils/binary-merkle-tree/Cargo.toml @@ -12,12 +12,12 @@ homepage = "https://substrate.io" workspace = true [dependencies] -array-bytes = { version = "6.1", optional = true } +array-bytes = { version = "6.2.2", optional = true } log = { optional = true, workspace = true } hash-db = { version = "0.16.0", default-features = false } [dev-dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" env_logger = "0.11" sp-core = { path = "../../primitives/core" } sp-runtime = { path = "../../primitives/runtime" } diff --git a/substrate/utils/fork-tree/Cargo.toml b/substrate/utils/fork-tree/Cargo.toml index 87135ef2afb884249fd4dfb2683e453c2328180d..275f44623bd1455cb34caa544fbfa4a6e140111b 100644 --- a/substrate/utils/fork-tree/Cargo.toml +++ b/substrate/utils/fork-tree/Cargo.toml @@ -17,4 +17,4 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"] } diff --git a/substrate/utils/frame/benchmarking-cli/Cargo.toml b/substrate/utils/frame/benchmarking-cli/Cargo.toml index 92169484c928d88d28bf3fe85c177ec477d6eaab..7cfacdc2e5edea443de8742fbe23cf9245872f08 100644 --- a/substrate/utils/frame/benchmarking-cli/Cargo.toml +++ b/substrate/utils/frame/benchmarking-cli/Cargo.toml @@ -16,14 +16,14 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -array-bytes = "6.1" +array-bytes = "6.2.2" chrono = "0.4" clap = { version = "4.5.3", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } comfy-table = { version = "7.1.0", default-features = false } handlebars = "5.1.0" Inflector = "0.11.4" -itertools = "0.10.3" +itertools = "0.11" lazy_static = "1.4.0" linked-hash-map = "0.5.4" log = { workspace = true, default-features = true } diff --git a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md index 648908010ba04cf6b19cf2aa50c0ea68491a1e28..cee095fb8cadd4fab0cc34c53bc8f0f7df6fc830 100644 --- a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md @@ -108,7 +108,7 @@ The complete command for Polkadot looks like this: cargo run --profile=production -- benchmark overhead --chain=polkadot-dev --wasm-execution=compiled --weight-path=runtime/polkadot/constants/src/weights/ ``` -This will overwrite the the +This will overwrite the [block_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/block_weights.rs) and [extrinsic_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/extrinsic_weights.rs) diff --git a/substrate/utils/frame/frame-utilities-cli/Cargo.toml b/substrate/utils/frame/frame-utilities-cli/Cargo.toml deleted file mode 100644 index 3952c9fd219f495270c811f0f849eb4178a96a92..0000000000000000000000000000000000000000 --- a/substrate/utils/frame/frame-utilities-cli/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "substrate-frame-cli" -version = "32.0.0" -authors.workspace = true -edition.workspace = true -license = "Apache-2.0" -homepage = "https://substrate.io" -repository.workspace = true -description = "cli interface for FRAME" -documentation = "https://docs.rs/substrate-frame-cli" -readme = "README.md" - -[lints] -workspace = true - -[dependencies] -clap = { version = "4.5.3", features = ["derive"] } -frame-support = { path = "../../../frame/support" } -frame-system = { path = "../../../frame/system" } -sc-cli = { path = "../../../client/cli" } -sp-core = { path = "../../../primitives/core" } -sp-runtime = { path = "../../../primitives/runtime" } - -[features] -default = [] diff --git a/substrate/utils/frame/frame-utilities-cli/README.md b/substrate/utils/frame/frame-utilities-cli/README.md deleted file mode 100644 index 54467a3ad7704451f4064f8334ea374b8c7f6bca..0000000000000000000000000000000000000000 --- a/substrate/utils/frame/frame-utilities-cli/README.md +++ /dev/null @@ -1,3 +0,0 @@ -frame-system CLI utilities - -License: Apache-2.0 diff --git a/substrate/utils/frame/frame-utilities-cli/src/lib.rs b/substrate/utils/frame/frame-utilities-cli/src/lib.rs deleted file mode 100644 index 97129e36f7e9c04664a793d75d00e8bf8a86a413..0000000000000000000000000000000000000000 --- a/substrate/utils/frame/frame-utilities-cli/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! frame-system CLI utilities - -mod pallet_id; - -pub use pallet_id::PalletIdCmd; diff --git a/substrate/utils/frame/frame-utilities-cli/src/pallet_id.rs b/substrate/utils/frame/frame-utilities-cli/src/pallet_id.rs deleted file mode 100644 index abc0cdb3ff52b355596e4b1cd25c67ee0508d951..0000000000000000000000000000000000000000 --- a/substrate/utils/frame/frame-utilities-cli/src/pallet_id.rs +++ /dev/null @@ -1,88 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Implementation of the `palletid` subcommand - -use clap::Parser; -use frame_support::PalletId; -use sc_cli::{ - utils::print_from_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, - OutputTypeFlag, -}; -use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; -use sp_runtime::traits::AccountIdConversion; - -/// The `palletid` command -#[derive(Debug, Parser)] -#[command(name = "palletid", about = "Inspect a module ID address")] -pub struct PalletIdCmd { - /// The module ID used to derive the account - id: String, - - /// network address format - #[arg( - long, - value_name = "NETWORK", - value_parser = sc_cli::parse_ss58_address_format, - ignore_case = true, - )] - pub network: Option, - - #[allow(missing_docs)] - #[command(flatten)] - pub output_scheme: OutputTypeFlag, - - #[allow(missing_docs)] - #[command(flatten)] - pub crypto_scheme: CryptoSchemeFlag, - - #[allow(missing_docs)] - #[command(flatten)] - pub keystore_params: KeystoreParams, -} - -impl PalletIdCmd { - /// runs the command - pub fn run(&self) -> Result<(), Error> - where - R: frame_system::Config, - R::AccountId: Ss58Codec, - { - if self.id.len() != 8 { - return Err("a module id must be a string of 8 characters".into()) - } - let password = self.keystore_params.read_password()?; - - let id_fixed_array: [u8; 8] = self.id.as_bytes().try_into().map_err(|_| { - "Cannot convert argument to palletid: argument should be 8-character string" - })?; - - let account_id: R::AccountId = PalletId(id_fixed_array).into_account_truncating(); - - with_crypto_scheme!( - self.crypto_scheme.scheme, - print_from_uri( - &account_id.to_ss58check_with_version(unwrap_or_default_ss58_version(self.network)), - password, - self.network, - self.output_scheme.output_type - ) - ); - - Ok(()) - } -} diff --git a/substrate/utils/frame/remote-externalities/Cargo.toml b/substrate/utils/frame/remote-externalities/Cargo.toml index 82b019154832aee4202d60d3a1a2b9015b7b774a..2911d5eef65902af9a0bec6a679a89db9eb6fb7a 100644 --- a/substrate/utils/frame/remote-externalities/Cargo.toml +++ b/substrate/utils/frame/remote-externalities/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] jsonrpsee = { version = "0.22", features = ["http-client"] } -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } log = { workspace = true, default-features = true } serde = { workspace = true, default-features = true } sp-core = { path = "../../../primitives/core" } diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs index 58cb901470c17df20f877ed96930b9be05f7d88d..0ecb98f31343aa050d9daa8f33445e858631813d 100644 --- a/substrate/utils/frame/remote-externalities/src/lib.rs +++ b/substrate/utils/frame/remote-externalities/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::{ }, }; use sp_runtime::{ - traits::{Block as BlockT, Hash, HashingFor}, + traits::{Block as BlockT, HashingFor}, StateVersion, }; use sp_state_machine::TestExternalities; @@ -58,37 +58,39 @@ type ChildKeyValues = Vec<(ChildInfo, Vec)>; type SnapshotVersion = Compact; const LOG_TARGET: &str = "remote-ext"; -const DEFAULT_HTTP_ENDPOINT: &str = "https://rpc.polkadot.io:443"; -const SNAPSHOT_VERSION: SnapshotVersion = Compact(3); +const DEFAULT_HTTP_ENDPOINT: &str = "https://polkadot-try-runtime-node.parity-chains.parity.io:443"; +const SNAPSHOT_VERSION: SnapshotVersion = Compact(4); /// The snapshot that we store on disk. #[derive(Decode, Encode)] -struct Snapshot { +struct Snapshot { snapshot_version: SnapshotVersion, state_version: StateVersion, - block_hash: H, // > raw_storage: Vec<(Vec, (Vec, i32))>, - storage_root: H, + // The storage root of the state. This may vary from the storage root in the header, if not the + // entire state was fetched. + storage_root: B::Hash, + header: B::Header, } -impl Snapshot { +impl Snapshot { pub fn new( state_version: StateVersion, - block_hash: H, raw_storage: Vec<(Vec, (Vec, i32))>, - storage_root: H, + storage_root: B::Hash, + header: B::Header, ) -> Self { Self { snapshot_version: SNAPSHOT_VERSION, state_version, - block_hash, raw_storage, storage_root, + header, } } - fn load(path: &PathBuf) -> Result, &'static str> { + fn load(path: &PathBuf) -> Result, &'static str> { let bytes = fs::read(path).map_err(|_| "fs::read failed.")?; // The first item in the SCALE encoded struct bytes is the snapshot version. We decode and // check that first, before proceeding to decode the rest of the snapshot. @@ -105,21 +107,21 @@ impl Snapshot { /// An externalities that acts exactly the same as [`sp_io::TestExternalities`] but has a few extra /// bits and pieces to it, and can be loaded remotely. -pub struct RemoteExternalities { +pub struct RemoteExternalities { /// The inner externalities. - pub inner_ext: TestExternalities, - /// The block hash with which we created this externality env. - pub block_hash: H::Out, + pub inner_ext: TestExternalities>, + /// The block header which we created this externality env. + pub header: B::Header, } -impl Deref for RemoteExternalities { - type Target = TestExternalities; +impl Deref for RemoteExternalities { + type Target = TestExternalities>; fn deref(&self) -> &Self::Target { &self.inner_ext } } -impl DerefMut for RemoteExternalities { +impl DerefMut for RemoteExternalities { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner_ext } @@ -832,34 +834,55 @@ where ) -> Result, &'static str> { let retry_strategy = FixedInterval::new(Self::KEYS_PAGE_RETRY_INTERVAL).take(Self::MAX_RETRIES); - let get_child_keys_closure = || { - #[allow(deprecated)] - substrate_rpc_client::ChildStateApi::storage_keys( - client, - PrefixedStorageKey::new(prefixed_top_key.as_ref().to_vec()), - child_prefix.clone(), - Some(at), - ) - }; - let child_keys = - Retry::spawn(retry_strategy, get_child_keys_closure).await.map_err(|e| { - error!(target: LOG_TARGET, "Error = {:?}", e); - "rpc child_get_keys failed." - })?; + let mut all_child_keys = Vec::new(); + let mut start_key = None; + + loop { + let get_child_keys_closure = || { + let top_key = PrefixedStorageKey::new(prefixed_top_key.0.clone()); + substrate_rpc_client::ChildStateApi::storage_keys_paged( + client, + top_key, + Some(child_prefix.clone()), + Self::DEFAULT_KEY_DOWNLOAD_PAGE, + start_key.clone(), + Some(at), + ) + }; + + let child_keys = Retry::spawn(retry_strategy.clone(), get_child_keys_closure) + .await + .map_err(|e| { + error!(target: LOG_TARGET, "Error = {:?}", e); + "rpc child_get_keys failed." + })?; + + let keys_count = child_keys.len(); + if keys_count == 0 { + break; + } + + start_key = child_keys.last().cloned(); + all_child_keys.extend(child_keys); + + if keys_count < Self::DEFAULT_KEY_DOWNLOAD_PAGE as usize { + break; + } + } debug!( target: LOG_TARGET, "[thread = {:?}] scraped {} child-keys of the child-bearing top key: {}", std::thread::current().id(), - child_keys.len(), + all_child_keys.len(), HexDisplay::from(prefixed_top_key) ); - Ok(child_keys) + Ok(all_child_keys) } } -impl Builder +impl Builder where B::Hash: DeserializeOwned, B::Header: DeserializeOwned, @@ -1030,6 +1053,21 @@ where Ok(()) } + async fn load_header(&self) -> Result { + let retry_strategy = + FixedInterval::new(Self::KEYS_PAGE_RETRY_INTERVAL).take(Self::MAX_RETRIES); + let get_header_closure = || { + ChainApi::<(), _, B::Header, ()>::header( + self.as_online().rpc_client(), + Some(self.as_online().at_expected()), + ) + }; + Retry::spawn(retry_strategy, get_header_closure) + .await + .map_err(|_| "Failed to fetch header for block from network")? + .ok_or("Network returned None block header") + } + /// Load the data from a remote server. The main code path is calling into `load_top_remote` and /// `load_child_remote`. /// @@ -1058,13 +1096,11 @@ where // If we need to save a snapshot, save the raw storage and root hash to the snapshot. if let Some(path) = self.as_online().state_snapshot.clone().map(|c| c.path) { let (raw_storage, storage_root) = pending_ext.into_raw_snapshot(); - let snapshot = Snapshot::::new( + let snapshot = Snapshot::::new( state_version, - self.as_online() - .at - .expect("set to `Some` in `init_remote_client`; must be called before; qed"), raw_storage.clone(), storage_root, + self.load_header().await?, ); let encoded = snapshot.encode(); log::info!( @@ -1086,22 +1122,21 @@ where Ok(pending_ext) } - async fn do_load_remote(&mut self) -> Result>, &'static str> { + async fn do_load_remote(&mut self) -> Result, &'static str> { self.init_remote_client().await?; - let block_hash = self.as_online().at_expected(); let inner_ext = self.load_remote_and_maybe_save().await?; - Ok(RemoteExternalities { block_hash, inner_ext }) + Ok(RemoteExternalities { header: self.load_header().await?, inner_ext }) } fn do_load_offline( &mut self, config: OfflineConfig, - ) -> Result>, &'static str> { + ) -> Result, &'static str> { let mut sp = Spinner::with_timer(Spinners::Dots, "Loading snapshot...".into()); let start = Instant::now(); info!(target: LOG_TARGET, "Loading snapshot from {:?}", &config.state_snapshot.path); - let Snapshot { snapshot_version: _, block_hash, state_version, raw_storage, storage_root } = - Snapshot::::load(&config.state_snapshot.path)?; + let Snapshot { snapshot_version: _, header, state_version, raw_storage, storage_root } = + Snapshot::::load(&config.state_snapshot.path)?; let inner_ext = TestExternalities::from_raw_snapshot( raw_storage, @@ -1110,12 +1145,10 @@ where ); sp.stop_with_message(format!("✅ Loaded snapshot ({:.2}s)", start.elapsed().as_secs_f32())); - Ok(RemoteExternalities { inner_ext, block_hash }) + Ok(RemoteExternalities { inner_ext, header }) } - pub(crate) async fn pre_build( - mut self, - ) -> Result>, &'static str> { + pub(crate) async fn pre_build(mut self) -> Result, &'static str> { let mut ext = match self.mode.clone() { Mode::Offline(config) => self.do_load_offline(config)?, Mode::Online(_) => self.do_load_remote().await?, @@ -1154,7 +1187,7 @@ where } // Public methods -impl Builder +impl Builder where B::Hash: DeserializeOwned, B::Header: DeserializeOwned, @@ -1191,7 +1224,7 @@ where self } - pub async fn build(self) -> Result>, &'static str> { + pub async fn build(self) -> Result, &'static str> { let mut ext = self.pre_build().await?; ext.commit_all().unwrap(); @@ -1226,7 +1259,7 @@ mod tests { init_logger(); Builder::::new() .mode(Mode::Offline(OfflineConfig { - state_snapshot: SnapshotConfig::new("test_data/proxy_test"), + state_snapshot: SnapshotConfig::new("test_data/test.snap"), })) .build() .await @@ -1241,7 +1274,7 @@ mod tests { // get the first key from the snapshot file. let some_key = Builder::::new() .mode(Mode::Offline(OfflineConfig { - state_snapshot: SnapshotConfig::new("test_data/proxy_test"), + state_snapshot: SnapshotConfig::new("test_data/test.snap"), })) .build() .await @@ -1255,7 +1288,7 @@ mod tests { Builder::::new() .mode(Mode::Offline(OfflineConfig { - state_snapshot: SnapshotConfig::new("test_data/proxy_test"), + state_snapshot: SnapshotConfig::new("test_data/test.snap"), })) .blacklist_hashed_key(&some_key) .build() @@ -1341,7 +1374,7 @@ mod remote_tests { .await .unwrap(); - assert_eq!(ext.block_hash, cached_ext.block_hash); + assert_eq!(ext.header.hash(), cached_ext.header.hash()); } #[tokio::test] diff --git a/substrate/utils/frame/remote-externalities/test_data/proxy_test b/substrate/utils/frame/remote-externalities/test_data/proxy_test deleted file mode 100644 index f0b1b4f5af40bc8a159c9ee250bee7849cababae..0000000000000000000000000000000000000000 Binary files a/substrate/utils/frame/remote-externalities/test_data/proxy_test and /dev/null differ diff --git a/substrate/utils/frame/remote-externalities/test_data/test.snap b/substrate/utils/frame/remote-externalities/test_data/test.snap new file mode 100644 index 0000000000000000000000000000000000000000..28f2012d0f2a1b6a63ee8825deaf70257625279a Binary files /dev/null and b/substrate/utils/frame/remote-externalities/test_data/test.snap differ diff --git a/substrate/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml b/substrate/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml index 98a87b7d5b200f632cf599dd7fa741f3a804dd0b..ee3bf5eb68d716548a4a738f80254cfe811c651f 100644 --- a/substrate/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml +++ b/substrate/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } serde = { features = ["derive"], workspace = true, default-features = true } sp-core = { path = "../../../../primitives/core" } @@ -24,7 +24,7 @@ sp-state-machine = { path = "../../../../primitives/state-machine" } sp-trie = { path = "../../../../primitives/trie" } trie-db = "0.29.0" -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } # Substrate Dependencies sc-client-api = { path = "../../../../client/api" } diff --git a/substrate/utils/frame/rpc/support/Cargo.toml b/substrate/utils/frame/rpc/support/Cargo.toml index 84db06da7b0d26fa52f066dc7ef9f6d879bcc34c..bf566f909ecb712d8b00a26717739243adb06129 100644 --- a/substrate/utils/frame/rpc/support/Cargo.toml +++ b/substrate/utils/frame/rpc/support/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } +codec = { package = "parity-scale-codec", version = "3.6.12" } jsonrpsee = { version = "0.22", features = ["jsonrpsee-types"] } serde = { workspace = true, default-features = true } frame-support = { path = "../../../../frame/support" } diff --git a/substrate/utils/frame/rpc/system/Cargo.toml b/substrate/utils/frame/rpc/system/Cargo.toml index 9e571bef9d04fd6025990755a2ecae79e180f335..6829d753ed71327dea8ad4e65d91af67c14285f1 100644 --- a/substrate/utils/frame/rpc/system/Cargo.toml +++ b/substrate/utils/frame/rpc/system/Cargo.toml @@ -16,8 +16,8 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.22", features = ["client-core", "macros", "server"] } +codec = { package = "parity-scale-codec", version = "3.6.12" } +jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } futures = "0.3.30" log = { workspace = true, default-features = true } frame-system-rpc-runtime-api = { path = "../../../../frame/system/rpc/runtime-api" } diff --git a/substrate/utils/wasm-builder/Cargo.toml b/substrate/utils/wasm-builder/Cargo.toml index bac323e2e6a0905cf1d956589235c196ef2881a4..090955494f0a7572a08407c2aed26919863b3837 100644 --- a/substrate/utils/wasm-builder/Cargo.toml +++ b/substrate/utils/wasm-builder/Cargo.toml @@ -27,3 +27,34 @@ filetime = "0.2.16" wasm-opt = "0.116" parity-wasm = "0.45" polkavm-linker = { workspace = true } + +# Dependencies required for the `metadata-hash` feature. +merkleized-metadata = { version = "0.1.0", optional = true } +sc-executor = { path = "../../client/executor", optional = true } +sp-core = { path = "../../primitives/core", optional = true } +sp-io = { path = "../../primitives/io", optional = true } +sp-version = { path = "../../primitives/version", optional = true } +frame-metadata = { version = "16.0.0", features = ["current"], optional = true } +codec = { package = "parity-scale-codec", version = "3.1.5", optional = true } +array-bytes = { version = "6.1", optional = true } +sp-tracing = { path = "../../primitives/tracing", optional = true } + +[features] +# Enable support for generating the metadata hash. +# +# To generate the metadata hash the runtime is build once, executed to build the metadata and then +# build a second time with the `RUNTIME_METADATA_HASH` environment variable set. The environment +# variable then contains the hash and can be used inside the runtime. +# +# This pulls in quite a lot of dependencies and thus, is disabled by default. +metadata-hash = [ + "array-bytes", + "codec", + "frame-metadata", + "merkleized-metadata", + "sc-executor", + "sp-core", + "sp-io", + "sp-tracing", + "sp-version", +] diff --git a/substrate/utils/wasm-builder/src/builder.rs b/substrate/utils/wasm-builder/src/builder.rs index 163703fbec628327c0ba3dc0683972285af71e30..37c6c4aa74319321122dabb6d3da7295d753732e 100644 --- a/substrate/utils/wasm-builder/src/builder.rs +++ b/substrate/utils/wasm-builder/src/builder.rs @@ -23,6 +23,13 @@ use std::{ use crate::RuntimeTarget; +/// Extra information when generating the `metadata-hash`. +#[cfg(feature = "metadata-hash")] +pub(crate) struct MetadataExtraInfo { + pub decimals: u8, + pub token_symbol: String, +} + /// Returns the manifest dir from the `CARGO_MANIFEST_DIR` env. fn get_manifest_dir() -> PathBuf { env::var("CARGO_MANIFEST_DIR") @@ -53,6 +60,8 @@ impl WasmBuilderSelectProject { disable_runtime_version_section_check: false, export_heap_base: false, import_memory: false, + #[cfg(feature = "metadata-hash")] + enable_metadata_hash: None, } } @@ -71,6 +80,8 @@ impl WasmBuilderSelectProject { disable_runtime_version_section_check: false, export_heap_base: false, import_memory: false, + #[cfg(feature = "metadata-hash")] + enable_metadata_hash: None, }) } else { Err("Project path must point to the `Cargo.toml` of the project") @@ -108,6 +119,10 @@ pub struct WasmBuilder { export_heap_base: bool, /// Whether `--import-memory` should be added to the link args (WASM-only). import_memory: bool, + + /// Whether to enable the metadata hash generation. + #[cfg(feature = "metadata-hash")] + enable_metadata_hash: Option, } impl WasmBuilder { @@ -191,6 +206,22 @@ impl WasmBuilder { self } + /// Enable generation of the metadata hash. + /// + /// This will compile the runtime once, fetch the metadata, build the metadata hash and + /// then compile again with the env `RUNTIME_METADATA_HASH` set. For more information + /// about the metadata hash see [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html). + /// + /// - `token_symbol`: The symbol of the main native token of the chain. + /// - `decimals`: The number of decimals of the main native token. + #[cfg(feature = "metadata-hash")] + pub fn enable_metadata_hash(mut self, token_symbol: impl Into, decimals: u8) -> Self { + self.enable_metadata_hash = + Some(MetadataExtraInfo { token_symbol: token_symbol.into(), decimals }); + + self + } + /// Disable the check for the `runtime_version` wasm section. /// /// By default the `wasm-builder` will ensure that the `runtime_version` section will @@ -237,6 +268,8 @@ impl WasmBuilder { self.features_to_enable, self.file_name, !self.disable_runtime_version_section_check, + #[cfg(feature = "metadata-hash")] + self.enable_metadata_hash, ); // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't @@ -311,6 +344,7 @@ fn build_project( features_to_enable: Vec, wasm_binary_name: Option, check_for_runtime_version_section: bool, + #[cfg(feature = "metadata-hash")] enable_metadata_hash: Option, ) { let cargo_cmd = match crate::prerequisites::check(target) { Ok(cmd) => cmd, @@ -328,6 +362,8 @@ fn build_project( features_to_enable, wasm_binary_name, check_for_runtime_version_section, + #[cfg(feature = "metadata-hash")] + enable_metadata_hash, ); let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary { diff --git a/substrate/utils/wasm-builder/src/lib.rs b/substrate/utils/wasm-builder/src/lib.rs index 9ebab38b9cb2f727594e310f1e6d27c221f528dc..07de4c15831b842e6ac559ebf445901744d7d98f 100644 --- a/substrate/utils/wasm-builder/src/lib.rs +++ b/substrate/utils/wasm-builder/src/lib.rs @@ -116,6 +116,8 @@ use std::{ use version::Version; mod builder; +#[cfg(feature = "metadata-hash")] +mod metadata_hash; mod prerequisites; mod version; mod wasm_project; @@ -238,7 +240,7 @@ fn get_rustup_command(target: RuntimeTarget) -> Option { } /// Wraps a specific command which represents a cargo invocation. -#[derive(Debug)] +#[derive(Debug, Clone)] struct CargoCommand { program: String, args: Vec, @@ -350,6 +352,7 @@ impl CargoCommand { } /// Wraps a [`CargoCommand`] and the version of `rustc` the cargo command uses. +#[derive(Clone)] struct CargoCommandVersioned { command: CargoCommand, version: String, diff --git a/substrate/utils/wasm-builder/src/metadata_hash.rs b/substrate/utils/wasm-builder/src/metadata_hash.rs new file mode 100644 index 0000000000000000000000000000000000000000..1003f2d18eafdab2c619f260c10ba5e30e0d589b --- /dev/null +++ b/substrate/utils/wasm-builder/src/metadata_hash.rs @@ -0,0 +1,132 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::builder::MetadataExtraInfo; +use codec::{Decode, Encode}; +use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; +use merkleized_metadata::{generate_metadata_digest, ExtraInfo}; +use sc_executor::WasmExecutor; +use sp_core::traits::{CallContext, CodeExecutor, RuntimeCode, WrappedRuntimeCode}; +use std::path::Path; + +/// The host functions that we provide when calling into the wasm file. +/// +/// Any other host function will return an error. +type HostFunctions = ( + // The allocator functions. + sp_io::allocator::HostFunctions, + // Logging is good to have for debugging issues. + sp_io::logging::HostFunctions, + // Give access to the "state", actually the state will be empty, but some chains put constants + // into the state and this would panic at metadata generation. Thus, we give them an empty + // state to not panic. + sp_io::storage::HostFunctions, + // The hashing functions. + sp_io::hashing::HostFunctions, +); + +/// Generate the metadata hash. +/// +/// The metadata hash is generated as specced in +/// [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html). +/// +/// Returns the metadata hash. +pub fn generate_metadata_hash(wasm: &Path, extra_info: MetadataExtraInfo) -> [u8; 32] { + sp_tracing::try_init_simple(); + + let wasm = std::fs::read(wasm).expect("Wasm file was just created and should be readable."); + + let executor = WasmExecutor::::builder() + .with_allow_missing_host_functions(true) + .build(); + + let runtime_code = RuntimeCode { + code_fetcher: &WrappedRuntimeCode(wasm.into()), + heap_pages: None, + // The hash is only used for caching and thus, not that important for our use case here. + hash: vec![1, 2, 3], + }; + + let metadata = executor + .call( + &mut sp_io::TestExternalities::default().ext(), + &runtime_code, + "Metadata_metadata_at_version", + &15u32.encode(), + CallContext::Offchain, + ) + .0 + .expect("`Metadata::metadata_at_version` should exist."); + + let metadata = Option::>::decode(&mut &metadata[..]) + .ok() + .flatten() + .expect("Metadata V15 support is required."); + + let metadata = RuntimeMetadataPrefixed::decode(&mut &metadata[..]) + .expect("Invalid encoded metadata?") + .1; + + let runtime_version = executor + .call( + &mut sp_io::TestExternalities::default().ext(), + &runtime_code, + "Core_version", + &[], + CallContext::Offchain, + ) + .0 + .expect("`Core_version` should exist."); + let runtime_version = sp_version::RuntimeVersion::decode(&mut &runtime_version[..]) + .expect("Invalid `RuntimeVersion` encoding"); + + let base58_prefix = extract_ss58_prefix(&metadata); + + let extra_info = ExtraInfo { + spec_version: runtime_version.spec_version, + spec_name: runtime_version.spec_name.into(), + base58_prefix, + decimals: extra_info.decimals, + token_symbol: extra_info.token_symbol, + }; + + generate_metadata_digest(&metadata, extra_info) + .expect("Failed to generate the metadata digest") + .hash() +} + +/// Extract the `SS58` from the constants in the given `metadata`. +fn extract_ss58_prefix(metadata: &RuntimeMetadata) -> u16 { + let RuntimeMetadata::V15(ref metadata) = metadata else { + panic!("Metadata version 15 required") + }; + + let system = metadata + .pallets + .iter() + .find(|p| p.name == "System") + .expect("Each FRAME runtime has the `System` pallet; qed"); + + system + .constants + .iter() + .find_map(|c| { + (c.name == "SS58Prefix") + .then(|| u16::decode(&mut &c.value[..]).expect("SS58 is an `u16`; qed")) + }) + .expect("`SS58PREFIX` exists in the `System` constants; qed") +} diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs index b58e6bfa36b478b91995789a148b042d167d9f3f..ff6c8e38a332121d6e4c7fcdfa6fe4128867ac5a 100644 --- a/substrate/utils/wasm-builder/src/wasm_project.rs +++ b/substrate/utils/wasm-builder/src/wasm_project.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "metadata-hash")] +use crate::builder::MetadataExtraInfo; use crate::{write_file_if_changed, CargoCommandVersioned, RuntimeTarget, OFFLINE}; use build_helper::rerun_if_changed; @@ -113,57 +115,103 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata { /// The path to the compact runtime binary and the bloaty runtime binary. pub(crate) fn create_and_compile( target: RuntimeTarget, - project_cargo_toml: &Path, + orig_project_cargo_toml: &Path, default_rustflags: &str, cargo_cmd: CargoCommandVersioned, features_to_enable: Vec, - bloaty_blob_out_name_override: Option, + blob_out_name_override: Option, check_for_runtime_version_section: bool, + #[cfg(feature = "metadata-hash")] enable_metadata_hash: Option, ) -> (Option, WasmBinaryBloaty) { let runtime_workspace_root = get_wasm_workspace_root(); let runtime_workspace = runtime_workspace_root.join(target.build_subdirectory()); - let crate_metadata = crate_metadata(project_cargo_toml); + let crate_metadata = crate_metadata(orig_project_cargo_toml); let project = create_project( target, - project_cargo_toml, + orig_project_cargo_toml, &runtime_workspace, &crate_metadata, crate_metadata.workspace_root.as_ref(), features_to_enable, ); + let wasm_project_cargo_toml = project.join("Cargo.toml"); let build_config = BuildConfiguration::detect(target, &project); - // Build the bloaty runtime blob - let raw_blob_path = build_bloaty_blob( - target, - &build_config.blob_build_profile, - &project, - default_rustflags, - cargo_cmd, - ); + #[cfg(feature = "metadata-hash")] + let raw_blob_path = match enable_metadata_hash { + Some(extra_info) => { + // When the metadata hash is enabled we need to build the runtime twice. + let raw_blob_path = build_bloaty_blob( + target, + &build_config.blob_build_profile, + &project, + default_rustflags, + cargo_cmd.clone(), + None, + ); - let (final_blob_binary, bloaty_blob_binary) = match target { - RuntimeTarget::Wasm => compile_wasm( - project_cargo_toml, + let hash = crate::metadata_hash::generate_metadata_hash(&raw_blob_path, extra_info); + + build_bloaty_blob( + target, + &build_config.blob_build_profile, + &project, + default_rustflags, + cargo_cmd, + Some(hash), + ) + }, + None => build_bloaty_blob( + target, + &build_config.blob_build_profile, &project, - bloaty_blob_out_name_override, - check_for_runtime_version_section, - &build_config, + default_rustflags, + cargo_cmd, + None, ), + }; + + // If the feature is not enabled, we only need to do it once. + #[cfg(not(feature = "metadata-hash"))] + let raw_blob_path = { + build_bloaty_blob( + target, + &build_config.blob_build_profile, + &project, + default_rustflags, + cargo_cmd, + ) + }; + + let blob_name = + blob_out_name_override.unwrap_or_else(|| get_blob_name(target, &wasm_project_cargo_toml)); + + let (final_blob_binary, bloaty_blob_binary) = match target { + RuntimeTarget::Wasm => { + let out_path = project.join(format!("{blob_name}.wasm")); + fs::copy(raw_blob_path, &out_path).expect("copying the runtime blob should never fail"); + + maybe_compact_and_compress_wasm( + &wasm_project_cargo_toml, + &project, + WasmBinaryBloaty(out_path), + &blob_name, + check_for_runtime_version_section, + &build_config, + ) + }, RuntimeTarget::Riscv => { - let out_name = bloaty_blob_out_name_override - .unwrap_or_else(|| get_blob_name(target, project_cargo_toml)); - let out_path = project.join(format!("{out_name}.polkavm")); + let out_path = project.join(format!("{blob_name}.polkavm")); fs::copy(raw_blob_path, &out_path).expect("copying the runtime blob should never fail"); (None, WasmBinaryBloaty(out_path)) }, }; generate_rerun_if_changed_instructions( - project_cargo_toml, + orig_project_cargo_toml, &project, &runtime_workspace, final_blob_binary.as_ref(), @@ -177,25 +225,14 @@ pub(crate) fn create_and_compile( (final_blob_binary, bloaty_blob_binary) } -fn compile_wasm( - project_cargo_toml: &Path, +fn maybe_compact_and_compress_wasm( + wasm_project_cargo_toml: &Path, project: &Path, - bloaty_blob_out_name_override: Option, + bloaty_blob_binary: WasmBinaryBloaty, + blob_name: &str, check_for_runtime_version_section: bool, build_config: &BuildConfiguration, ) -> (Option, WasmBinaryBloaty) { - // Get the name of the bloaty runtime blob. - let bloaty_blob_default_name = get_blob_name(RuntimeTarget::Wasm, project_cargo_toml); - let bloaty_blob_out_name = - bloaty_blob_out_name_override.unwrap_or_else(|| bloaty_blob_default_name.clone()); - - let bloaty_blob_binary = copy_bloaty_blob( - &project, - &build_config.blob_build_profile, - &bloaty_blob_default_name, - &bloaty_blob_out_name, - ); - // Try to compact and compress the bloaty blob, if the *outer* profile wants it. // // This is because, by default the inner profile will be set to `Release` even when the outer @@ -203,15 +240,9 @@ fn compile_wasm( // development activities. let (compact_blob_path, compact_compressed_blob_path) = if build_config.outer_build_profile.wants_compact() { - let compact_blob_path = compact_wasm( - &project, - &build_config.blob_build_profile, - project_cargo_toml, - &bloaty_blob_out_name, - ); - let compact_compressed_blob_path = compact_blob_path - .as_ref() - .and_then(|p| try_compress_blob(&p.0, &bloaty_blob_out_name)); + let compact_blob_path = compact_wasm(&project, blob_name, &bloaty_blob_binary); + let compact_compressed_blob_path = + compact_blob_path.as_ref().and_then(|p| try_compress_blob(&p.0, blob_name)); (compact_blob_path, compact_compressed_blob_path) } else { (None, None) @@ -221,15 +252,12 @@ fn compile_wasm( ensure_runtime_version_wasm_section_exists(bloaty_blob_binary.bloaty_path()); } - compact_blob_path - .as_ref() - .map(|wasm_binary| copy_blob_to_target_directory(project_cargo_toml, wasm_binary)); + let final_blob_binary = compact_compressed_blob_path.or(compact_blob_path); - compact_compressed_blob_path.as_ref().map(|wasm_binary_compressed| { - copy_blob_to_target_directory(project_cargo_toml, wasm_binary_compressed) - }); + final_blob_binary + .as_ref() + .map(|binary| copy_blob_to_target_directory(wasm_project_cargo_toml, binary)); - let final_blob_binary = compact_compressed_blob_path.or(compact_blob_path); (final_blob_binary, bloaty_blob_binary) } @@ -347,12 +375,25 @@ fn get_crate_name(cargo_manifest: &Path) -> String { .expect("Package name exists; qed") } +/// Extract the `lib.name` from the given `Cargo.toml`. +fn get_lib_name(cargo_manifest: &Path) -> Option { + let cargo_toml: Table = toml::from_str( + &fs::read_to_string(cargo_manifest).expect("File exists as checked before; qed"), + ) + .expect("Cargo manifest is a valid toml file; qed"); + + let lib = cargo_toml.get("lib").and_then(|t| t.as_table())?; + + lib.get("name").and_then(|p| p.as_str()).map(ToOwned::to_owned) +} + /// Returns the name for the blob binary. fn get_blob_name(target: RuntimeTarget, cargo_manifest: &Path) -> String { - let crate_name = get_crate_name(cargo_manifest); match target { - RuntimeTarget::Wasm => crate_name.replace('-', "_"), - RuntimeTarget::Riscv => crate_name, + RuntimeTarget::Wasm => get_lib_name(cargo_manifest) + .expect("The wasm project should have a `lib.name`; qed") + .replace('-', "_"), + RuntimeTarget::Riscv => get_crate_name(cargo_manifest), } } @@ -379,7 +420,6 @@ fn create_project_cargo_toml( workspace_root_path: &Path, crate_name: &str, crate_path: &Path, - wasm_binary: &str, enabled_features: impl Iterator, ) { let mut workspace_toml: Table = toml::from_str( @@ -443,7 +483,7 @@ fn create_project_cargo_toml( if target == RuntimeTarget::Wasm { let mut lib = Table::new(); - lib.insert("name".into(), wasm_binary.into()); + lib.insert("name".into(), crate_name.replace("-", "_").into()); lib.insert("crate-type".into(), vec!["cdylib".to_string()].into()); wasm_workspace_toml.insert("lib".into(), lib.into()); } @@ -588,7 +628,6 @@ fn create_project( ) -> PathBuf { let crate_name = get_crate_name(project_cargo_toml); let crate_path = project_cargo_toml.parent().expect("Parent path exists; qed"); - let wasm_binary = get_blob_name(target, project_cargo_toml); let wasm_project_folder = wasm_workspace.join(&crate_name); fs::create_dir_all(wasm_project_folder.join("src")) @@ -610,7 +649,6 @@ fn create_project( workspace_root_path, &crate_name, crate_path, - &wasm_binary, enabled_features.into_iter(), ); @@ -775,12 +813,15 @@ fn offline_build() -> bool { } /// Build the project and create the bloaty runtime blob. +/// +/// Returns the path to the generated bloaty runtime blob. fn build_bloaty_blob( target: RuntimeTarget, blob_build_profile: &Profile, project: &Path, default_rustflags: &str, cargo_cmd: CargoCommandVersioned, + #[cfg(feature = "metadata-hash")] metadata_hash: Option<[u8; 32]>, ) -> PathBuf { let manifest_path = project.join("Cargo.toml"); let mut build_cmd = cargo_cmd.command(); @@ -820,6 +861,11 @@ fn build_bloaty_blob( // We don't want to call ourselves recursively .env(crate::SKIP_BUILD_ENV, ""); + #[cfg(feature = "metadata-hash")] + if let Some(hash) = metadata_hash { + build_cmd.env("RUNTIME_METADATA_HASH", array_bytes::bytes2hex("0x", &hash)); + } + if super::color_output_enabled() { build_cmd.arg("--color=always"); } @@ -908,23 +954,16 @@ fn build_bloaty_blob( fn compact_wasm( project: &Path, - inner_profile: &Profile, - cargo_manifest: &Path, - out_name: &str, + blob_name: &str, + bloaty_binary: &WasmBinaryBloaty, ) -> Option { - let default_out_name = get_blob_name(RuntimeTarget::Wasm, cargo_manifest); - let in_path = project - .join("target/wasm32-unknown-unknown") - .join(inner_profile.directory()) - .join(format!("{}.wasm", default_out_name)); - - let wasm_compact_path = project.join(format!("{}.compact.wasm", out_name)); + let wasm_compact_path = project.join(format!("{blob_name}.compact.wasm")); let start = std::time::Instant::now(); wasm_opt::OptimizationOptions::new_opt_level_0() .mvp_features_only() .debug_info(true) .add_pass(wasm_opt::Pass::StripDwarf) - .run(&in_path, &wasm_compact_path) + .run(bloaty_binary.bloaty_path(), &wasm_compact_path) .expect("Failed to compact generated WASM binary."); println!( "{} {}", @@ -934,22 +973,6 @@ fn compact_wasm( Some(WasmBinary(wasm_compact_path)) } -fn copy_bloaty_blob( - project: &Path, - inner_profile: &Profile, - in_name: &str, - out_name: &str, -) -> WasmBinaryBloaty { - let in_path = project - .join("target/wasm32-unknown-unknown") - .join(inner_profile.directory()) - .join(format!("{}.wasm", in_name)); - - let bloaty_path = project.join(format!("{}.wasm", out_name)); - fs::copy(in_path, &bloaty_path).expect("Copying the bloaty file to the project dir."); - WasmBinaryBloaty(bloaty_path) -} - fn try_compress_blob(compact_blob_path: &Path, out_name: &str) -> Option { use sp_maybe_compressed_blob::CODE_BLOB_BOMB_LIMIT; diff --git a/templates/minimal/Cargo.toml b/templates/minimal/Cargo.toml index 6cd28c5a49364a911c9b93fa1269456cf07527d5..95656ff92d244602930d1e4438fde1138b37c5d5 100644 --- a/templates/minimal/Cargo.toml +++ b/templates/minimal/Cargo.toml @@ -9,9 +9,6 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [dependencies] minimal-template-node = { path = "./node" } minimal-template-runtime = { path = "./runtime" } diff --git a/templates/minimal/node/Cargo.toml b/templates/minimal/node/Cargo.toml index 606fd05803562abe7dc85b35c6a4c0b7c15a320c..f732eff445c309ad234b0ba18eef2b137a808b6b 100644 --- a/templates/minimal/node/Cargo.toml +++ b/templates/minimal/node/Cargo.toml @@ -10,9 +10,6 @@ edition.workspace = true publish = false build = "build.rs" -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/templates/minimal/node/src/chain_spec.rs b/templates/minimal/node/src/chain_spec.rs index 6b721deb6d1df402d811ba40cd6c848c01a83754..7a3475bb167334e05f570ad4b46e8d471ec5a9a8 100644 --- a/templates/minimal/node/src/chain_spec.rs +++ b/templates/minimal/node/src/chain_spec.rs @@ -21,7 +21,7 @@ use serde_json::{json, Value}; use sp_keyring::AccountKeyring; /// This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec<()>; +pub type ChainSpec = sc_service::GenericChainSpec; fn props() -> Properties { let mut properties = Properties::new(); diff --git a/templates/minimal/node/src/cli.rs b/templates/minimal/node/src/cli.rs index e464fa7d6caa36ce41b45ae79a3883713ef50aca..22726b7eb9a36c0254c2f8423086e5206b730570 100644 --- a/templates/minimal/node/src/cli.rs +++ b/templates/minimal/node/src/cli.rs @@ -32,7 +32,7 @@ impl std::str::FromStr for Consensus { } else if let Some(block_time) = s.strip_prefix("manual-seal-") { Consensus::ManualSeal(block_time.parse().map_err(|_| "invalid block time")?) } else { - return Err("incorrect consensus identifier".into()) + return Err("incorrect consensus identifier".into()); }) } } diff --git a/templates/minimal/node/src/service.rs b/templates/minimal/node/src/service.rs index d84df95dc1924edf8077783aed4f2ce80a803f14..5a92627621bfcba71667ed198786a8f5e5aa9b5a 100644 --- a/templates/minimal/node/src/service.rs +++ b/templates/minimal/node/src/service.rs @@ -61,7 +61,7 @@ pub fn new_partial(config: &Configuration) -> Result { }) .transpose()?; - let executor = sc_service::new_wasm_executor(&config); + let executor = sc_service::new_wasm_executor(config); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( diff --git a/templates/minimal/pallets/template/Cargo.toml b/templates/minimal/pallets/template/Cargo.toml index 909ba03445483e53fe108a096256d0df5d1cdc40..30962664481aecdd6f5d57b7ee4e89133e45f76d 100644 --- a/templates/minimal/pallets/template/Cargo.toml +++ b/templates/minimal/pallets/template/Cargo.toml @@ -9,14 +9,11 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", features = [ "derive", ], default-features = false } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/templates/minimal/runtime/Cargo.toml b/templates/minimal/runtime/Cargo.toml index ceac8a49853369a6a882e32f13cc4728aa3c29ad..3581ca7c851ee75d4bc316fdc48fc4ee59e47f3f 100644 --- a/templates/minimal/runtime/Cargo.toml +++ b/templates/minimal/runtime/Cargo.toml @@ -9,11 +9,8 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false } +parity-scale-codec = { version = "3.6.12", default-features = false } scale-info = { version = "2.6.0", default-features = false } # this is a frame-based runtime, thus importing `frame` with runtime feature enabled. diff --git a/templates/parachain/node/Cargo.toml b/templates/parachain/node/Cargo.toml index 63267acdbca83fb7035b51bd100a1fd13ee2d8e7..4fe228f71fe2dc270f0a1eafed8e6035f96e1b23 100644 --- a/templates/parachain/node/Cargo.toml +++ b/templates/parachain/node/Cargo.toml @@ -10,20 +10,18 @@ edition.workspace = true publish = false build = "build.rs" -[lints] -workspace = true - # [[bin]] # name = "parachain-template-node" [dependencies] clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.6.12" } serde = { features = ["derive"], workspace = true, default-features = true } jsonrpsee = { version = "0.22", features = ["server"] } futures = "0.3.28" serde_json = { workspace = true, default-features = true } +docify = "0.2.8" # Local parachain-template-runtime = { path = "../runtime" } diff --git a/templates/parachain/node/src/chain_spec.rs b/templates/parachain/node/src/chain_spec.rs index 16c91865cdb4aa9ae3c5882652100f5ef56a988c..3fa91c0261622cd71dbf2b473eb70748f3a29b96 100644 --- a/templates/parachain/node/src/chain_spec.rs +++ b/templates/parachain/node/src/chain_spec.rs @@ -8,7 +8,7 @@ use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. -pub type ChainSpec = sc_service::GenericChainSpec<(), Extensions>; +pub type ChainSpec = sc_service::GenericChainSpec; /// The default XCM version to set in genesis config. const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; @@ -22,11 +22,12 @@ pub fn get_from_seed(seed: &str) -> ::Pu /// The extensions for the [`ChainSpec`]. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] -#[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. + #[serde(alias = "relayChain", alias = "RelayChain")] pub relay_chain: String, /// The id of the Parachain. + #[serde(alias = "paraId", alias = "ParaId")] pub para_id: u32, } diff --git a/templates/parachain/node/src/cli.rs b/templates/parachain/node/src/cli.rs index cffbfbc1db23f8b28d234e78f781977d7face5ab..f008e856d99b8ba4dceac5835681920713d2d3f9 100644 --- a/templates/parachain/node/src/cli.rs +++ b/templates/parachain/node/src/cli.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; /// Sub-commands supported by the collator. +#[allow(clippy::large_enum_variant)] #[derive(Debug, clap::Subcommand)] pub enum Subcommand { /// Build a chain specification. diff --git a/templates/parachain/node/src/command.rs b/templates/parachain/node/src/command.rs index 56ae022cad2b22757af87cef08d179433e9db509..eba7fdcdae7185186f2ec12f27efec5b1fca720b 100644 --- a/templates/parachain/node/src/command.rs +++ b/templates/parachain/node/src/command.rs @@ -194,13 +194,11 @@ pub fn run() -> Result<()> { cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => - return Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ + BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." - .into(), - ) - .into()), + .into(), + )), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; diff --git a/templates/parachain/node/src/service.rs b/templates/parachain/node/src/service.rs index 0b1b6259c72de1485a2422c386b897fd9033355a..8ca94895406c951d6d41baaf8dc4e9759d23dffa 100644 --- a/templates/parachain/node/src/service.rs +++ b/templates/parachain/node/src/service.rs @@ -12,6 +12,7 @@ use parachain_template_runtime::{ // Cumulus Imports use cumulus_client_collator::service::CollatorService; +use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams}; use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport; use cumulus_client_consensus_proposer::Proposer; use cumulus_client_service::{ @@ -19,7 +20,10 @@ use cumulus_client_service::{ BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, ParachainHostFunctions, StartRelayChainTasksParams, }; -use cumulus_primitives_core::{relay_chain::CollatorPair, ParaId}; +use cumulus_primitives_core::{ + relay_chain::{CollatorPair, ValidationCode}, + ParaId, +}; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; // Substrate Imports @@ -34,6 +38,7 @@ use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_keystore::KeystorePtr; use substrate_prometheus_endpoint::Registry; +#[docify::export(wasm_executor)] type ParachainExecutor = WasmExecutor; type ParachainClient = TFullClient; @@ -56,6 +61,7 @@ pub type Service = PartialComponents< /// /// 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. +#[docify::export(component_instantiation)] pub fn new_partial(config: &Configuration) -> Result { let telemetry = config .telemetry_endpoints @@ -153,8 +159,10 @@ fn build_import_queue( ) } +#[allow(clippy::too_many_arguments)] fn start_consensus( client: Arc, + backend: Arc, block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, telemetry: Option, @@ -168,10 +176,6 @@ fn start_consensus( overseer_handle: OverseerHandle, announce_block: Arc>) + Send + Sync>, ) -> Result<(), sc_service::Error> { - use cumulus_client_consensus_aura::collators::basic::{ - self as basic_aura, Params as BasicAuraParams, - }; - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( task_manager.spawn_handle(), client.clone(), @@ -189,11 +193,16 @@ fn start_consensus( client.clone(), ); - let params = BasicAuraParams { + let params = AuraParams { create_inherent_data_providers: move |_, ()| async move { Ok(()) }, block_import, - para_client: client, + para_client: client.clone(), + para_backend: backend, relay_client: relay_chain_interface, + code_hash_provider: move |block_hash| { + client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) + }, + sync_oracle, keystore, collator_key, para_id, @@ -201,14 +210,13 @@ fn start_consensus( relay_chain_slot_duration, proposer, collator_service, - // Very limited proposal time. - authoring_duration: Duration::from_millis(500), - collation_request_receiver: None, + authoring_duration: Duration::from_millis(2000), + reinitialize: false, }; - - let fut = basic_aura::run::( - params, - ); + let fut = + aura::run::( + params, + ); task_manager.spawn_essential_handle().spawn("aura", None, fut); Ok(()) @@ -314,8 +322,8 @@ pub async fn start_parachain_node( task_manager: &mut task_manager, config: parachain_config, keystore: params.keystore_container.keystore(), - backend, - network: network.clone(), + backend: backend.clone(), + network, sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, @@ -382,7 +390,7 @@ pub async fn start_parachain_node( prometheus_registry.as_ref(), telemetry.as_ref().map(|t| t.handle()), &task_manager, - relay_chain_interface.clone(), + relay_chain_interface, transaction_pool, params.keystore_container.keystore(), relay_chain_slot_duration, diff --git a/templates/parachain/pallets/template/Cargo.toml b/templates/parachain/pallets/template/Cargo.toml index 199da2f12d2c691ba6d51d009c6b20734b1c4c46..f5411c02821c093402f4c24bd5341ccb39ba7e9d 100644 --- a/templates/parachain/pallets/template/Cargo.toml +++ b/templates/parachain/pallets/template/Cargo.toml @@ -9,14 +9,11 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/templates/parachain/pallets/template/src/benchmarking.rs b/templates/parachain/pallets/template/src/benchmarking.rs index 5a262417629c579c6ecf5ada30ae803217623766..d1a9554aed6dc0533f914e18661942ed56bcd514 100644 --- a/templates/parachain/pallets/template/src/benchmarking.rs +++ b/templates/parachain/pallets/template/src/benchmarking.rs @@ -13,7 +13,7 @@ mod benchmarks { #[benchmark] fn do_something() { - let value = 100u32.into(); + let value = 100u32; let caller: T::AccountId = whitelisted_caller(); #[extrinsic_call] do_something(RawOrigin::Signed(caller), value); diff --git a/templates/parachain/pallets/template/src/mock.rs b/templates/parachain/pallets/template/src/mock.rs index 8a88be3e3e9f6d08137ae1bb16767145e2d84aa9..9a907f61660530c1788b555ac1d1475bbc08827a 100644 --- a/templates/parachain/pallets/template/src/mock.rs +++ b/templates/parachain/pallets/template/src/mock.rs @@ -18,7 +18,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = 42; } @@ -37,7 +36,6 @@ impl system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/templates/parachain/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml index 0d985796a11e880123f9b7ca71bf123fe1b48184..e88284bedb6a672a7db0f82de3fe745f7d831d5f 100644 --- a/templates/parachain/runtime/Cargo.toml +++ b/templates/parachain/runtime/Cargo.toml @@ -9,17 +9,15 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] substrate-wasm-builder = { path = "../../../substrate/utils/wasm-builder", optional = true } +docify = "0.2.8" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } hex-literal = { version = "0.4.1", optional = true } @@ -28,6 +26,7 @@ scale-info = { version = "2.11.1", default-features = false, features = [ "derive", ] } smallvec = "1.11.0" +docify = "0.2.8" # Local pallet-parachain-template = { path = "../pallets/template", default-features = false } @@ -35,6 +34,7 @@ pallet-parachain-template = { path = "../pallets/template", default-features = f # Substrate / FRAME frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-executive = { path = "../../../substrate/frame/executive", default-features = false } +frame-metadata-hash-extension = { path = "../../../substrate/frame/metadata-hash-extension", default-features = false } frame-support = { path = "../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../substrate/frame/system", default-features = false } frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } @@ -76,12 +76,11 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm # Cumulus cumulus-pallet-aura-ext = { path = "../../../cumulus/pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../cumulus/pallets/parachain-system", default-features = false, features = [ - "parameterized-consensus-hook", -] } +cumulus-pallet-parachain-system = { path = "../../../cumulus/pallets/parachain-system", default-features = false } cumulus-pallet-session-benchmarking = { path = "../../../cumulus/pallets/session-benchmarking", default-features = false } cumulus-pallet-xcm = { path = "../../../cumulus/pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../../cumulus/pallets/xcmp-queue", default-features = false } +cumulus-primitives-aura = { path = "../../../cumulus/primitives/aura", default-features = false } cumulus-primitives-core = { path = "../../../cumulus/primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../cumulus/primitives/utility", default-features = false } cumulus-primitives-storage-weight-reclaim = { path = "../../../cumulus/primitives/storage-weight-reclaim", default-features = false } @@ -98,11 +97,13 @@ std = [ "cumulus-pallet-session-benchmarking/std", "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", "cumulus-primitives-core/std", "cumulus-primitives-storage-weight-reclaim/std", "cumulus-primitives-utility/std", "frame-benchmarking?/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", @@ -194,3 +195,16 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] + +# Enable the metadata hash generation. +# +# This is hidden behind a feature because it increases the compile time. +# The wasm binary needs to be compiled twice, once to fetch the metadata, +# generate the metadata hash and then a second time with the +# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` +# extension. +metadata-hash = ["substrate-wasm-builder/metadata-hash"] + +# A convenience feature for enabling things when doing a build +# for an on-chain release. +on-chain-release-build = ["metadata-hash"] diff --git a/templates/parachain/runtime/build.rs b/templates/parachain/runtime/build.rs index bb05afe02b1fc526d1c7a2c64514e7f25f33c7be..4f33752ca6b2d47b31270ca885a1c42f10ed8410 100644 --- a/templates/parachain/runtime/build.rs +++ b/templates/parachain/runtime/build.rs @@ -1,4 +1,12 @@ -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "metadata-hash"))] +#[docify::export(template_enable_metadata_hash)] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("UNIT", 12) + .build(); +} + +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] fn main() { substrate_wasm_builder::WasmBuilder::build_using_defaults(); } diff --git a/templates/parachain/runtime/src/apis.rs b/templates/parachain/runtime/src/apis.rs index b13ba278fae607c9e585ad04618d1651293436e1..107956ded410464757c767b81d1ac88da9aba1a4 100644 --- a/templates/parachain/runtime/src/apis.rs +++ b/templates/parachain/runtime/src/apis.rs @@ -42,14 +42,15 @@ use sp_version::RuntimeVersion; // Local module imports use super::{ - AccountId, Aura, Balance, Block, Executive, InherentDataExt, Nonce, ParachainSystem, Runtime, - RuntimeCall, RuntimeGenesisConfig, SessionKeys, System, TransactionPayment, VERSION, + AccountId, Balance, Block, ConsensusHook, Executive, InherentDataExt, Nonce, ParachainSystem, + Runtime, RuntimeCall, RuntimeGenesisConfig, SessionKeys, System, TransactionPayment, + SLOT_DURATION, VERSION, }; impl_runtime_apis! { impl sp_consensus_aura::AuraApi for Runtime { fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) } fn authorities() -> Vec { @@ -57,6 +58,15 @@ impl_runtime_apis! { } } + impl cumulus_primitives_aura::AuraUnincludedSegmentApi for Runtime { + fn can_build_upon( + included_hash: ::Hash, + slot: cumulus_primitives_aura::Slot, + ) -> bool { + ConsensusHook::can_build_upon(included_hash, slot) + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION diff --git a/templates/parachain/runtime/src/configs/mod.rs b/templates/parachain/runtime/src/configs/mod.rs index f1aea481ee277c5b753452bab315175cb4afb741..63e6a67a90638266820bce44e8aee75a544681bc 100644 --- a/templates/parachain/runtime/src/configs/mod.rs +++ b/templates/parachain/runtime/src/configs/mod.rs @@ -26,7 +26,7 @@ mod xcm_config; // Substrate and Polkadot dependencies -use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; use frame_support::{ derive_impl, @@ -53,12 +53,11 @@ use xcm::latest::prelude::BodyId; // Local module imports use super::{ weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}, - AccountId, Aura, Balance, Balances, Block, BlockNumber, CollatorSelection, Hash, MessageQueue, - Nonce, PalletInfo, ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, RuntimeFreezeReason, - RuntimeHoldReason, RuntimeOrigin, RuntimeTask, Session, SessionKeys, System, WeightToFee, - XcmpQueue, AVERAGE_ON_INITIALIZE_RATIO, BLOCK_PROCESSING_VELOCITY, EXISTENTIAL_DEPOSIT, HOURS, - MAXIMUM_BLOCK_WEIGHT, MICROUNIT, NORMAL_DISPATCH_RATIO, RELAY_CHAIN_SLOT_DURATION_MILLIS, - SLOT_DURATION, UNINCLUDED_SEGMENT_CAPACITY, VERSION, + AccountId, Aura, Balance, Balances, Block, BlockNumber, CollatorSelection, ConsensusHook, Hash, + MessageQueue, Nonce, PalletInfo, ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, + RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeTask, Session, SessionKeys, + System, WeightToFee, XcmpQueue, AVERAGE_ON_INITIALIZE_RATIO, EXISTENTIAL_DEPOSIT, HOURS, + MAXIMUM_BLOCK_WEIGHT, MICROUNIT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, VERSION, }; use xcm_config::{RelayLocation, XcmOriginToTransactDispatchOrigin}; @@ -128,7 +127,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type MinimumPeriod = ConstU64<0>; type WeightInfo = (); } @@ -195,13 +194,8 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; - type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< - Runtime, - RELAY_CHAIN_SLOT_DURATION_MILLIS, - BLOCK_PROCESSING_VELOCITY, - UNINCLUDED_SEGMENT_CAPACITY, - >; + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; } impl parachain_info::Config for Runtime {} @@ -227,7 +221,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = (); @@ -242,6 +236,8 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxPageSize = ConstU32<{ 1 << 16 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = (); @@ -271,8 +267,8 @@ impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; - type AllowMultipleBlocksPerSlot = ConstBool; - type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; + type AllowMultipleBlocksPerSlot = ConstBool; + type SlotDuration = ConstU64; } parameter_types! { diff --git a/templates/parachain/runtime/src/configs/xcm_config.rs b/templates/parachain/runtime/src/configs/xcm_config.rs index c6b6e8da1b89d38a8f5f7695809972d35d83cf12..e162bcbf88686c00ea10dc9b06c985329faa763b 100644 --- a/templates/parachain/runtime/src/configs/xcm_config.rs +++ b/templates/parachain/runtime/src/configs/xcm_config.rs @@ -142,6 +142,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpNewChannelOpenRequestHandler = (); type HrmpChannelAcceptedHandler = (); type HrmpChannelClosingHandler = (); + type XcmRecorder = PolkadotXcm; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 5bfd6f290c1b9839f4e19c0c21984f258512dd37..987b88af8444dac73fa1b8972e78973f35ea869d 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -75,6 +75,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. +#[docify::export(template_signed_extra)] pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, @@ -85,6 +86,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, ); /// Unchecked extrinsic type as expected by this runtime. @@ -173,7 +175,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// up by `pallet_aura` to implement `fn slot_duration()`. /// /// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 12000; +pub const MILLISECS_PER_BLOCK: u64 = 6000; // NOTE: Currently it is not possible to change the slot duration after the chain has started. // Attempting to do so will brick block production. @@ -200,21 +202,29 @@ const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); /// `Operational` extrinsics. const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// We allow for 0.5 of a second of compute with a 12 second average block time. +/// We allow for 2 seconds of compute with a 6 second average block time. const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( - WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), + WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, ); /// Maximum number of blocks simultaneously accepted by the Runtime, not yet included /// into the relay chain. -const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; +const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3; /// How many parachain blocks are processed by the relay chain per parent. Limits the /// number of blocks authored per slot. const BLOCK_PROCESSING_VELOCITY: u32 = 1; /// Relay chain slot duration, in milliseconds. const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; +/// Aura consensus hook +type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< + Runtime, + RELAY_CHAIN_SLOT_DURATION_MILLIS, + BLOCK_PROCESSING_VELOCITY, + UNINCLUDED_SEGMENT_CAPACITY, +>; + /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { diff --git a/templates/solochain/node/Cargo.toml b/templates/solochain/node/Cargo.toml index 9332da3a6549c90fe3eebfcda3fbb51dc49c57d6..515f85e541821a8c23d56e9c7c543d55e0f87f38 100644 --- a/templates/solochain/node/Cargo.toml +++ b/templates/solochain/node/Cargo.toml @@ -11,9 +11,6 @@ publish = false build = "build.rs" -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/templates/solochain/node/src/chain_spec.rs b/templates/solochain/node/src/chain_spec.rs index be49f2c1fc731ee4e5ece7841151068abf0f0790..651025e68ded916485f03b377bb44482d89ac5ba 100644 --- a/templates/solochain/node/src/chain_spec.rs +++ b/templates/solochain/node/src/chain_spec.rs @@ -1,5 +1,5 @@ use sc_service::ChainType; -use solochain_template_runtime::{AccountId, RuntimeGenesisConfig, Signature, WASM_BINARY}; +use solochain_template_runtime::{AccountId, Signature, WASM_BINARY}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; @@ -9,7 +9,7 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; // 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::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; /// Generate a crypto pair from seed. pub fn get_from_seed(seed: &str) -> ::Public { diff --git a/templates/solochain/node/src/command.rs b/templates/solochain/node/src/command.rs index e46fedc91f0e26fb9e4e36dbbc45a3cc0c0c7310..624ace1bf350a1d5b36d0f409d0ca3868fd127fc 100644 --- a/templates/solochain/node/src/command.rs +++ b/templates/solochain/node/src/command.rs @@ -114,7 +114,7 @@ pub fn run() -> sc_cli::Result<()> { "Runtime benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." .into(), - ) + ); } cmd.run_with_spec::, ()>(Some( diff --git a/templates/solochain/pallets/template/Cargo.toml b/templates/solochain/pallets/template/Cargo.toml index 24519f1d22e0d214e418974de65c7f77588498c4..8c6f26d8e5d0ca49adab27b54bb157e39d8acb02 100644 --- a/templates/solochain/pallets/template/Cargo.toml +++ b/templates/solochain/pallets/template/Cargo.toml @@ -9,14 +9,11 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/templates/solochain/pallets/template/src/benchmarking.rs b/templates/solochain/pallets/template/src/benchmarking.rs index 5a262417629c579c6ecf5ada30ae803217623766..d1a9554aed6dc0533f914e18661942ed56bcd514 100644 --- a/templates/solochain/pallets/template/src/benchmarking.rs +++ b/templates/solochain/pallets/template/src/benchmarking.rs @@ -13,7 +13,7 @@ mod benchmarks { #[benchmark] fn do_something() { - let value = 100u32.into(); + let value = 100u32; let caller: T::AccountId = whitelisted_caller(); #[extrinsic_call] do_something(RawOrigin::Signed(caller), value); diff --git a/templates/solochain/pallets/template/src/mock.rs b/templates/solochain/pallets/template/src/mock.rs index 3f1fd2dd6d4441c2177d3f44a0f377b3ab2edc72..09081dae0625c595b31967c2b36b244715fa3b0b 100644 --- a/templates/solochain/pallets/template/src/mock.rs +++ b/templates/solochain/pallets/template/src/mock.rs @@ -1,8 +1,5 @@ use crate as pallet_template; -use frame_support::{ - derive_impl, - traits::{ConstU16, ConstU64}, -}; +use frame_support::{derive_impl, traits::ConstU16}; use sp_core::H256; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, @@ -35,7 +32,6 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml index 7a81f192043f5bc516ca774e1cebf8c039f06ceb..8aeb1a6a16e6573dac6984b5af3a0998bec95909 100644 --- a/templates/solochain/runtime/Cargo.toml +++ b/templates/solochain/runtime/Cargo.toml @@ -9,14 +9,11 @@ repository.workspace = true edition.workspace = true publish = false -[lints] -workspace = true - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ "derive", ] } scale-info = { version = "2.11.1", default-features = false, features = [ diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9f1308d5096c7cf7fa863469c638ac7cd3477b6a --- /dev/null +++ b/umbrella/Cargo.toml @@ -0,0 +1,2449 @@ +[package] +name = "polkadot-sdk" +version = "0.1.0" +description = "Polkadot SDK umbrella crate." +license = "Apache-2.0" + +[features] +default = ["std"] +std = [ + "asset-test-utils?/std", + "assets-common?/std", + "binary-merkle-tree?/std", + "bp-asset-hub-rococo?/std", + "bp-asset-hub-westend?/std", + "bp-bridge-hub-cumulus?/std", + "bp-bridge-hub-kusama?/std", + "bp-bridge-hub-polkadot?/std", + "bp-bridge-hub-rococo?/std", + "bp-bridge-hub-westend?/std", + "bp-header-chain?/std", + "bp-kusama?/std", + "bp-messages?/std", + "bp-parachains?/std", + "bp-polkadot-bulletin?/std", + "bp-polkadot-core?/std", + "bp-polkadot?/std", + "bp-relayers?/std", + "bp-rococo?/std", + "bp-runtime?/std", + "bp-test-utils?/std", + "bp-westend?/std", + "bp-xcm-bridge-hub-router?/std", + "bp-xcm-bridge-hub?/std", + "bridge-hub-common?/std", + "bridge-hub-test-utils?/std", + "bridge-runtime-common?/std", + "cumulus-pallet-aura-ext?/std", + "cumulus-pallet-dmp-queue?/std", + "cumulus-pallet-parachain-system-proc-macro?/std", + "cumulus-pallet-parachain-system?/std", + "cumulus-pallet-session-benchmarking?/std", + "cumulus-pallet-solo-to-para?/std", + "cumulus-pallet-xcm?/std", + "cumulus-pallet-xcmp-queue?/std", + "cumulus-ping?/std", + "cumulus-primitives-aura?/std", + "cumulus-primitives-core?/std", + "cumulus-primitives-parachain-inherent?/std", + "cumulus-primitives-proof-size-hostfunction?/std", + "cumulus-primitives-storage-weight-reclaim?/std", + "cumulus-primitives-timestamp?/std", + "cumulus-primitives-utility?/std", + "cumulus-test-relay-sproof-builder?/std", + "frame-benchmarking-pallet-pov?/std", + "frame-benchmarking?/std", + "frame-election-provider-support?/std", + "frame-executive?/std", + "frame-metadata-hash-extension?/std", + "frame-support-procedural?/std", + "frame-support?/std", + "frame-system-benchmarking?/std", + "frame-system-rpc-runtime-api?/std", + "frame-system?/std", + "frame-try-runtime?/std", + "pallet-alliance?/std", + "pallet-asset-conversion-ops?/std", + "pallet-asset-conversion-tx-payment?/std", + "pallet-asset-conversion?/std", + "pallet-asset-rate?/std", + "pallet-asset-tx-payment?/std", + "pallet-assets?/std", + "pallet-atomic-swap?/std", + "pallet-aura?/std", + "pallet-authority-discovery?/std", + "pallet-authorship?/std", + "pallet-babe?/std", + "pallet-bags-list?/std", + "pallet-balances?/std", + "pallet-beefy-mmr?/std", + "pallet-beefy?/std", + "pallet-bounties?/std", + "pallet-bridge-grandpa?/std", + "pallet-bridge-messages?/std", + "pallet-bridge-parachains?/std", + "pallet-bridge-relayers?/std", + "pallet-broker?/std", + "pallet-child-bounties?/std", + "pallet-collator-selection?/std", + "pallet-collective-content?/std", + "pallet-collective?/std", + "pallet-contracts-mock-network?/std", + "pallet-contracts?/std", + "pallet-conviction-voting?/std", + "pallet-core-fellowship?/std", + "pallet-delegated-staking?/std", + "pallet-democracy?/std", + "pallet-dev-mode?/std", + "pallet-election-provider-multi-phase?/std", + "pallet-election-provider-support-benchmarking?/std", + "pallet-elections-phragmen?/std", + "pallet-fast-unstake?/std", + "pallet-glutton?/std", + "pallet-grandpa?/std", + "pallet-identity?/std", + "pallet-im-online?/std", + "pallet-indices?/std", + "pallet-insecure-randomness-collective-flip?/std", + "pallet-lottery?/std", + "pallet-membership?/std", + "pallet-message-queue?/std", + "pallet-migrations?/std", + "pallet-mixnet?/std", + "pallet-mmr?/std", + "pallet-multisig?/std", + "pallet-nft-fractionalization?/std", + "pallet-nfts-runtime-api?/std", + "pallet-nfts?/std", + "pallet-nis?/std", + "pallet-node-authorization?/std", + "pallet-nomination-pools-benchmarking?/std", + "pallet-nomination-pools-runtime-api?/std", + "pallet-nomination-pools?/std", + "pallet-offences-benchmarking?/std", + "pallet-offences?/std", + "pallet-paged-list?/std", + "pallet-parameters?/std", + "pallet-preimage?/std", + "pallet-proxy?/std", + "pallet-ranked-collective?/std", + "pallet-recovery?/std", + "pallet-referenda?/std", + "pallet-remark?/std", + "pallet-root-offences?/std", + "pallet-root-testing?/std", + "pallet-safe-mode?/std", + "pallet-salary?/std", + "pallet-scheduler?/std", + "pallet-scored-pool?/std", + "pallet-session-benchmarking?/std", + "pallet-session?/std", + "pallet-skip-feeless-payment?/std", + "pallet-society?/std", + "pallet-staking-reward-fn?/std", + "pallet-staking-runtime-api?/std", + "pallet-staking?/std", + "pallet-state-trie-migration?/std", + "pallet-statement?/std", + "pallet-sudo?/std", + "pallet-timestamp?/std", + "pallet-tips?/std", + "pallet-transaction-payment-rpc-runtime-api?/std", + "pallet-transaction-payment?/std", + "pallet-transaction-storage?/std", + "pallet-treasury?/std", + "pallet-tx-pause?/std", + "pallet-uniques?/std", + "pallet-utility?/std", + "pallet-vesting?/std", + "pallet-whitelist?/std", + "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub-router?/std", + "pallet-xcm-bridge-hub?/std", + "pallet-xcm?/std", + "parachains-common?/std", + "parachains-runtimes-test-utils?/std", + "polkadot-core-primitives?/std", + "polkadot-parachain-primitives?/std", + "polkadot-primitives?/std", + "polkadot-runtime-common?/std", + "polkadot-runtime-metrics?/std", + "polkadot-runtime-parachains?/std", + "polkadot-sdk-frame?/std", + "rococo-runtime-constants?/std", + "sc-executor?/std", + "slot-range-helper?/std", + "snowbridge-beacon-primitives?/std", + "snowbridge-core?/std", + "snowbridge-ethereum?/std", + "snowbridge-outbound-queue-merkle-tree?/std", + "snowbridge-outbound-queue-runtime-api?/std", + "snowbridge-pallet-ethereum-client-fixtures?/std", + "snowbridge-pallet-ethereum-client?/std", + "snowbridge-pallet-inbound-queue-fixtures?/std", + "snowbridge-pallet-inbound-queue?/std", + "snowbridge-pallet-outbound-queue?/std", + "snowbridge-pallet-system?/std", + "snowbridge-router-primitives?/std", + "snowbridge-runtime-common?/std", + "snowbridge-runtime-test-common?/std", + "snowbridge-system-runtime-api?/std", + "sp-api-proc-macro?/std", + "sp-api?/std", + "sp-application-crypto?/std", + "sp-arithmetic?/std", + "sp-authority-discovery?/std", + "sp-block-builder?/std", + "sp-consensus-aura?/std", + "sp-consensus-babe?/std", + "sp-consensus-beefy?/std", + "sp-consensus-grandpa?/std", + "sp-consensus-pow?/std", + "sp-consensus-slots?/std", + "sp-core-hashing?/std", + "sp-core?/std", + "sp-crypto-ec-utils?/std", + "sp-crypto-hashing?/std", + "sp-debug-derive?/std", + "sp-externalities?/std", + "sp-genesis-builder?/std", + "sp-inherents?/std", + "sp-io?/std", + "sp-keyring?/std", + "sp-keystore?/std", + "sp-metadata-ir?/std", + "sp-mixnet?/std", + "sp-mmr-primitives?/std", + "sp-npos-elections?/std", + "sp-offchain?/std", + "sp-runtime-interface?/std", + "sp-runtime?/std", + "sp-session?/std", + "sp-staking?/std", + "sp-state-machine?/std", + "sp-statement-store?/std", + "sp-std?/std", + "sp-storage?/std", + "sp-timestamp?/std", + "sp-tracing?/std", + "sp-transaction-pool?/std", + "sp-transaction-storage-proof?/std", + "sp-trie?/std", + "sp-version?/std", + "sp-wasm-interface?/std", + "sp-weights?/std", + "staging-parachain-info?/std", + "staging-xcm-builder?/std", + "staging-xcm-executor?/std", + "staging-xcm?/std", + "substrate-bip39?/std", + "testnet-parachains-constants?/std", + "westend-runtime-constants?/std", + "xcm-fee-payment-runtime-api?/std", +] +runtime-benchmarks = [ + "assets-common?/runtime-benchmarks", + "bridge-hub-common?/runtime-benchmarks", + "bridge-runtime-common?/runtime-benchmarks", + "cumulus-pallet-dmp-queue?/runtime-benchmarks", + "cumulus-pallet-parachain-system?/runtime-benchmarks", + "cumulus-pallet-session-benchmarking?/runtime-benchmarks", + "cumulus-pallet-xcmp-queue?/runtime-benchmarks", + "cumulus-primitives-core?/runtime-benchmarks", + "cumulus-primitives-utility?/runtime-benchmarks", + "frame-benchmarking-cli?/runtime-benchmarks", + "frame-benchmarking-pallet-pov?/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-election-provider-support?/runtime-benchmarks", + "frame-support?/runtime-benchmarks", + "frame-system-benchmarking?/runtime-benchmarks", + "frame-system?/runtime-benchmarks", + "pallet-alliance?/runtime-benchmarks", + "pallet-asset-conversion-ops?/runtime-benchmarks", + "pallet-asset-conversion?/runtime-benchmarks", + "pallet-asset-rate?/runtime-benchmarks", + "pallet-asset-tx-payment?/runtime-benchmarks", + "pallet-assets?/runtime-benchmarks", + "pallet-babe?/runtime-benchmarks", + "pallet-bags-list?/runtime-benchmarks", + "pallet-balances?/runtime-benchmarks", + "pallet-bounties?/runtime-benchmarks", + "pallet-bridge-grandpa?/runtime-benchmarks", + "pallet-bridge-messages?/runtime-benchmarks", + "pallet-bridge-parachains?/runtime-benchmarks", + "pallet-bridge-relayers?/runtime-benchmarks", + "pallet-broker?/runtime-benchmarks", + "pallet-child-bounties?/runtime-benchmarks", + "pallet-collator-selection?/runtime-benchmarks", + "pallet-collective-content?/runtime-benchmarks", + "pallet-collective?/runtime-benchmarks", + "pallet-contracts-mock-network?/runtime-benchmarks", + "pallet-contracts?/runtime-benchmarks", + "pallet-conviction-voting?/runtime-benchmarks", + "pallet-core-fellowship?/runtime-benchmarks", + "pallet-delegated-staking?/runtime-benchmarks", + "pallet-democracy?/runtime-benchmarks", + "pallet-election-provider-multi-phase?/runtime-benchmarks", + "pallet-election-provider-support-benchmarking?/runtime-benchmarks", + "pallet-elections-phragmen?/runtime-benchmarks", + "pallet-fast-unstake?/runtime-benchmarks", + "pallet-glutton?/runtime-benchmarks", + "pallet-grandpa?/runtime-benchmarks", + "pallet-identity?/runtime-benchmarks", + "pallet-im-online?/runtime-benchmarks", + "pallet-indices?/runtime-benchmarks", + "pallet-lottery?/runtime-benchmarks", + "pallet-membership?/runtime-benchmarks", + "pallet-message-queue?/runtime-benchmarks", + "pallet-migrations?/runtime-benchmarks", + "pallet-mixnet?/runtime-benchmarks", + "pallet-mmr?/runtime-benchmarks", + "pallet-multisig?/runtime-benchmarks", + "pallet-nft-fractionalization?/runtime-benchmarks", + "pallet-nfts?/runtime-benchmarks", + "pallet-nis?/runtime-benchmarks", + "pallet-nomination-pools-benchmarking?/runtime-benchmarks", + "pallet-nomination-pools?/runtime-benchmarks", + "pallet-offences-benchmarking?/runtime-benchmarks", + "pallet-offences?/runtime-benchmarks", + "pallet-paged-list?/runtime-benchmarks", + "pallet-parameters?/runtime-benchmarks", + "pallet-preimage?/runtime-benchmarks", + "pallet-proxy?/runtime-benchmarks", + "pallet-ranked-collective?/runtime-benchmarks", + "pallet-recovery?/runtime-benchmarks", + "pallet-referenda?/runtime-benchmarks", + "pallet-remark?/runtime-benchmarks", + "pallet-root-offences?/runtime-benchmarks", + "pallet-safe-mode?/runtime-benchmarks", + "pallet-salary?/runtime-benchmarks", + "pallet-scheduler?/runtime-benchmarks", + "pallet-session-benchmarking?/runtime-benchmarks", + "pallet-skip-feeless-payment?/runtime-benchmarks", + "pallet-society?/runtime-benchmarks", + "pallet-staking?/runtime-benchmarks", + "pallet-state-trie-migration?/runtime-benchmarks", + "pallet-sudo?/runtime-benchmarks", + "pallet-timestamp?/runtime-benchmarks", + "pallet-tips?/runtime-benchmarks", + "pallet-transaction-storage?/runtime-benchmarks", + "pallet-treasury?/runtime-benchmarks", + "pallet-tx-pause?/runtime-benchmarks", + "pallet-uniques?/runtime-benchmarks", + "pallet-utility?/runtime-benchmarks", + "pallet-vesting?/runtime-benchmarks", + "pallet-whitelist?/runtime-benchmarks", + "pallet-xcm-benchmarks?/runtime-benchmarks", + "pallet-xcm-bridge-hub-router?/runtime-benchmarks", + "pallet-xcm-bridge-hub?/runtime-benchmarks", + "pallet-xcm?/runtime-benchmarks", + "parachains-common?/runtime-benchmarks", + "polkadot-cli?/runtime-benchmarks", + "polkadot-node-metrics?/runtime-benchmarks", + "polkadot-parachain-primitives?/runtime-benchmarks", + "polkadot-primitives?/runtime-benchmarks", + "polkadot-runtime-common?/runtime-benchmarks", + "polkadot-runtime-parachains?/runtime-benchmarks", + "polkadot-sdk-frame?/runtime-benchmarks", + "polkadot-service?/runtime-benchmarks", + "sc-client-db?/runtime-benchmarks", + "sc-service?/runtime-benchmarks", + "snowbridge-core?/runtime-benchmarks", + "snowbridge-pallet-ethereum-client-fixtures?/runtime-benchmarks", + "snowbridge-pallet-ethereum-client?/runtime-benchmarks", + "snowbridge-pallet-inbound-queue-fixtures?/runtime-benchmarks", + "snowbridge-pallet-inbound-queue?/runtime-benchmarks", + "snowbridge-pallet-outbound-queue?/runtime-benchmarks", + "snowbridge-pallet-system?/runtime-benchmarks", + "snowbridge-router-primitives?/runtime-benchmarks", + "snowbridge-runtime-common?/runtime-benchmarks", + "snowbridge-runtime-test-common?/runtime-benchmarks", + "sp-runtime?/runtime-benchmarks", + "sp-staking?/runtime-benchmarks", + "staging-node-inspect?/runtime-benchmarks", + "staging-xcm-builder?/runtime-benchmarks", + "staging-xcm-executor?/runtime-benchmarks", + "xcm-fee-payment-runtime-api?/runtime-benchmarks", +] +try-runtime = [ + "cumulus-pallet-aura-ext?/try-runtime", + "cumulus-pallet-dmp-queue?/try-runtime", + "cumulus-pallet-parachain-system?/try-runtime", + "cumulus-pallet-solo-to-para?/try-runtime", + "cumulus-pallet-xcm?/try-runtime", + "cumulus-pallet-xcmp-queue?/try-runtime", + "cumulus-ping?/try-runtime", + "frame-benchmarking-pallet-pov?/try-runtime", + "frame-election-provider-support?/try-runtime", + "frame-executive?/try-runtime", + "frame-support?/try-runtime", + "frame-system?/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-alliance?/try-runtime", + "pallet-asset-conversion-ops?/try-runtime", + "pallet-asset-conversion-tx-payment?/try-runtime", + "pallet-asset-conversion?/try-runtime", + "pallet-asset-rate?/try-runtime", + "pallet-asset-tx-payment?/try-runtime", + "pallet-assets?/try-runtime", + "pallet-atomic-swap?/try-runtime", + "pallet-aura?/try-runtime", + "pallet-authority-discovery?/try-runtime", + "pallet-authorship?/try-runtime", + "pallet-babe?/try-runtime", + "pallet-bags-list?/try-runtime", + "pallet-balances?/try-runtime", + "pallet-beefy-mmr?/try-runtime", + "pallet-beefy?/try-runtime", + "pallet-bounties?/try-runtime", + "pallet-bridge-grandpa?/try-runtime", + "pallet-bridge-messages?/try-runtime", + "pallet-bridge-parachains?/try-runtime", + "pallet-bridge-relayers?/try-runtime", + "pallet-broker?/try-runtime", + "pallet-child-bounties?/try-runtime", + "pallet-collator-selection?/try-runtime", + "pallet-collective-content?/try-runtime", + "pallet-collective?/try-runtime", + "pallet-contracts?/try-runtime", + "pallet-conviction-voting?/try-runtime", + "pallet-core-fellowship?/try-runtime", + "pallet-delegated-staking?/try-runtime", + "pallet-democracy?/try-runtime", + "pallet-dev-mode?/try-runtime", + "pallet-election-provider-multi-phase?/try-runtime", + "pallet-elections-phragmen?/try-runtime", + "pallet-fast-unstake?/try-runtime", + "pallet-glutton?/try-runtime", + "pallet-grandpa?/try-runtime", + "pallet-identity?/try-runtime", + "pallet-im-online?/try-runtime", + "pallet-indices?/try-runtime", + "pallet-insecure-randomness-collective-flip?/try-runtime", + "pallet-lottery?/try-runtime", + "pallet-membership?/try-runtime", + "pallet-message-queue?/try-runtime", + "pallet-migrations?/try-runtime", + "pallet-mixnet?/try-runtime", + "pallet-mmr?/try-runtime", + "pallet-multisig?/try-runtime", + "pallet-nft-fractionalization?/try-runtime", + "pallet-nfts?/try-runtime", + "pallet-nis?/try-runtime", + "pallet-node-authorization?/try-runtime", + "pallet-nomination-pools?/try-runtime", + "pallet-offences?/try-runtime", + "pallet-paged-list?/try-runtime", + "pallet-parameters?/try-runtime", + "pallet-preimage?/try-runtime", + "pallet-proxy?/try-runtime", + "pallet-ranked-collective?/try-runtime", + "pallet-recovery?/try-runtime", + "pallet-referenda?/try-runtime", + "pallet-remark?/try-runtime", + "pallet-root-offences?/try-runtime", + "pallet-root-testing?/try-runtime", + "pallet-safe-mode?/try-runtime", + "pallet-salary?/try-runtime", + "pallet-scheduler?/try-runtime", + "pallet-scored-pool?/try-runtime", + "pallet-session?/try-runtime", + "pallet-skip-feeless-payment?/try-runtime", + "pallet-society?/try-runtime", + "pallet-staking?/try-runtime", + "pallet-state-trie-migration?/try-runtime", + "pallet-statement?/try-runtime", + "pallet-sudo?/try-runtime", + "pallet-timestamp?/try-runtime", + "pallet-tips?/try-runtime", + "pallet-transaction-payment?/try-runtime", + "pallet-transaction-storage?/try-runtime", + "pallet-treasury?/try-runtime", + "pallet-tx-pause?/try-runtime", + "pallet-uniques?/try-runtime", + "pallet-utility?/try-runtime", + "pallet-vesting?/try-runtime", + "pallet-whitelist?/try-runtime", + "pallet-xcm-bridge-hub-router?/try-runtime", + "pallet-xcm-bridge-hub?/try-runtime", + "pallet-xcm?/try-runtime", + "polkadot-cli?/try-runtime", + "polkadot-runtime-common?/try-runtime", + "polkadot-runtime-parachains?/try-runtime", + "polkadot-sdk-frame?/try-runtime", + "polkadot-service?/try-runtime", + "snowbridge-pallet-ethereum-client?/try-runtime", + "snowbridge-pallet-inbound-queue?/try-runtime", + "snowbridge-pallet-outbound-queue?/try-runtime", + "snowbridge-pallet-system?/try-runtime", + "sp-runtime?/try-runtime", + "staging-parachain-info?/try-runtime", +] +serde = [ + "bp-polkadot-core?/serde", + "frame-benchmarking?/serde", + "pallet-asset-tx-payment?/serde", + "pallet-beefy-mmr?/serde", + "pallet-beefy?/serde", + "pallet-contracts?/serde", + "pallet-conviction-voting?/serde", + "pallet-democracy?/serde", + "pallet-message-queue?/serde", + "pallet-offences?/serde", + "pallet-parameters?/serde", + "pallet-referenda?/serde", + "pallet-remark?/serde", + "pallet-state-trie-migration?/serde", + "pallet-tips?/serde", + "pallet-transaction-payment?/serde", + "pallet-transaction-storage?/serde", + "pallet-treasury?/serde", + "pallet-xcm?/serde", + "snowbridge-beacon-primitives?/serde", + "snowbridge-core?/serde", + "snowbridge-ethereum?/serde", + "snowbridge-pallet-ethereum-client?/serde", + "snowbridge-pallet-inbound-queue?/serde", + "sp-application-crypto?/serde", + "sp-arithmetic?/serde", + "sp-authority-discovery?/serde", + "sp-consensus-aura?/serde", + "sp-consensus-babe?/serde", + "sp-consensus-beefy?/serde", + "sp-consensus-grandpa?/serde", + "sp-consensus-slots?/serde", + "sp-core?/serde", + "sp-mmr-primitives?/serde", + "sp-npos-elections?/serde", + "sp-runtime?/serde", + "sp-staking?/serde", + "sp-statement-store?/serde", + "sp-storage?/serde", + "sp-version?/serde", + "sp-weights?/serde", +] +experimental = [ + "frame-support-procedural?/experimental", + "frame-support?/experimental", + "frame-system?/experimental", + "polkadot-sdk-frame?/experimental", +] +with-tracing = [ + "frame-executive?/with-tracing", + "frame-executive?/with-tracing", + "sp-io?/with-tracing", + "sp-io?/with-tracing", + "sp-tracing?/with-tracing", + "sp-tracing?/with-tracing", +] +runtime = ["assets-common", "binary-merkle-tree", "bp-asset-hub-rococo", "bp-asset-hub-westend", "bp-bridge-hub-cumulus", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", "bp-header-chain", "bp-kusama", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-bulletin", "bp-polkadot-core", "bp-relayers", "bp-rococo", "bp-runtime", "bp-test-utils", "bp-westend", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "rococo-runtime-constants", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "westend-runtime-constants", "xcm-fee-payment-runtime-api", "xcm-procedural"] +node = ["asset-test-utils", "bridge-hub-test-utils", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", "cumulus-client-consensus-common", "cumulus-client-consensus-proposer", "cumulus-client-consensus-relay-chain", "cumulus-client-network", "cumulus-client-parachain-inherent", "cumulus-client-pov-recovery", "cumulus-client-service", "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "cumulus-relay-chain-rpc-interface", "cumulus-test-relay-sproof-builder", "emulated-integration-tests-common", "fork-tree", "frame-benchmarking-cli", "frame-remote-externalities", "frame-support-procedural-tools", "generate-bags", "mmr-gadget", "mmr-rpc", "pallet-contracts-mock-network", "pallet-transaction-payment-rpc", "parachains-runtimes-test-utils", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", "polkadot-availability-recovery", "polkadot-cli", "polkadot-collator-protocol", "polkadot-dispute-distribution", "polkadot-erasure-coding", "polkadot-gossip-support", "polkadot-network-bridge", "polkadot-node-collation-generation", "polkadot-node-core-approval-voting", "polkadot-node-core-av-store", "polkadot-node-core-backing", "polkadot-node-core-bitfield-signing", "polkadot-node-core-candidate-validation", "polkadot-node-core-chain-api", "polkadot-node-core-chain-selection", "polkadot-node-core-dispute-coordinator", "polkadot-node-core-parachains-inherent", "polkadot-node-core-prospective-parachains", "polkadot-node-core-provisioner", "polkadot-node-core-pvf", "polkadot-node-core-pvf-checker", "polkadot-node-core-pvf-common", "polkadot-node-core-pvf-execute-worker", "polkadot-node-core-pvf-prepare-worker", "polkadot-node-core-runtime-api", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-rpc", "polkadot-service", "polkadot-statement-distribution", "polkadot-statement-table", "sc-allocator", "sc-authority-discovery", "sc-basic-authorship", "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", "sc-client-db", "sc-consensus", "sc-consensus-aura", "sc-consensus-babe", "sc-consensus-babe-rpc", "sc-consensus-beefy", "sc-consensus-beefy-rpc", "sc-consensus-epochs", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", "sc-consensus-manual-seal", "sc-consensus-pow", "sc-consensus-slots", "sc-executor", "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", "sc-informant", "sc-keystore", "sc-mixnet", "sc-network", "sc-network-common", "sc-network-gossip", "sc-network-light", "sc-network-statement", "sc-network-sync", "sc-network-transactions", "sc-network-types", "sc-offchain", "sc-proposer-metrics", "sc-rpc", "sc-rpc-api", "sc-rpc-server", "sc-rpc-spec-v2", "sc-service", "sc-state-db", "sc-statement-store", "sc-storage-monitor", "sc-sync-state-rpc", "sc-sysinfo", "sc-telemetry", "sc-tracing", "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", "snowbridge-runtime-test-common", "sp-blockchain", "sp-consensus", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-database", "sp-maybe-compressed-blob", "sp-panic-handler", "sp-rpc", "staging-node-inspect", "staging-tracking-allocator", "std", "subkey", "substrate-build-script-utils", "substrate-frame-rpc-support", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", "substrate-rpc-client", "substrate-state-trie-migration-rpc", "substrate-wasm-builder", "tracing-gum", "xcm-emulator", "xcm-simulator"] +tuples-96 = [ + "frame-support-procedural?/tuples-96", + "frame-support?/tuples-96", +] + +[package.edition] +workspace = true + +[package.authors] +workspace = true + +[dependencies.assets-common] +path = "../cumulus/parachains/runtimes/assets/common" +default-features = false +optional = true + +[dependencies.binary-merkle-tree] +path = "../substrate/utils/binary-merkle-tree" +default-features = false +optional = true + +[dependencies.bp-asset-hub-rococo] +path = "../bridges/chains/chain-asset-hub-rococo" +default-features = false +optional = true + +[dependencies.bp-asset-hub-westend] +path = "../bridges/chains/chain-asset-hub-westend" +default-features = false +optional = true + +[dependencies.bp-bridge-hub-cumulus] +path = "../bridges/chains/chain-bridge-hub-cumulus" +default-features = false +optional = true + +[dependencies.bp-bridge-hub-kusama] +path = "../bridges/chains/chain-bridge-hub-kusama" +default-features = false +optional = true + +[dependencies.bp-bridge-hub-polkadot] +path = "../bridges/chains/chain-bridge-hub-polkadot" +default-features = false +optional = true + +[dependencies.bp-bridge-hub-rococo] +path = "../bridges/chains/chain-bridge-hub-rococo" +default-features = false +optional = true + +[dependencies.bp-bridge-hub-westend] +path = "../bridges/chains/chain-bridge-hub-westend" +default-features = false +optional = true + +[dependencies.bp-header-chain] +path = "../bridges/primitives/header-chain" +default-features = false +optional = true + +[dependencies.bp-kusama] +path = "../bridges/chains/chain-kusama" +default-features = false +optional = true + +[dependencies.bp-messages] +path = "../bridges/primitives/messages" +default-features = false +optional = true + +[dependencies.bp-parachains] +path = "../bridges/primitives/parachains" +default-features = false +optional = true + +[dependencies.bp-polkadot] +path = "../bridges/chains/chain-polkadot" +default-features = false +optional = true + +[dependencies.bp-polkadot-bulletin] +path = "../bridges/chains/chain-polkadot-bulletin" +default-features = false +optional = true + +[dependencies.bp-polkadot-core] +path = "../bridges/primitives/polkadot-core" +default-features = false +optional = true + +[dependencies.bp-relayers] +path = "../bridges/primitives/relayers" +default-features = false +optional = true + +[dependencies.bp-rococo] +path = "../bridges/chains/chain-rococo" +default-features = false +optional = true + +[dependencies.bp-runtime] +path = "../bridges/primitives/runtime" +default-features = false +optional = true + +[dependencies.bp-test-utils] +path = "../bridges/primitives/test-utils" +default-features = false +optional = true + +[dependencies.bp-westend] +path = "../bridges/chains/chain-westend" +default-features = false +optional = true + +[dependencies.bp-xcm-bridge-hub] +path = "../bridges/primitives/xcm-bridge-hub" +default-features = false +optional = true + +[dependencies.bp-xcm-bridge-hub-router] +path = "../bridges/primitives/xcm-bridge-hub-router" +default-features = false +optional = true + +[dependencies.bridge-hub-common] +path = "../cumulus/parachains/runtimes/bridge-hubs/common" +default-features = false +optional = true + +[dependencies.bridge-runtime-common] +path = "../bridges/bin/runtime-common" +default-features = false +optional = true + +[dependencies.cumulus-pallet-aura-ext] +path = "../cumulus/pallets/aura-ext" +default-features = false +optional = true + +[dependencies.cumulus-pallet-dmp-queue] +path = "../cumulus/pallets/dmp-queue" +default-features = false +optional = true + +[dependencies.cumulus-pallet-parachain-system] +path = "../cumulus/pallets/parachain-system" +default-features = false +optional = true + +[dependencies.cumulus-pallet-parachain-system-proc-macro] +path = "../cumulus/pallets/parachain-system/proc-macro" +default-features = false +optional = true + +[dependencies.cumulus-pallet-session-benchmarking] +path = "../cumulus/pallets/session-benchmarking" +default-features = false +optional = true + +[dependencies.cumulus-pallet-solo-to-para] +path = "../cumulus/pallets/solo-to-para" +default-features = false +optional = true + +[dependencies.cumulus-pallet-xcm] +path = "../cumulus/pallets/xcm" +default-features = false +optional = true + +[dependencies.cumulus-pallet-xcmp-queue] +path = "../cumulus/pallets/xcmp-queue" +default-features = false +optional = true + +[dependencies.cumulus-ping] +path = "../cumulus/parachains/pallets/ping" +default-features = false +optional = true + +[dependencies.cumulus-primitives-aura] +path = "../cumulus/primitives/aura" +default-features = false +optional = true + +[dependencies.cumulus-primitives-core] +path = "../cumulus/primitives/core" +default-features = false +optional = true + +[dependencies.cumulus-primitives-parachain-inherent] +path = "../cumulus/primitives/parachain-inherent" +default-features = false +optional = true + +[dependencies.cumulus-primitives-proof-size-hostfunction] +path = "../cumulus/primitives/proof-size-hostfunction" +default-features = false +optional = true + +[dependencies.cumulus-primitives-storage-weight-reclaim] +path = "../cumulus/primitives/storage-weight-reclaim" +default-features = false +optional = true + +[dependencies.cumulus-primitives-timestamp] +path = "../cumulus/primitives/timestamp" +default-features = false +optional = true + +[dependencies.cumulus-primitives-utility] +path = "../cumulus/primitives/utility" +default-features = false +optional = true + +[dependencies.frame-benchmarking] +path = "../substrate/frame/benchmarking" +default-features = false +optional = true + +[dependencies.frame-benchmarking-pallet-pov] +path = "../substrate/frame/benchmarking/pov" +default-features = false +optional = true + +[dependencies.frame-election-provider-solution-type] +path = "../substrate/frame/election-provider-support/solution-type" +default-features = false +optional = true + +[dependencies.frame-election-provider-support] +path = "../substrate/frame/election-provider-support" +default-features = false +optional = true + +[dependencies.frame-executive] +path = "../substrate/frame/executive" +default-features = false +optional = true + +[dependencies.frame-metadata-hash-extension] +path = "../substrate/frame/metadata-hash-extension" +default-features = false +optional = true + +[dependencies.frame-support] +path = "../substrate/frame/support" +default-features = false +optional = true + +[dependencies.frame-support-procedural] +path = "../substrate/frame/support/procedural" +default-features = false +optional = true + +[dependencies.frame-support-procedural-tools-derive] +path = "../substrate/frame/support/procedural/tools/derive" +default-features = false +optional = true + +[dependencies.frame-system] +path = "../substrate/frame/system" +default-features = false +optional = true + +[dependencies.frame-system-benchmarking] +path = "../substrate/frame/system/benchmarking" +default-features = false +optional = true + +[dependencies.frame-system-rpc-runtime-api] +path = "../substrate/frame/system/rpc/runtime-api" +default-features = false +optional = true + +[dependencies.frame-try-runtime] +path = "../substrate/frame/try-runtime" +default-features = false +optional = true + +[dependencies.pallet-alliance] +path = "../substrate/frame/alliance" +default-features = false +optional = true + +[dependencies.pallet-asset-conversion] +path = "../substrate/frame/asset-conversion" +default-features = false +optional = true + +[dependencies.pallet-asset-conversion-ops] +path = "../substrate/frame/asset-conversion/ops" +default-features = false +optional = true + +[dependencies.pallet-asset-conversion-tx-payment] +path = "../substrate/frame/transaction-payment/asset-conversion-tx-payment" +default-features = false +optional = true + +[dependencies.pallet-asset-rate] +path = "../substrate/frame/asset-rate" +default-features = false +optional = true + +[dependencies.pallet-asset-tx-payment] +path = "../substrate/frame/transaction-payment/asset-tx-payment" +default-features = false +optional = true + +[dependencies.pallet-assets] +path = "../substrate/frame/assets" +default-features = false +optional = true + +[dependencies.pallet-atomic-swap] +path = "../substrate/frame/atomic-swap" +default-features = false +optional = true + +[dependencies.pallet-aura] +path = "../substrate/frame/aura" +default-features = false +optional = true + +[dependencies.pallet-authority-discovery] +path = "../substrate/frame/authority-discovery" +default-features = false +optional = true + +[dependencies.pallet-authorship] +path = "../substrate/frame/authorship" +default-features = false +optional = true + +[dependencies.pallet-babe] +path = "../substrate/frame/babe" +default-features = false +optional = true + +[dependencies.pallet-bags-list] +path = "../substrate/frame/bags-list" +default-features = false +optional = true + +[dependencies.pallet-balances] +path = "../substrate/frame/balances" +default-features = false +optional = true + +[dependencies.pallet-beefy] +path = "../substrate/frame/beefy" +default-features = false +optional = true + +[dependencies.pallet-beefy-mmr] +path = "../substrate/frame/beefy-mmr" +default-features = false +optional = true + +[dependencies.pallet-bounties] +path = "../substrate/frame/bounties" +default-features = false +optional = true + +[dependencies.pallet-bridge-grandpa] +path = "../bridges/modules/grandpa" +default-features = false +optional = true + +[dependencies.pallet-bridge-messages] +path = "../bridges/modules/messages" +default-features = false +optional = true + +[dependencies.pallet-bridge-parachains] +path = "../bridges/modules/parachains" +default-features = false +optional = true + +[dependencies.pallet-bridge-relayers] +path = "../bridges/modules/relayers" +default-features = false +optional = true + +[dependencies.pallet-broker] +path = "../substrate/frame/broker" +default-features = false +optional = true + +[dependencies.pallet-child-bounties] +path = "../substrate/frame/child-bounties" +default-features = false +optional = true + +[dependencies.pallet-collator-selection] +path = "../cumulus/pallets/collator-selection" +default-features = false +optional = true + +[dependencies.pallet-collective] +path = "../substrate/frame/collective" +default-features = false +optional = true + +[dependencies.pallet-collective-content] +path = "../cumulus/parachains/pallets/collective-content" +default-features = false +optional = true + +[dependencies.pallet-contracts] +path = "../substrate/frame/contracts" +default-features = false +optional = true + +[dependencies.pallet-contracts-proc-macro] +path = "../substrate/frame/contracts/proc-macro" +default-features = false +optional = true + +[dependencies.pallet-contracts-uapi] +path = "../substrate/frame/contracts/uapi" +default-features = false +optional = true + +[dependencies.pallet-conviction-voting] +path = "../substrate/frame/conviction-voting" +default-features = false +optional = true + +[dependencies.pallet-core-fellowship] +path = "../substrate/frame/core-fellowship" +default-features = false +optional = true + +[dependencies.pallet-delegated-staking] +path = "../substrate/frame/delegated-staking" +default-features = false +optional = true + +[dependencies.pallet-democracy] +path = "../substrate/frame/democracy" +default-features = false +optional = true + +[dependencies.pallet-dev-mode] +path = "../substrate/frame/examples/dev-mode" +default-features = false +optional = true + +[dependencies.pallet-election-provider-multi-phase] +path = "../substrate/frame/election-provider-multi-phase" +default-features = false +optional = true + +[dependencies.pallet-election-provider-support-benchmarking] +path = "../substrate/frame/election-provider-support/benchmarking" +default-features = false +optional = true + +[dependencies.pallet-elections-phragmen] +path = "../substrate/frame/elections-phragmen" +default-features = false +optional = true + +[dependencies.pallet-fast-unstake] +path = "../substrate/frame/fast-unstake" +default-features = false +optional = true + +[dependencies.pallet-glutton] +path = "../substrate/frame/glutton" +default-features = false +optional = true + +[dependencies.pallet-grandpa] +path = "../substrate/frame/grandpa" +default-features = false +optional = true + +[dependencies.pallet-identity] +path = "../substrate/frame/identity" +default-features = false +optional = true + +[dependencies.pallet-im-online] +path = "../substrate/frame/im-online" +default-features = false +optional = true + +[dependencies.pallet-indices] +path = "../substrate/frame/indices" +default-features = false +optional = true + +[dependencies.pallet-insecure-randomness-collective-flip] +path = "../substrate/frame/insecure-randomness-collective-flip" +default-features = false +optional = true + +[dependencies.pallet-lottery] +path = "../substrate/frame/lottery" +default-features = false +optional = true + +[dependencies.pallet-membership] +path = "../substrate/frame/membership" +default-features = false +optional = true + +[dependencies.pallet-message-queue] +path = "../substrate/frame/message-queue" +default-features = false +optional = true + +[dependencies.pallet-migrations] +path = "../substrate/frame/migrations" +default-features = false +optional = true + +[dependencies.pallet-mixnet] +path = "../substrate/frame/mixnet" +default-features = false +optional = true + +[dependencies.pallet-mmr] +path = "../substrate/frame/merkle-mountain-range" +default-features = false +optional = true + +[dependencies.pallet-multisig] +path = "../substrate/frame/multisig" +default-features = false +optional = true + +[dependencies.pallet-nft-fractionalization] +path = "../substrate/frame/nft-fractionalization" +default-features = false +optional = true + +[dependencies.pallet-nfts] +path = "../substrate/frame/nfts" +default-features = false +optional = true + +[dependencies.pallet-nfts-runtime-api] +path = "../substrate/frame/nfts/runtime-api" +default-features = false +optional = true + +[dependencies.pallet-nis] +path = "../substrate/frame/nis" +default-features = false +optional = true + +[dependencies.pallet-node-authorization] +path = "../substrate/frame/node-authorization" +default-features = false +optional = true + +[dependencies.pallet-nomination-pools] +path = "../substrate/frame/nomination-pools" +default-features = false +optional = true + +[dependencies.pallet-nomination-pools-benchmarking] +path = "../substrate/frame/nomination-pools/benchmarking" +default-features = false +optional = true + +[dependencies.pallet-nomination-pools-runtime-api] +path = "../substrate/frame/nomination-pools/runtime-api" +default-features = false +optional = true + +[dependencies.pallet-offences] +path = "../substrate/frame/offences" +default-features = false +optional = true + +[dependencies.pallet-offences-benchmarking] +path = "../substrate/frame/offences/benchmarking" +default-features = false +optional = true + +[dependencies.pallet-paged-list] +path = "../substrate/frame/paged-list" +default-features = false +optional = true + +[dependencies.pallet-parameters] +path = "../substrate/frame/parameters" +default-features = false +optional = true + +[dependencies.pallet-preimage] +path = "../substrate/frame/preimage" +default-features = false +optional = true + +[dependencies.pallet-proxy] +path = "../substrate/frame/proxy" +default-features = false +optional = true + +[dependencies.pallet-ranked-collective] +path = "../substrate/frame/ranked-collective" +default-features = false +optional = true + +[dependencies.pallet-recovery] +path = "../substrate/frame/recovery" +default-features = false +optional = true + +[dependencies.pallet-referenda] +path = "../substrate/frame/referenda" +default-features = false +optional = true + +[dependencies.pallet-remark] +path = "../substrate/frame/remark" +default-features = false +optional = true + +[dependencies.pallet-root-offences] +path = "../substrate/frame/root-offences" +default-features = false +optional = true + +[dependencies.pallet-root-testing] +path = "../substrate/frame/root-testing" +default-features = false +optional = true + +[dependencies.pallet-safe-mode] +path = "../substrate/frame/safe-mode" +default-features = false +optional = true + +[dependencies.pallet-salary] +path = "../substrate/frame/salary" +default-features = false +optional = true + +[dependencies.pallet-scheduler] +path = "../substrate/frame/scheduler" +default-features = false +optional = true + +[dependencies.pallet-scored-pool] +path = "../substrate/frame/scored-pool" +default-features = false +optional = true + +[dependencies.pallet-session] +path = "../substrate/frame/session" +default-features = false +optional = true + +[dependencies.pallet-session-benchmarking] +path = "../substrate/frame/session/benchmarking" +default-features = false +optional = true + +[dependencies.pallet-skip-feeless-payment] +path = "../substrate/frame/transaction-payment/skip-feeless-payment" +default-features = false +optional = true + +[dependencies.pallet-society] +path = "../substrate/frame/society" +default-features = false +optional = true + +[dependencies.pallet-staking] +path = "../substrate/frame/staking" +default-features = false +optional = true + +[dependencies.pallet-staking-reward-curve] +path = "../substrate/frame/staking/reward-curve" +default-features = false +optional = true + +[dependencies.pallet-staking-reward-fn] +path = "../substrate/frame/staking/reward-fn" +default-features = false +optional = true + +[dependencies.pallet-staking-runtime-api] +path = "../substrate/frame/staking/runtime-api" +default-features = false +optional = true + +[dependencies.pallet-state-trie-migration] +path = "../substrate/frame/state-trie-migration" +default-features = false +optional = true + +[dependencies.pallet-statement] +path = "../substrate/frame/statement" +default-features = false +optional = true + +[dependencies.pallet-sudo] +path = "../substrate/frame/sudo" +default-features = false +optional = true + +[dependencies.pallet-timestamp] +path = "../substrate/frame/timestamp" +default-features = false +optional = true + +[dependencies.pallet-tips] +path = "../substrate/frame/tips" +default-features = false +optional = true + +[dependencies.pallet-transaction-payment] +path = "../substrate/frame/transaction-payment" +default-features = false +optional = true + +[dependencies.pallet-transaction-payment-rpc-runtime-api] +path = "../substrate/frame/transaction-payment/rpc/runtime-api" +default-features = false +optional = true + +[dependencies.pallet-transaction-storage] +path = "../substrate/frame/transaction-storage" +default-features = false +optional = true + +[dependencies.pallet-treasury] +path = "../substrate/frame/treasury" +default-features = false +optional = true + +[dependencies.pallet-tx-pause] +path = "../substrate/frame/tx-pause" +default-features = false +optional = true + +[dependencies.pallet-uniques] +path = "../substrate/frame/uniques" +default-features = false +optional = true + +[dependencies.pallet-utility] +path = "../substrate/frame/utility" +default-features = false +optional = true + +[dependencies.pallet-vesting] +path = "../substrate/frame/vesting" +default-features = false +optional = true + +[dependencies.pallet-whitelist] +path = "../substrate/frame/whitelist" +default-features = false +optional = true + +[dependencies.pallet-xcm] +path = "../polkadot/xcm/pallet-xcm" +default-features = false +optional = true + +[dependencies.pallet-xcm-benchmarks] +path = "../polkadot/xcm/pallet-xcm-benchmarks" +default-features = false +optional = true + +[dependencies.pallet-xcm-bridge-hub] +path = "../bridges/modules/xcm-bridge-hub" +default-features = false +optional = true + +[dependencies.pallet-xcm-bridge-hub-router] +path = "../bridges/modules/xcm-bridge-hub-router" +default-features = false +optional = true + +[dependencies.parachains-common] +path = "../cumulus/parachains/common" +default-features = false +optional = true + +[dependencies.polkadot-core-primitives] +path = "../polkadot/core-primitives" +default-features = false +optional = true + +[dependencies.polkadot-parachain-primitives] +path = "../polkadot/parachain" +default-features = false +optional = true + +[dependencies.polkadot-primitives] +path = "../polkadot/primitives" +default-features = false +optional = true + +[dependencies.polkadot-runtime-common] +path = "../polkadot/runtime/common" +default-features = false +optional = true + +[dependencies.polkadot-runtime-metrics] +path = "../polkadot/runtime/metrics" +default-features = false +optional = true + +[dependencies.polkadot-runtime-parachains] +path = "../polkadot/runtime/parachains" +default-features = false +optional = true + +[dependencies.polkadot-sdk-frame] +path = "../substrate/frame" +default-features = false +optional = true + +[dependencies.rococo-runtime-constants] +path = "../polkadot/runtime/rococo/constants" +default-features = false +optional = true + +[dependencies.sc-chain-spec-derive] +path = "../substrate/client/chain-spec/derive" +default-features = false +optional = true + +[dependencies.sc-tracing-proc-macro] +path = "../substrate/client/tracing/proc-macro" +default-features = false +optional = true + +[dependencies.slot-range-helper] +path = "../polkadot/runtime/common/slot_range_helper" +default-features = false +optional = true + +[dependencies.snowbridge-beacon-primitives] +path = "../bridges/snowbridge/primitives/beacon" +default-features = false +optional = true + +[dependencies.snowbridge-core] +path = "../bridges/snowbridge/primitives/core" +default-features = false +optional = true + +[dependencies.snowbridge-ethereum] +path = "../bridges/snowbridge/primitives/ethereum" +default-features = false +optional = true + +[dependencies.snowbridge-outbound-queue-merkle-tree] +path = "../bridges/snowbridge/pallets/outbound-queue/merkle-tree" +default-features = false +optional = true + +[dependencies.snowbridge-outbound-queue-runtime-api] +path = "../bridges/snowbridge/pallets/outbound-queue/runtime-api" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-ethereum-client] +path = "../bridges/snowbridge/pallets/ethereum-client" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-ethereum-client-fixtures] +path = "../bridges/snowbridge/pallets/ethereum-client/fixtures" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-inbound-queue] +path = "../bridges/snowbridge/pallets/inbound-queue" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-inbound-queue-fixtures] +path = "../bridges/snowbridge/pallets/inbound-queue/fixtures" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-outbound-queue] +path = "../bridges/snowbridge/pallets/outbound-queue" +default-features = false +optional = true + +[dependencies.snowbridge-pallet-system] +path = "../bridges/snowbridge/pallets/system" +default-features = false +optional = true + +[dependencies.snowbridge-router-primitives] +path = "../bridges/snowbridge/primitives/router" +default-features = false +optional = true + +[dependencies.snowbridge-runtime-common] +path = "../bridges/snowbridge/runtime/runtime-common" +default-features = false +optional = true + +[dependencies.snowbridge-system-runtime-api] +path = "../bridges/snowbridge/pallets/system/runtime-api" +default-features = false +optional = true + +[dependencies.sp-api] +path = "../substrate/primitives/api" +default-features = false +optional = true + +[dependencies.sp-api-proc-macro] +path = "../substrate/primitives/api/proc-macro" +default-features = false +optional = true + +[dependencies.sp-application-crypto] +path = "../substrate/primitives/application-crypto" +default-features = false +optional = true + +[dependencies.sp-arithmetic] +path = "../substrate/primitives/arithmetic" +default-features = false +optional = true + +[dependencies.sp-authority-discovery] +path = "../substrate/primitives/authority-discovery" +default-features = false +optional = true + +[dependencies.sp-block-builder] +path = "../substrate/primitives/block-builder" +default-features = false +optional = true + +[dependencies.sp-consensus-aura] +path = "../substrate/primitives/consensus/aura" +default-features = false +optional = true + +[dependencies.sp-consensus-babe] +path = "../substrate/primitives/consensus/babe" +default-features = false +optional = true + +[dependencies.sp-consensus-beefy] +path = "../substrate/primitives/consensus/beefy" +default-features = false +optional = true + +[dependencies.sp-consensus-grandpa] +path = "../substrate/primitives/consensus/grandpa" +default-features = false +optional = true + +[dependencies.sp-consensus-pow] +path = "../substrate/primitives/consensus/pow" +default-features = false +optional = true + +[dependencies.sp-consensus-slots] +path = "../substrate/primitives/consensus/slots" +default-features = false +optional = true + +[dependencies.sp-core] +path = "../substrate/primitives/core" +default-features = false +optional = true + +[dependencies.sp-crypto-ec-utils] +path = "../substrate/primitives/crypto/ec-utils" +default-features = false +optional = true + +[dependencies.sp-crypto-hashing] +path = "../substrate/primitives/crypto/hashing" +default-features = false +optional = true + +[dependencies.sp-crypto-hashing-proc-macro] +path = "../substrate/primitives/crypto/hashing/proc-macro" +default-features = false +optional = true + +[dependencies.sp-debug-derive] +path = "../substrate/primitives/debug-derive" +default-features = false +optional = true + +[dependencies.sp-externalities] +path = "../substrate/primitives/externalities" +default-features = false +optional = true + +[dependencies.sp-genesis-builder] +path = "../substrate/primitives/genesis-builder" +default-features = false +optional = true + +[dependencies.sp-inherents] +path = "../substrate/primitives/inherents" +default-features = false +optional = true + +[dependencies.sp-io] +path = "../substrate/primitives/io" +default-features = false +optional = true + +[dependencies.sp-keyring] +path = "../substrate/primitives/keyring" +default-features = false +optional = true + +[dependencies.sp-keystore] +path = "../substrate/primitives/keystore" +default-features = false +optional = true + +[dependencies.sp-metadata-ir] +path = "../substrate/primitives/metadata-ir" +default-features = false +optional = true + +[dependencies.sp-mixnet] +path = "../substrate/primitives/mixnet" +default-features = false +optional = true + +[dependencies.sp-mmr-primitives] +path = "../substrate/primitives/merkle-mountain-range" +default-features = false +optional = true + +[dependencies.sp-npos-elections] +path = "../substrate/primitives/npos-elections" +default-features = false +optional = true + +[dependencies.sp-offchain] +path = "../substrate/primitives/offchain" +default-features = false +optional = true + +[dependencies.sp-runtime] +path = "../substrate/primitives/runtime" +default-features = false +optional = true + +[dependencies.sp-runtime-interface] +path = "../substrate/primitives/runtime-interface" +default-features = false +optional = true + +[dependencies.sp-runtime-interface-proc-macro] +path = "../substrate/primitives/runtime-interface/proc-macro" +default-features = false +optional = true + +[dependencies.sp-session] +path = "../substrate/primitives/session" +default-features = false +optional = true + +[dependencies.sp-staking] +path = "../substrate/primitives/staking" +default-features = false +optional = true + +[dependencies.sp-state-machine] +path = "../substrate/primitives/state-machine" +default-features = false +optional = true + +[dependencies.sp-statement-store] +path = "../substrate/primitives/statement-store" +default-features = false +optional = true + +[dependencies.sp-std] +path = "../substrate/primitives/std" +default-features = false +optional = true + +[dependencies.sp-storage] +path = "../substrate/primitives/storage" +default-features = false +optional = true + +[dependencies.sp-timestamp] +path = "../substrate/primitives/timestamp" +default-features = false +optional = true + +[dependencies.sp-tracing] +path = "../substrate/primitives/tracing" +default-features = false +optional = true + +[dependencies.sp-transaction-pool] +path = "../substrate/primitives/transaction-pool" +default-features = false +optional = true + +[dependencies.sp-transaction-storage-proof] +path = "../substrate/primitives/transaction-storage-proof" +default-features = false +optional = true + +[dependencies.sp-trie] +path = "../substrate/primitives/trie" +default-features = false +optional = true + +[dependencies.sp-version] +path = "../substrate/primitives/version" +default-features = false +optional = true + +[dependencies.sp-version-proc-macro] +path = "../substrate/primitives/version/proc-macro" +default-features = false +optional = true + +[dependencies.sp-wasm-interface] +path = "../substrate/primitives/wasm-interface" +default-features = false +optional = true + +[dependencies.sp-weights] +path = "../substrate/primitives/weights" +default-features = false +optional = true + +[dependencies.staging-parachain-info] +path = "../cumulus/parachains/pallets/parachain-info" +default-features = false +optional = true + +[dependencies.staging-xcm] +path = "../polkadot/xcm" +default-features = false +optional = true + +[dependencies.staging-xcm-builder] +path = "../polkadot/xcm/xcm-builder" +default-features = false +optional = true + +[dependencies.staging-xcm-executor] +path = "../polkadot/xcm/xcm-executor" +default-features = false +optional = true + +[dependencies.substrate-bip39] +path = "../substrate/utils/substrate-bip39" +default-features = false +optional = true + +[dependencies.testnet-parachains-constants] +path = "../cumulus/parachains/runtimes/constants" +default-features = false +optional = true + +[dependencies.tracing-gum-proc-macro] +path = "../polkadot/node/gum/proc-macro" +default-features = false +optional = true + +[dependencies.westend-runtime-constants] +path = "../polkadot/runtime/westend/constants" +default-features = false +optional = true + +[dependencies.xcm-fee-payment-runtime-api] +path = "../polkadot/xcm/xcm-fee-payment-runtime-api" +default-features = false +optional = true + +[dependencies.xcm-procedural] +path = "../polkadot/xcm/procedural" +default-features = false +optional = true + +[dependencies.asset-test-utils] +path = "../cumulus/parachains/runtimes/assets/test-utils" +default-features = false +optional = true + +[dependencies.bridge-hub-test-utils] +path = "../cumulus/parachains/runtimes/bridge-hubs/test-utils" +default-features = false +optional = true + +[dependencies.cumulus-client-cli] +path = "../cumulus/client/cli" +default-features = false +optional = true + +[dependencies.cumulus-client-collator] +path = "../cumulus/client/collator" +default-features = false +optional = true + +[dependencies.cumulus-client-consensus-aura] +path = "../cumulus/client/consensus/aura" +default-features = false +optional = true + +[dependencies.cumulus-client-consensus-common] +path = "../cumulus/client/consensus/common" +default-features = false +optional = true + +[dependencies.cumulus-client-consensus-proposer] +path = "../cumulus/client/consensus/proposer" +default-features = false +optional = true + +[dependencies.cumulus-client-consensus-relay-chain] +path = "../cumulus/client/consensus/relay-chain" +default-features = false +optional = true + +[dependencies.cumulus-client-network] +path = "../cumulus/client/network" +default-features = false +optional = true + +[dependencies.cumulus-client-parachain-inherent] +path = "../cumulus/client/parachain-inherent" +default-features = false +optional = true + +[dependencies.cumulus-client-pov-recovery] +path = "../cumulus/client/pov-recovery" +default-features = false +optional = true + +[dependencies.cumulus-client-service] +path = "../cumulus/client/service" +default-features = false +optional = true + +[dependencies.cumulus-relay-chain-inprocess-interface] +path = "../cumulus/client/relay-chain-inprocess-interface" +default-features = false +optional = true + +[dependencies.cumulus-relay-chain-interface] +path = "../cumulus/client/relay-chain-interface" +default-features = false +optional = true + +[dependencies.cumulus-relay-chain-minimal-node] +path = "../cumulus/client/relay-chain-minimal-node" +default-features = false +optional = true + +[dependencies.cumulus-relay-chain-rpc-interface] +path = "../cumulus/client/relay-chain-rpc-interface" +default-features = false +optional = true + +[dependencies.cumulus-test-relay-sproof-builder] +path = "../cumulus/test/relay-sproof-builder" +default-features = false +optional = true + +[dependencies.emulated-integration-tests-common] +path = "../cumulus/parachains/integration-tests/emulated/common" +default-features = false +optional = true + +[dependencies.fork-tree] +path = "../substrate/utils/fork-tree" +default-features = false +optional = true + +[dependencies.frame-benchmarking-cli] +path = "../substrate/utils/frame/benchmarking-cli" +default-features = false +optional = true + +[dependencies.frame-remote-externalities] +path = "../substrate/utils/frame/remote-externalities" +default-features = false +optional = true + +[dependencies.frame-support-procedural-tools] +path = "../substrate/frame/support/procedural/tools" +default-features = false +optional = true + +[dependencies.generate-bags] +path = "../substrate/utils/frame/generate-bags" +default-features = false +optional = true + +[dependencies.mmr-gadget] +path = "../substrate/client/merkle-mountain-range" +default-features = false +optional = true + +[dependencies.mmr-rpc] +path = "../substrate/client/merkle-mountain-range/rpc" +default-features = false +optional = true + +[dependencies.pallet-contracts-mock-network] +path = "../substrate/frame/contracts/mock-network" +default-features = false +optional = true + +[dependencies.pallet-transaction-payment-rpc] +path = "../substrate/frame/transaction-payment/rpc" +default-features = false +optional = true + +[dependencies.parachains-runtimes-test-utils] +path = "../cumulus/parachains/runtimes/test-utils" +default-features = false +optional = true + +[dependencies.polkadot-approval-distribution] +path = "../polkadot/node/network/approval-distribution" +default-features = false +optional = true + +[dependencies.polkadot-availability-bitfield-distribution] +path = "../polkadot/node/network/bitfield-distribution" +default-features = false +optional = true + +[dependencies.polkadot-availability-distribution] +path = "../polkadot/node/network/availability-distribution" +default-features = false +optional = true + +[dependencies.polkadot-availability-recovery] +path = "../polkadot/node/network/availability-recovery" +default-features = false +optional = true + +[dependencies.polkadot-cli] +path = "../polkadot/cli" +default-features = false +optional = true + +[dependencies.polkadot-collator-protocol] +path = "../polkadot/node/network/collator-protocol" +default-features = false +optional = true + +[dependencies.polkadot-dispute-distribution] +path = "../polkadot/node/network/dispute-distribution" +default-features = false +optional = true + +[dependencies.polkadot-erasure-coding] +path = "../polkadot/erasure-coding" +default-features = false +optional = true + +[dependencies.polkadot-gossip-support] +path = "../polkadot/node/network/gossip-support" +default-features = false +optional = true + +[dependencies.polkadot-network-bridge] +path = "../polkadot/node/network/bridge" +default-features = false +optional = true + +[dependencies.polkadot-node-collation-generation] +path = "../polkadot/node/collation-generation" +default-features = false +optional = true + +[dependencies.polkadot-node-core-approval-voting] +path = "../polkadot/node/core/approval-voting" +default-features = false +optional = true + +[dependencies.polkadot-node-core-av-store] +path = "../polkadot/node/core/av-store" +default-features = false +optional = true + +[dependencies.polkadot-node-core-backing] +path = "../polkadot/node/core/backing" +default-features = false +optional = true + +[dependencies.polkadot-node-core-bitfield-signing] +path = "../polkadot/node/core/bitfield-signing" +default-features = false +optional = true + +[dependencies.polkadot-node-core-candidate-validation] +path = "../polkadot/node/core/candidate-validation" +default-features = false +optional = true + +[dependencies.polkadot-node-core-chain-api] +path = "../polkadot/node/core/chain-api" +default-features = false +optional = true + +[dependencies.polkadot-node-core-chain-selection] +path = "../polkadot/node/core/chain-selection" +default-features = false +optional = true + +[dependencies.polkadot-node-core-dispute-coordinator] +path = "../polkadot/node/core/dispute-coordinator" +default-features = false +optional = true + +[dependencies.polkadot-node-core-parachains-inherent] +path = "../polkadot/node/core/parachains-inherent" +default-features = false +optional = true + +[dependencies.polkadot-node-core-prospective-parachains] +path = "../polkadot/node/core/prospective-parachains" +default-features = false +optional = true + +[dependencies.polkadot-node-core-provisioner] +path = "../polkadot/node/core/provisioner" +default-features = false +optional = true + +[dependencies.polkadot-node-core-pvf] +path = "../polkadot/node/core/pvf" +default-features = false +optional = true + +[dependencies.polkadot-node-core-pvf-checker] +path = "../polkadot/node/core/pvf-checker" +default-features = false +optional = true + +[dependencies.polkadot-node-core-pvf-common] +path = "../polkadot/node/core/pvf/common" +default-features = false +optional = true + +[dependencies.polkadot-node-core-pvf-execute-worker] +path = "../polkadot/node/core/pvf/execute-worker" +default-features = false +optional = true + +[dependencies.polkadot-node-core-pvf-prepare-worker] +path = "../polkadot/node/core/pvf/prepare-worker" +default-features = false +optional = true + +[dependencies.polkadot-node-core-runtime-api] +path = "../polkadot/node/core/runtime-api" +default-features = false +optional = true + +[dependencies.polkadot-node-jaeger] +path = "../polkadot/node/jaeger" +default-features = false +optional = true + +[dependencies.polkadot-node-metrics] +path = "../polkadot/node/metrics" +default-features = false +optional = true + +[dependencies.polkadot-node-network-protocol] +path = "../polkadot/node/network/protocol" +default-features = false +optional = true + +[dependencies.polkadot-node-primitives] +path = "../polkadot/node/primitives" +default-features = false +optional = true + +[dependencies.polkadot-node-subsystem] +path = "../polkadot/node/subsystem" +default-features = false +optional = true + +[dependencies.polkadot-node-subsystem-types] +path = "../polkadot/node/subsystem-types" +default-features = false +optional = true + +[dependencies.polkadot-node-subsystem-util] +path = "../polkadot/node/subsystem-util" +default-features = false +optional = true + +[dependencies.polkadot-overseer] +path = "../polkadot/node/overseer" +default-features = false +optional = true + +[dependencies.polkadot-rpc] +path = "../polkadot/rpc" +default-features = false +optional = true + +[dependencies.polkadot-service] +path = "../polkadot/node/service" +default-features = false +optional = true + +[dependencies.polkadot-statement-distribution] +path = "../polkadot/node/network/statement-distribution" +default-features = false +optional = true + +[dependencies.polkadot-statement-table] +path = "../polkadot/statement-table" +default-features = false +optional = true + +[dependencies.sc-allocator] +path = "../substrate/client/allocator" +default-features = false +optional = true + +[dependencies.sc-authority-discovery] +path = "../substrate/client/authority-discovery" +default-features = false +optional = true + +[dependencies.sc-basic-authorship] +path = "../substrate/client/basic-authorship" +default-features = false +optional = true + +[dependencies.sc-block-builder] +path = "../substrate/client/block-builder" +default-features = false +optional = true + +[dependencies.sc-chain-spec] +path = "../substrate/client/chain-spec" +default-features = false +optional = true + +[dependencies.sc-cli] +path = "../substrate/client/cli" +default-features = false +optional = true + +[dependencies.sc-client-api] +path = "../substrate/client/api" +default-features = false +optional = true + +[dependencies.sc-client-db] +path = "../substrate/client/db" +default-features = false +optional = true + +[dependencies.sc-consensus] +path = "../substrate/client/consensus/common" +default-features = false +optional = true + +[dependencies.sc-consensus-aura] +path = "../substrate/client/consensus/aura" +default-features = false +optional = true + +[dependencies.sc-consensus-babe] +path = "../substrate/client/consensus/babe" +default-features = false +optional = true + +[dependencies.sc-consensus-babe-rpc] +path = "../substrate/client/consensus/babe/rpc" +default-features = false +optional = true + +[dependencies.sc-consensus-beefy] +path = "../substrate/client/consensus/beefy" +default-features = false +optional = true + +[dependencies.sc-consensus-beefy-rpc] +path = "../substrate/client/consensus/beefy/rpc" +default-features = false +optional = true + +[dependencies.sc-consensus-epochs] +path = "../substrate/client/consensus/epochs" +default-features = false +optional = true + +[dependencies.sc-consensus-grandpa] +path = "../substrate/client/consensus/grandpa" +default-features = false +optional = true + +[dependencies.sc-consensus-grandpa-rpc] +path = "../substrate/client/consensus/grandpa/rpc" +default-features = false +optional = true + +[dependencies.sc-consensus-manual-seal] +path = "../substrate/client/consensus/manual-seal" +default-features = false +optional = true + +[dependencies.sc-consensus-pow] +path = "../substrate/client/consensus/pow" +default-features = false +optional = true + +[dependencies.sc-consensus-slots] +path = "../substrate/client/consensus/slots" +default-features = false +optional = true + +[dependencies.sc-executor] +path = "../substrate/client/executor" +default-features = false +optional = true + +[dependencies.sc-executor-common] +path = "../substrate/client/executor/common" +default-features = false +optional = true + +[dependencies.sc-executor-polkavm] +path = "../substrate/client/executor/polkavm" +default-features = false +optional = true + +[dependencies.sc-executor-wasmtime] +path = "../substrate/client/executor/wasmtime" +default-features = false +optional = true + +[dependencies.sc-informant] +path = "../substrate/client/informant" +default-features = false +optional = true + +[dependencies.sc-keystore] +path = "../substrate/client/keystore" +default-features = false +optional = true + +[dependencies.sc-mixnet] +path = "../substrate/client/mixnet" +default-features = false +optional = true + +[dependencies.sc-network] +path = "../substrate/client/network" +default-features = false +optional = true + +[dependencies.sc-network-common] +path = "../substrate/client/network/common" +default-features = false +optional = true + +[dependencies.sc-network-gossip] +path = "../substrate/client/network-gossip" +default-features = false +optional = true + +[dependencies.sc-network-light] +path = "../substrate/client/network/light" +default-features = false +optional = true + +[dependencies.sc-network-statement] +path = "../substrate/client/network/statement" +default-features = false +optional = true + +[dependencies.sc-network-sync] +path = "../substrate/client/network/sync" +default-features = false +optional = true + +[dependencies.sc-network-transactions] +path = "../substrate/client/network/transactions" +default-features = false +optional = true + +[dependencies.sc-network-types] +path = "../substrate/client/network/types" +default-features = false +optional = true + +[dependencies.sc-offchain] +path = "../substrate/client/offchain" +default-features = false +optional = true + +[dependencies.sc-proposer-metrics] +path = "../substrate/client/proposer-metrics" +default-features = false +optional = true + +[dependencies.sc-rpc] +path = "../substrate/client/rpc" +default-features = false +optional = true + +[dependencies.sc-rpc-api] +path = "../substrate/client/rpc-api" +default-features = false +optional = true + +[dependencies.sc-rpc-server] +path = "../substrate/client/rpc-servers" +default-features = false +optional = true + +[dependencies.sc-rpc-spec-v2] +path = "../substrate/client/rpc-spec-v2" +default-features = false +optional = true + +[dependencies.sc-service] +path = "../substrate/client/service" +default-features = false +optional = true + +[dependencies.sc-state-db] +path = "../substrate/client/state-db" +default-features = false +optional = true + +[dependencies.sc-statement-store] +path = "../substrate/client/statement-store" +default-features = false +optional = true + +[dependencies.sc-storage-monitor] +path = "../substrate/client/storage-monitor" +default-features = false +optional = true + +[dependencies.sc-sync-state-rpc] +path = "../substrate/client/sync-state-rpc" +default-features = false +optional = true + +[dependencies.sc-sysinfo] +path = "../substrate/client/sysinfo" +default-features = false +optional = true + +[dependencies.sc-telemetry] +path = "../substrate/client/telemetry" +default-features = false +optional = true + +[dependencies.sc-tracing] +path = "../substrate/client/tracing" +default-features = false +optional = true + +[dependencies.sc-transaction-pool] +path = "../substrate/client/transaction-pool" +default-features = false +optional = true + +[dependencies.sc-transaction-pool-api] +path = "../substrate/client/transaction-pool/api" +default-features = false +optional = true + +[dependencies.sc-utils] +path = "../substrate/client/utils" +default-features = false +optional = true + +[dependencies.snowbridge-runtime-test-common] +path = "../bridges/snowbridge/runtime/test-common" +default-features = false +optional = true + +[dependencies.sp-blockchain] +path = "../substrate/primitives/blockchain" +default-features = false +optional = true + +[dependencies.sp-consensus] +path = "../substrate/primitives/consensus/common" +default-features = false +optional = true + +[dependencies.sp-core-hashing] +path = "../substrate/deprecated/hashing" +default-features = false +optional = true + +[dependencies.sp-core-hashing-proc-macro] +path = "../substrate/deprecated/hashing/proc-macro" +default-features = false +optional = true + +[dependencies.sp-database] +path = "../substrate/primitives/database" +default-features = false +optional = true + +[dependencies.sp-maybe-compressed-blob] +path = "../substrate/primitives/maybe-compressed-blob" +default-features = false +optional = true + +[dependencies.sp-panic-handler] +path = "../substrate/primitives/panic-handler" +default-features = false +optional = true + +[dependencies.sp-rpc] +path = "../substrate/primitives/rpc" +default-features = false +optional = true + +[dependencies.staging-node-inspect] +path = "../substrate/bin/node/inspect" +default-features = false +optional = true + +[dependencies.staging-tracking-allocator] +path = "../polkadot/node/tracking-allocator" +default-features = false +optional = true + +[dependencies.subkey] +path = "../substrate/bin/utils/subkey" +default-features = false +optional = true + +[dependencies.substrate-build-script-utils] +path = "../substrate/utils/build-script-utils" +default-features = false +optional = true + +[dependencies.substrate-frame-rpc-support] +path = "../substrate/utils/frame/rpc/support" +default-features = false +optional = true + +[dependencies.substrate-frame-rpc-system] +path = "../substrate/utils/frame/rpc/system" +default-features = false +optional = true + +[dependencies.substrate-prometheus-endpoint] +path = "../substrate/utils/prometheus" +default-features = false +optional = true + +[dependencies.substrate-rpc-client] +path = "../substrate/utils/frame/rpc/client" +default-features = false +optional = true + +[dependencies.substrate-state-trie-migration-rpc] +path = "../substrate/utils/frame/rpc/state-trie-migration-rpc" +default-features = false +optional = true + +[dependencies.substrate-wasm-builder] +path = "../substrate/utils/wasm-builder" +default-features = false +optional = true + +[dependencies.tracing-gum] +path = "../polkadot/node/gum" +default-features = false +optional = true + +[dependencies.xcm-emulator] +path = "../cumulus/xcm/xcm-emulator" +default-features = false +optional = true + +[dependencies.xcm-simulator] +path = "../polkadot/xcm/xcm-simulator" +default-features = false +optional = true + +[package.metadata.docs.rs] +features = ["node", "runtime"] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/umbrella/src/lib.rs b/umbrella/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..2e87c186edae83c5d123000a72e9a198d99bf154 --- /dev/null +++ b/umbrella/src/lib.rs @@ -0,0 +1,1564 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +#![cfg_attr(not(feature = "std"), no_std)] + +//! Polkadot SDK umbrella crate re-exporting all other published crates. +//! +//! This helps to set a single version number for all your dependencies. Docs are in the +//! `polkadot-sdk-docs` crate. + +// This file is auto-generated and checked by the CI. You can edit it manually, but it must be +// exactly the way that the CI expects it. + +/// Test utils for Asset Hub runtimes. +#[cfg(feature = "asset-test-utils")] +pub use asset_test_utils; + +/// Assets common utilities. +#[cfg(feature = "assets-common")] +pub use assets_common; + +/// A no-std/Substrate compatible library to construct binary merkle tree. +#[cfg(feature = "binary-merkle-tree")] +pub use binary_merkle_tree; + +/// Primitives of AssetHubRococo parachain runtime. +#[cfg(feature = "bp-asset-hub-rococo")] +pub use bp_asset_hub_rococo; + +/// Primitives of AssetHubWestend parachain runtime. +#[cfg(feature = "bp-asset-hub-westend")] +pub use bp_asset_hub_westend; + +/// Primitives for BridgeHub parachain runtimes. +#[cfg(feature = "bp-bridge-hub-cumulus")] +pub use bp_bridge_hub_cumulus; + +/// Primitives of BridgeHubKusama parachain runtime. +#[cfg(feature = "bp-bridge-hub-kusama")] +pub use bp_bridge_hub_kusama; + +/// Primitives of BridgeHubPolkadot parachain runtime. +#[cfg(feature = "bp-bridge-hub-polkadot")] +pub use bp_bridge_hub_polkadot; + +/// Primitives of BridgeHubRococo parachain runtime. +#[cfg(feature = "bp-bridge-hub-rococo")] +pub use bp_bridge_hub_rococo; + +/// Primitives of BridgeHubWestend parachain runtime. +#[cfg(feature = "bp-bridge-hub-westend")] +pub use bp_bridge_hub_westend; + +/// A common interface for describing what a bridge pallet should be able to do. +#[cfg(feature = "bp-header-chain")] +pub use bp_header_chain; + +/// Primitives of Kusama runtime. +#[cfg(feature = "bp-kusama")] +pub use bp_kusama; + +/// Primitives of messages module. +#[cfg(feature = "bp-messages")] +pub use bp_messages; + +/// Primitives of parachains module. +#[cfg(feature = "bp-parachains")] +pub use bp_parachains; + +/// Primitives of Polkadot runtime. +#[cfg(feature = "bp-polkadot")] +pub use bp_polkadot; + +/// Primitives of Polkadot Bulletin chain runtime. +#[cfg(feature = "bp-polkadot-bulletin")] +pub use bp_polkadot_bulletin; + +/// Primitives of Polkadot-like runtime. +#[cfg(feature = "bp-polkadot-core")] +pub use bp_polkadot_core; + +/// Primitives of relayers module. +#[cfg(feature = "bp-relayers")] +pub use bp_relayers; + +/// Primitives of Rococo runtime. +#[cfg(feature = "bp-rococo")] +pub use bp_rococo; + +/// Primitives that may be used at (bridges) runtime level. +#[cfg(feature = "bp-runtime")] +pub use bp_runtime; + +/// Utilities for testing substrate-based runtime bridge code. +#[cfg(feature = "bp-test-utils")] +pub use bp_test_utils; + +/// Primitives of Westend runtime. +#[cfg(feature = "bp-westend")] +pub use bp_westend; + +/// Primitives of the xcm-bridge-hub pallet. +#[cfg(feature = "bp-xcm-bridge-hub")] +pub use bp_xcm_bridge_hub; + +/// Primitives of the xcm-bridge-hub fee pallet. +#[cfg(feature = "bp-xcm-bridge-hub-router")] +pub use bp_xcm_bridge_hub_router; + +/// Bridge hub common utilities. +#[cfg(feature = "bridge-hub-common")] +pub use bridge_hub_common; + +/// Utils for BridgeHub testing. +#[cfg(feature = "bridge-hub-test-utils")] +pub use bridge_hub_test_utils; + +/// Common types and functions that may be used by substrate-based runtimes of all bridged +/// chains. +#[cfg(feature = "bridge-runtime-common")] +pub use bridge_runtime_common; + +/// Parachain node CLI utilities. +#[cfg(feature = "cumulus-client-cli")] +pub use cumulus_client_cli; + +/// Common node-side functionality and glue code to collate parachain blocks. +#[cfg(feature = "cumulus-client-collator")] +pub use cumulus_client_collator; + +/// AURA consensus algorithm for parachains. +#[cfg(feature = "cumulus-client-consensus-aura")] +pub use cumulus_client_consensus_aura; + +/// Cumulus specific common consensus implementations. +#[cfg(feature = "cumulus-client-consensus-common")] +pub use cumulus_client_consensus_common; + +/// A Substrate `Proposer` for building parachain blocks. +#[cfg(feature = "cumulus-client-consensus-proposer")] +pub use cumulus_client_consensus_proposer; + +/// The relay-chain provided consensus algorithm. +#[cfg(feature = "cumulus-client-consensus-relay-chain")] +pub use cumulus_client_consensus_relay_chain; + +/// Cumulus-specific networking protocol. +#[cfg(feature = "cumulus-client-network")] +pub use cumulus_client_network; + +/// Inherent that needs to be present in every parachain block. Contains messages and a relay +/// chain storage-proof. +#[cfg(feature = "cumulus-client-parachain-inherent")] +pub use cumulus_client_parachain_inherent; + +/// Cumulus-specific networking protocol. +#[cfg(feature = "cumulus-client-pov-recovery")] +pub use cumulus_client_pov_recovery; + +/// Common functions used to assemble the components of a parachain node. +#[cfg(feature = "cumulus-client-service")] +pub use cumulus_client_service; + +/// AURA consensus extension pallet for parachains. +#[cfg(feature = "cumulus-pallet-aura-ext")] +pub use cumulus_pallet_aura_ext; + +/// Migrates messages from the old DMP queue pallet. +#[cfg(feature = "cumulus-pallet-dmp-queue")] +pub use cumulus_pallet_dmp_queue; + +/// Base pallet for cumulus-based parachains. +#[cfg(feature = "cumulus-pallet-parachain-system")] +pub use cumulus_pallet_parachain_system; + +/// Proc macros provided by the parachain-system pallet. +#[cfg(feature = "cumulus-pallet-parachain-system-proc-macro")] +pub use cumulus_pallet_parachain_system_proc_macro; + +/// FRAME sessions pallet benchmarking. +#[cfg(feature = "cumulus-pallet-session-benchmarking")] +pub use cumulus_pallet_session_benchmarking; + +/// Adds functionality to migrate from a Solo to a Parachain. +#[cfg(feature = "cumulus-pallet-solo-to-para")] +pub use cumulus_pallet_solo_to_para; + +/// Pallet for stuff specific to parachains' usage of XCM. +#[cfg(feature = "cumulus-pallet-xcm")] +pub use cumulus_pallet_xcm; + +/// Pallet to queue outbound and inbound XCMP messages. +#[cfg(feature = "cumulus-pallet-xcmp-queue")] +pub use cumulus_pallet_xcmp_queue; + +/// Ping Pallet for Cumulus XCM/UMP testing. +#[cfg(feature = "cumulus-ping")] +pub use cumulus_ping; + +/// Core primitives for Aura in Cumulus. +#[cfg(feature = "cumulus-primitives-aura")] +pub use cumulus_primitives_aura; + +/// Cumulus related core primitive types and traits. +#[cfg(feature = "cumulus-primitives-core")] +pub use cumulus_primitives_core; + +/// Inherent that needs to be present in every parachain block. Contains messages and a relay +/// chain storage-proof. +#[cfg(feature = "cumulus-primitives-parachain-inherent")] +pub use cumulus_primitives_parachain_inherent; + +/// Hostfunction exposing storage proof size to the runtime. +#[cfg(feature = "cumulus-primitives-proof-size-hostfunction")] +pub use cumulus_primitives_proof_size_hostfunction; + +/// Utilities to reclaim storage weight. +#[cfg(feature = "cumulus-primitives-storage-weight-reclaim")] +pub use cumulus_primitives_storage_weight_reclaim; + +/// Provides timestamp related functionality for parachains. +#[cfg(feature = "cumulus-primitives-timestamp")] +pub use cumulus_primitives_timestamp; + +/// Helper datatypes for Cumulus. +#[cfg(feature = "cumulus-primitives-utility")] +pub use cumulus_primitives_utility; + +/// Implementation of the RelayChainInterface trait for Polkadot full-nodes. +#[cfg(feature = "cumulus-relay-chain-inprocess-interface")] +pub use cumulus_relay_chain_inprocess_interface; + +/// Common interface for different relay chain datasources. +#[cfg(feature = "cumulus-relay-chain-interface")] +pub use cumulus_relay_chain_interface; + +/// Minimal node implementation to be used in tandem with RPC or light-client mode. +#[cfg(feature = "cumulus-relay-chain-minimal-node")] +pub use cumulus_relay_chain_minimal_node; + +/// Implementation of the RelayChainInterface trait that connects to a remote RPC-node. +#[cfg(feature = "cumulus-relay-chain-rpc-interface")] +pub use cumulus_relay_chain_rpc_interface; + +/// Mocked relay state proof builder for testing Cumulus. +#[cfg(feature = "cumulus-test-relay-sproof-builder")] +pub use cumulus_test_relay_sproof_builder; + +/// Common resources for integration testing with xcm-emulator. +#[cfg(feature = "emulated-integration-tests-common")] +pub use emulated_integration_tests_common; + +/// Utility library for managing tree-like ordered data with logic for pruning the tree while +/// finalizing nodes. +#[cfg(feature = "fork-tree")] +pub use fork_tree; + +/// Macro for benchmarking a FRAME runtime. +#[cfg(feature = "frame-benchmarking")] +pub use frame_benchmarking; + +/// CLI for benchmarking FRAME. +#[cfg(feature = "frame-benchmarking-cli")] +pub use frame_benchmarking_cli; + +/// Pallet for testing FRAME PoV benchmarking. +#[cfg(feature = "frame-benchmarking-pallet-pov")] +pub use frame_benchmarking_pallet_pov; + +/// NPoS Solution Type. +#[cfg(feature = "frame-election-provider-solution-type")] +pub use frame_election_provider_solution_type; + +/// election provider supporting traits. +#[cfg(feature = "frame-election-provider-support")] +pub use frame_election_provider_support; + +/// FRAME executives engine. +#[cfg(feature = "frame-executive")] +pub use frame_executive; + +/// FRAME signed extension for verifying the metadata hash. +#[cfg(feature = "frame-metadata-hash-extension")] +pub use frame_metadata_hash_extension; + +/// An externalities provided environment that can load itself from remote nodes or cached +/// files. +#[cfg(feature = "frame-remote-externalities")] +pub use frame_remote_externalities; + +/// Support code for the runtime. +#[cfg(feature = "frame-support")] +pub use frame_support; + +/// Proc macro of Support code for the runtime. +#[cfg(feature = "frame-support-procedural")] +pub use frame_support_procedural; + +/// Proc macro helpers for procedural macros. +#[cfg(feature = "frame-support-procedural-tools")] +pub use frame_support_procedural_tools; + +/// Use to derive parsing for parsing struct. +#[cfg(feature = "frame-support-procedural-tools-derive")] +pub use frame_support_procedural_tools_derive; + +/// FRAME system module. +#[cfg(feature = "frame-system")] +pub use frame_system; + +/// FRAME System benchmarking. +#[cfg(feature = "frame-system-benchmarking")] +pub use frame_system_benchmarking; + +/// Runtime API definition required by System RPC extensions. +#[cfg(feature = "frame-system-rpc-runtime-api")] +pub use frame_system_rpc_runtime_api; + +/// FRAME pallet for democracy. +#[cfg(feature = "frame-try-runtime")] +pub use frame_try_runtime; + +/// Bag threshold generation script for pallet-bag-list. +#[cfg(feature = "generate-bags")] +pub use generate_bags; + +/// MMR Client gadget for substrate. +#[cfg(feature = "mmr-gadget")] +pub use mmr_gadget; + +/// Node-specific RPC methods for interaction with Merkle Mountain Range pallet. +#[cfg(feature = "mmr-rpc")] +pub use mmr_rpc; + +/// The Alliance pallet provides a collective for standard-setting industry collaboration. +#[cfg(feature = "pallet-alliance")] +pub use pallet_alliance; + +/// FRAME asset conversion pallet. +#[cfg(feature = "pallet-asset-conversion")] +pub use pallet_asset_conversion; + +/// FRAME asset conversion pallet's operations suite. +#[cfg(feature = "pallet-asset-conversion-ops")] +pub use pallet_asset_conversion_ops; + +/// Pallet to manage transaction payments in assets by converting them to native assets. +#[cfg(feature = "pallet-asset-conversion-tx-payment")] +pub use pallet_asset_conversion_tx_payment; + +/// Whitelist non-native assets for treasury spending and provide conversion to native balance. +#[cfg(feature = "pallet-asset-rate")] +pub use pallet_asset_rate; + +/// pallet to manage transaction payments in assets. +#[cfg(feature = "pallet-asset-tx-payment")] +pub use pallet_asset_tx_payment; + +/// FRAME asset management pallet. +#[cfg(feature = "pallet-assets")] +pub use pallet_assets; + +/// FRAME atomic swap pallet. +#[cfg(feature = "pallet-atomic-swap")] +pub use pallet_atomic_swap; + +/// FRAME AURA consensus pallet. +#[cfg(feature = "pallet-aura")] +pub use pallet_aura; + +/// FRAME pallet for authority discovery. +#[cfg(feature = "pallet-authority-discovery")] +pub use pallet_authority_discovery; + +/// Block and Uncle Author tracking for the FRAME. +#[cfg(feature = "pallet-authorship")] +pub use pallet_authorship; + +/// Consensus extension module for BABE consensus. Collects on-chain randomness from VRF +/// outputs and manages epoch transitions. +#[cfg(feature = "pallet-babe")] +pub use pallet_babe; + +/// FRAME pallet bags list. +#[cfg(feature = "pallet-bags-list")] +pub use pallet_bags_list; + +/// FRAME pallet to manage balances. +#[cfg(feature = "pallet-balances")] +pub use pallet_balances; + +/// BEEFY FRAME pallet. +#[cfg(feature = "pallet-beefy")] +pub use pallet_beefy; + +/// BEEFY + MMR runtime utilities. +#[cfg(feature = "pallet-beefy-mmr")] +pub use pallet_beefy_mmr; + +/// FRAME pallet to manage bounties. +#[cfg(feature = "pallet-bounties")] +pub use pallet_bounties; + +/// Module implementing GRANDPA on-chain light client used for bridging consensus of +/// substrate-based chains. +#[cfg(feature = "pallet-bridge-grandpa")] +pub use pallet_bridge_grandpa; + +/// Module that allows bridged chains to exchange messages using lane concept. +#[cfg(feature = "pallet-bridge-messages")] +pub use pallet_bridge_messages; + +/// Module that allows bridged relay chains to exchange information on their parachains' heads. +#[cfg(feature = "pallet-bridge-parachains")] +pub use pallet_bridge_parachains; + +/// Module used to store relayer rewards and coordinate relayers set. +#[cfg(feature = "pallet-bridge-relayers")] +pub use pallet_bridge_relayers; + +/// Brokerage tool for managing Polkadot Core scheduling. +#[cfg(feature = "pallet-broker")] +pub use pallet_broker; + +/// FRAME pallet to manage child bounties. +#[cfg(feature = "pallet-child-bounties")] +pub use pallet_child_bounties; + +/// Simple pallet to select collators for a parachain. +#[cfg(feature = "pallet-collator-selection")] +pub use pallet_collator_selection; + +/// Collective system: Members of a set of account IDs can make their collective feelings known +/// through dispatched calls from one of two specialized origins. +#[cfg(feature = "pallet-collective")] +pub use pallet_collective; + +/// Managed content. +#[cfg(feature = "pallet-collective-content")] +pub use pallet_collective_content; + +/// FRAME pallet for WASM contracts. +#[cfg(feature = "pallet-contracts")] +pub use pallet_contracts; + +/// A mock network for testing pallet-contracts. +#[cfg(feature = "pallet-contracts-mock-network")] +pub use pallet_contracts_mock_network; + +/// Procedural macros used in pallet_contracts. +#[cfg(feature = "pallet-contracts-proc-macro")] +pub use pallet_contracts_proc_macro; + +/// Exposes all the host functions that a contract can import. +#[cfg(feature = "pallet-contracts-uapi")] +pub use pallet_contracts_uapi; + +/// FRAME pallet for conviction voting in referenda. +#[cfg(feature = "pallet-conviction-voting")] +pub use pallet_conviction_voting; + +/// Logic as per the description of The Fellowship for core Polkadot technology. +#[cfg(feature = "pallet-core-fellowship")] +pub use pallet_core_fellowship; + +/// FRAME delegated staking pallet. +#[cfg(feature = "pallet-delegated-staking")] +pub use pallet_delegated_staking; + +/// FRAME pallet for democracy. +#[cfg(feature = "pallet-democracy")] +pub use pallet_democracy; + +/// FRAME example pallet. +#[cfg(feature = "pallet-dev-mode")] +pub use pallet_dev_mode; + +/// PALLET two phase election providers. +#[cfg(feature = "pallet-election-provider-multi-phase")] +pub use pallet_election_provider_multi_phase; + +/// Benchmarking for election provider support onchain config trait. +#[cfg(feature = "pallet-election-provider-support-benchmarking")] +pub use pallet_election_provider_support_benchmarking; + +/// FRAME pallet based on seq-Phragmén election method. +#[cfg(feature = "pallet-elections-phragmen")] +pub use pallet_elections_phragmen; + +/// FRAME fast unstake pallet. +#[cfg(feature = "pallet-fast-unstake")] +pub use pallet_fast_unstake; + +/// FRAME pallet for pushing a chain to its weight limits. +#[cfg(feature = "pallet-glutton")] +pub use pallet_glutton; + +/// FRAME pallet for GRANDPA finality gadget. +#[cfg(feature = "pallet-grandpa")] +pub use pallet_grandpa; + +/// FRAME identity management pallet. +#[cfg(feature = "pallet-identity")] +pub use pallet_identity; + +/// FRAME's I'm online pallet. +#[cfg(feature = "pallet-im-online")] +pub use pallet_im_online; + +/// FRAME indices management pallet. +#[cfg(feature = "pallet-indices")] +pub use pallet_indices; + +/// Insecure do not use in production: FRAME randomness collective flip pallet. +#[cfg(feature = "pallet-insecure-randomness-collective-flip")] +pub use pallet_insecure_randomness_collective_flip; + +/// FRAME Participation Lottery Pallet. +#[cfg(feature = "pallet-lottery")] +pub use pallet_lottery; + +/// FRAME membership management pallet. +#[cfg(feature = "pallet-membership")] +pub use pallet_membership; + +/// FRAME pallet to queue and process messages. +#[cfg(feature = "pallet-message-queue")] +pub use pallet_message_queue; + +/// FRAME pallet to execute multi-block migrations. +#[cfg(feature = "pallet-migrations")] +pub use pallet_migrations; + +/// FRAME's mixnet pallet. +#[cfg(feature = "pallet-mixnet")] +pub use pallet_mixnet; + +/// FRAME Merkle Mountain Range pallet. +#[cfg(feature = "pallet-mmr")] +pub use pallet_mmr; + +/// FRAME multi-signature dispatch pallet. +#[cfg(feature = "pallet-multisig")] +pub use pallet_multisig; + +/// FRAME pallet to convert non-fungible to fungible tokens. +#[cfg(feature = "pallet-nft-fractionalization")] +pub use pallet_nft_fractionalization; + +/// FRAME NFTs pallet. +#[cfg(feature = "pallet-nfts")] +pub use pallet_nfts; + +/// Runtime API for the FRAME NFTs pallet. +#[cfg(feature = "pallet-nfts-runtime-api")] +pub use pallet_nfts_runtime_api; + +/// FRAME pallet for rewarding account freezing. +#[cfg(feature = "pallet-nis")] +pub use pallet_nis; + +/// FRAME pallet for node authorization. +#[cfg(feature = "pallet-node-authorization")] +pub use pallet_node_authorization; + +/// FRAME nomination pools pallet. +#[cfg(feature = "pallet-nomination-pools")] +pub use pallet_nomination_pools; + +/// FRAME nomination pools pallet benchmarking. +#[cfg(feature = "pallet-nomination-pools-benchmarking")] +pub use pallet_nomination_pools_benchmarking; + +/// Runtime API for nomination-pools FRAME pallet. +#[cfg(feature = "pallet-nomination-pools-runtime-api")] +pub use pallet_nomination_pools_runtime_api; + +/// FRAME offences pallet. +#[cfg(feature = "pallet-offences")] +pub use pallet_offences; + +/// FRAME offences pallet benchmarking. +#[cfg(feature = "pallet-offences-benchmarking")] +pub use pallet_offences_benchmarking; + +/// FRAME pallet that provides a paged list data structure. +#[cfg(feature = "pallet-paged-list")] +pub use pallet_paged_list; + +/// Pallet to store and configure parameters. +#[cfg(feature = "pallet-parameters")] +pub use pallet_parameters; + +/// FRAME pallet for storing preimages of hashes. +#[cfg(feature = "pallet-preimage")] +pub use pallet_preimage; + +/// FRAME proxying pallet. +#[cfg(feature = "pallet-proxy")] +pub use pallet_proxy; + +/// Ranked collective system: Members of a set of account IDs can make their collective +/// feelings known through dispatched calls from one of two specialized origins. +#[cfg(feature = "pallet-ranked-collective")] +pub use pallet_ranked_collective; + +/// FRAME account recovery pallet. +#[cfg(feature = "pallet-recovery")] +pub use pallet_recovery; + +/// FRAME pallet for inclusive on-chain decisions. +#[cfg(feature = "pallet-referenda")] +pub use pallet_referenda; + +/// Remark storage pallet. +#[cfg(feature = "pallet-remark")] +pub use pallet_remark; + +/// FRAME root offences pallet. +#[cfg(feature = "pallet-root-offences")] +pub use pallet_root_offences; + +/// FRAME root testing pallet. +#[cfg(feature = "pallet-root-testing")] +pub use pallet_root_testing; + +/// FRAME safe-mode pallet. +#[cfg(feature = "pallet-safe-mode")] +pub use pallet_safe_mode; + +/// Paymaster. +#[cfg(feature = "pallet-salary")] +pub use pallet_salary; + +/// FRAME Scheduler pallet. +#[cfg(feature = "pallet-scheduler")] +pub use pallet_scheduler; + +/// FRAME pallet for scored pools. +#[cfg(feature = "pallet-scored-pool")] +pub use pallet_scored_pool; + +/// FRAME sessions pallet. +#[cfg(feature = "pallet-session")] +pub use pallet_session; + +/// FRAME sessions pallet benchmarking. +#[cfg(feature = "pallet-session-benchmarking")] +pub use pallet_session_benchmarking; + +/// Pallet to skip payments for calls annotated with `feeless_if` if the respective conditions +/// are satisfied. +#[cfg(feature = "pallet-skip-feeless-payment")] +pub use pallet_skip_feeless_payment; + +/// FRAME society pallet. +#[cfg(feature = "pallet-society")] +pub use pallet_society; + +/// FRAME pallet staking. +#[cfg(feature = "pallet-staking")] +pub use pallet_staking; + +/// Reward Curve for FRAME staking pallet. +#[cfg(feature = "pallet-staking-reward-curve")] +pub use pallet_staking_reward_curve; + +/// Reward function for FRAME staking pallet. +#[cfg(feature = "pallet-staking-reward-fn")] +pub use pallet_staking_reward_fn; + +/// RPC runtime API for transaction payment FRAME pallet. +#[cfg(feature = "pallet-staking-runtime-api")] +pub use pallet_staking_runtime_api; + +/// FRAME pallet migration of trie. +#[cfg(feature = "pallet-state-trie-migration")] +pub use pallet_state_trie_migration; + +/// FRAME pallet for statement store. +#[cfg(feature = "pallet-statement")] +pub use pallet_statement; + +/// FRAME pallet for sudo. +#[cfg(feature = "pallet-sudo")] +pub use pallet_sudo; + +/// FRAME Timestamp Module. +#[cfg(feature = "pallet-timestamp")] +pub use pallet_timestamp; + +/// FRAME pallet to manage tips. +#[cfg(feature = "pallet-tips")] +pub use pallet_tips; + +/// FRAME pallet to manage transaction payments. +#[cfg(feature = "pallet-transaction-payment")] +pub use pallet_transaction_payment; + +/// RPC interface for the transaction payment pallet. +#[cfg(feature = "pallet-transaction-payment-rpc")] +pub use pallet_transaction_payment_rpc; + +/// RPC runtime API for transaction payment FRAME pallet. +#[cfg(feature = "pallet-transaction-payment-rpc-runtime-api")] +pub use pallet_transaction_payment_rpc_runtime_api; + +/// Storage chain pallet. +#[cfg(feature = "pallet-transaction-storage")] +pub use pallet_transaction_storage; + +/// FRAME pallet to manage treasury. +#[cfg(feature = "pallet-treasury")] +pub use pallet_treasury; + +/// FRAME transaction pause pallet. +#[cfg(feature = "pallet-tx-pause")] +pub use pallet_tx_pause; + +/// FRAME NFT asset management pallet. +#[cfg(feature = "pallet-uniques")] +pub use pallet_uniques; + +/// FRAME utilities pallet. +#[cfg(feature = "pallet-utility")] +pub use pallet_utility; + +/// FRAME pallet for manage vesting. +#[cfg(feature = "pallet-vesting")] +pub use pallet_vesting; + +/// FRAME pallet for whitelisting call, and dispatch from specific origin. +#[cfg(feature = "pallet-whitelist")] +pub use pallet_whitelist; + +/// A pallet for handling XCM programs. +#[cfg(feature = "pallet-xcm")] +pub use pallet_xcm; + +/// Benchmarks for the XCM pallet. +#[cfg(feature = "pallet-xcm-benchmarks")] +pub use pallet_xcm_benchmarks; + +/// Module that adds dynamic bridges/lanes support to XCM infrastructure at the bridge hub. +#[cfg(feature = "pallet-xcm-bridge-hub")] +pub use pallet_xcm_bridge_hub; + +/// Bridge hub interface for sibling/parent chains with dynamic fees support. +#[cfg(feature = "pallet-xcm-bridge-hub-router")] +pub use pallet_xcm_bridge_hub_router; + +/// Logic which is common to all parachain runtimes. +#[cfg(feature = "parachains-common")] +pub use parachains_common; + +/// Utils for Runtimes testing. +#[cfg(feature = "parachains-runtimes-test-utils")] +pub use parachains_runtimes_test_utils; + +/// Polkadot Approval Distribution subsystem for the distribution of assignments and approvals +/// for approval checks on candidates over the network. +#[cfg(feature = "polkadot-approval-distribution")] +pub use polkadot_approval_distribution; + +/// Polkadot Bitfiled Distribution subsystem, which gossips signed availability bitfields used +/// to compactly determine which backed candidates are available or not based on a 2/3+ quorum. +#[cfg(feature = "polkadot-availability-bitfield-distribution")] +pub use polkadot_availability_bitfield_distribution; + +/// The Availability Distribution subsystem. Requests the required availability data. Also +/// distributes availability data and chunks to requesters. +#[cfg(feature = "polkadot-availability-distribution")] +pub use polkadot_availability_distribution; + +/// The Availability Recovery subsystem. Handles requests for recovering the availability data +/// of included candidates. +#[cfg(feature = "polkadot-availability-recovery")] +pub use polkadot_availability_recovery; + +/// Polkadot Relay-chain Client Node. +#[cfg(feature = "polkadot-cli")] +pub use polkadot_cli; + +/// Polkadot Collator Protocol subsystem. Allows collators and validators to talk to each +/// other. +#[cfg(feature = "polkadot-collator-protocol")] +pub use polkadot_collator_protocol; + +/// Core Polkadot types used by Relay Chains and parachains. +#[cfg(feature = "polkadot-core-primitives")] +pub use polkadot_core_primitives; + +/// Polkadot Dispute Distribution subsystem, which ensures all concerned validators are aware +/// of a dispute and have the relevant votes. +#[cfg(feature = "polkadot-dispute-distribution")] +pub use polkadot_dispute_distribution; + +/// Erasure coding used for Polkadot's availability system. +#[cfg(feature = "polkadot-erasure-coding")] +pub use polkadot_erasure_coding; + +/// Polkadot Gossip Support subsystem. Responsible for keeping track of session changes and +/// issuing a connection request to the relevant validators on every new session. +#[cfg(feature = "polkadot-gossip-support")] +pub use polkadot_gossip_support; + +/// The Network Bridge Subsystem — protocol multiplexer for Polkadot. +#[cfg(feature = "polkadot-network-bridge")] +pub use polkadot_network_bridge; + +/// Collator-side subsystem that handles incoming candidate submissions from the parachain. +#[cfg(feature = "polkadot-node-collation-generation")] +pub use polkadot_node_collation_generation; + +/// Approval Voting Subsystem of the Polkadot node. +#[cfg(feature = "polkadot-node-core-approval-voting")] +pub use polkadot_node_core_approval_voting; + +/// The Availability Store subsystem. Wrapper over the DB that stores availability data and +/// chunks. +#[cfg(feature = "polkadot-node-core-av-store")] +pub use polkadot_node_core_av_store; + +/// The Candidate Backing Subsystem. Tracks parachain candidates that can be backed, as well as +/// the issuance of statements about candidates. +#[cfg(feature = "polkadot-node-core-backing")] +pub use polkadot_node_core_backing; + +/// Bitfield signing subsystem for the Polkadot node. +#[cfg(feature = "polkadot-node-core-bitfield-signing")] +pub use polkadot_node_core_bitfield_signing; + +/// Polkadot crate that implements the Candidate Validation subsystem. Handles requests to +/// validate candidates according to a PVF. +#[cfg(feature = "polkadot-node-core-candidate-validation")] +pub use polkadot_node_core_candidate_validation; + +/// The Chain API subsystem provides access to chain related utility functions like block +/// number to hash conversions. +#[cfg(feature = "polkadot-node-core-chain-api")] +pub use polkadot_node_core_chain_api; + +/// Chain Selection Subsystem. +#[cfg(feature = "polkadot-node-core-chain-selection")] +pub use polkadot_node_core_chain_selection; + +/// The node-side components that participate in disputes. +#[cfg(feature = "polkadot-node-core-dispute-coordinator")] +pub use polkadot_node_core_dispute_coordinator; + +/// Parachains inherent data provider for Polkadot node. +#[cfg(feature = "polkadot-node-core-parachains-inherent")] +pub use polkadot_node_core_parachains_inherent; + +/// The Prospective Parachains subsystem. Tracks and handles prospective parachain fragments. +#[cfg(feature = "polkadot-node-core-prospective-parachains")] +pub use polkadot_node_core_prospective_parachains; + +/// Responsible for assembling a relay chain block from a set of available parachain +/// candidates. +#[cfg(feature = "polkadot-node-core-provisioner")] +pub use polkadot_node_core_provisioner; + +/// Polkadot crate that implements the PVF validation host. Responsible for coordinating +/// preparation and execution of PVFs. +#[cfg(feature = "polkadot-node-core-pvf")] +pub use polkadot_node_core_pvf; + +/// Polkadot crate that implements the PVF pre-checking subsystem. Responsible for checking and +/// voting for PVFs that are pending approval. +#[cfg(feature = "polkadot-node-core-pvf-checker")] +pub use polkadot_node_core_pvf_checker; + +/// Polkadot crate that contains functionality related to PVFs that is shared by the PVF host +/// and the PVF workers. +#[cfg(feature = "polkadot-node-core-pvf-common")] +pub use polkadot_node_core_pvf_common; + +/// Polkadot crate that contains the logic for executing PVFs. Used by the +/// polkadot-execute-worker binary. +#[cfg(feature = "polkadot-node-core-pvf-execute-worker")] +pub use polkadot_node_core_pvf_execute_worker; + +/// Polkadot crate that contains the logic for preparing PVFs. Used by the +/// polkadot-prepare-worker binary. +#[cfg(feature = "polkadot-node-core-pvf-prepare-worker")] +pub use polkadot_node_core_pvf_prepare_worker; + +/// Wrapper around the parachain-related runtime APIs. +#[cfg(feature = "polkadot-node-core-runtime-api")] +pub use polkadot_node_core_runtime_api; + +/// Polkadot Jaeger primitives, but equally useful for Grafana/Tempo. +#[cfg(feature = "polkadot-node-jaeger")] +pub use polkadot_node_jaeger; + +/// Subsystem metric helpers. +#[cfg(feature = "polkadot-node-metrics")] +pub use polkadot_node_metrics; + +/// Primitives types for the Node-side. +#[cfg(feature = "polkadot-node-network-protocol")] +pub use polkadot_node_network_protocol; + +/// Primitives types for the Node-side. +#[cfg(feature = "polkadot-node-primitives")] +pub use polkadot_node_primitives; + +/// Subsystem traits and message definitions and the generated overseer. +#[cfg(feature = "polkadot-node-subsystem")] +pub use polkadot_node_subsystem; + +/// Subsystem traits and message definitions. +#[cfg(feature = "polkadot-node-subsystem-types")] +pub use polkadot_node_subsystem_types; + +/// Subsystem traits and message definitions. +#[cfg(feature = "polkadot-node-subsystem-util")] +pub use polkadot_node_subsystem_util; + +/// System overseer of the Polkadot node. +#[cfg(feature = "polkadot-overseer")] +pub use polkadot_overseer; + +/// Types and utilities for creating and working with parachains. +#[cfg(feature = "polkadot-parachain-primitives")] +pub use polkadot_parachain_primitives; + +/// Shared primitives used by Polkadot runtime. +#[cfg(feature = "polkadot-primitives")] +pub use polkadot_primitives; + +/// Polkadot specific RPC functionality. +#[cfg(feature = "polkadot-rpc")] +pub use polkadot_rpc; + +/// Pallets and constants used in Relay Chain networks. +#[cfg(feature = "polkadot-runtime-common")] +pub use polkadot_runtime_common; + +/// Runtime metric interface for the Polkadot node. +#[cfg(feature = "polkadot-runtime-metrics")] +pub use polkadot_runtime_metrics; + +/// Relay Chain runtime code responsible for Parachains. +#[cfg(feature = "polkadot-runtime-parachains")] +pub use polkadot_runtime_parachains; + +/// Experimental: The single package to get you started with building frame pallets and +/// runtimes. +#[cfg(feature = "polkadot-sdk-frame")] +pub use polkadot_sdk_frame; + +/// Utils to tie different Polkadot components together and allow instantiation of a node. +#[cfg(feature = "polkadot-service")] +pub use polkadot_service; + +/// Statement Distribution Subsystem. +#[cfg(feature = "polkadot-statement-distribution")] +pub use polkadot_statement_distribution; + +/// Stores messages other authorities issue about candidates in Polkadot. +#[cfg(feature = "polkadot-statement-table")] +pub use polkadot_statement_table; + +/// Constants used throughout the Rococo network. +#[cfg(feature = "rococo-runtime-constants")] +pub use rococo_runtime_constants; + +/// Collection of allocator implementations. +#[cfg(feature = "sc-allocator")] +pub use sc_allocator; + +/// Substrate authority discovery. +#[cfg(feature = "sc-authority-discovery")] +pub use sc_authority_discovery; + +/// Basic implementation of block-authoring logic. +#[cfg(feature = "sc-basic-authorship")] +pub use sc_basic_authorship; + +/// Substrate block builder. +#[cfg(feature = "sc-block-builder")] +pub use sc_block_builder; + +/// Substrate chain configurations. +#[cfg(feature = "sc-chain-spec")] +pub use sc_chain_spec; + +/// Macros to derive chain spec extension traits implementation. +#[cfg(feature = "sc-chain-spec-derive")] +pub use sc_chain_spec_derive; + +/// Substrate CLI interface. +#[cfg(feature = "sc-cli")] +pub use sc_cli; + +/// Substrate client interfaces. +#[cfg(feature = "sc-client-api")] +pub use sc_client_api; + +/// Client backend that uses RocksDB database as storage. +#[cfg(feature = "sc-client-db")] +pub use sc_client_db; + +/// Collection of common consensus specific implementations for Substrate (client). +#[cfg(feature = "sc-consensus")] +pub use sc_consensus; + +/// Aura consensus algorithm for substrate. +#[cfg(feature = "sc-consensus-aura")] +pub use sc_consensus_aura; + +/// BABE consensus algorithm for substrate. +#[cfg(feature = "sc-consensus-babe")] +pub use sc_consensus_babe; + +/// RPC extensions for the BABE consensus algorithm. +#[cfg(feature = "sc-consensus-babe-rpc")] +pub use sc_consensus_babe_rpc; + +/// BEEFY Client gadget for substrate. +#[cfg(feature = "sc-consensus-beefy")] +pub use sc_consensus_beefy; + +/// RPC for the BEEFY Client gadget for substrate. +#[cfg(feature = "sc-consensus-beefy-rpc")] +pub use sc_consensus_beefy_rpc; + +/// Generic epochs-based utilities for consensus. +#[cfg(feature = "sc-consensus-epochs")] +pub use sc_consensus_epochs; + +/// Integration of the GRANDPA finality gadget into substrate. +#[cfg(feature = "sc-consensus-grandpa")] +pub use sc_consensus_grandpa; + +/// RPC extensions for the GRANDPA finality gadget. +#[cfg(feature = "sc-consensus-grandpa-rpc")] +pub use sc_consensus_grandpa_rpc; + +/// Manual sealing engine for Substrate. +#[cfg(feature = "sc-consensus-manual-seal")] +pub use sc_consensus_manual_seal; + +/// PoW consensus algorithm for substrate. +#[cfg(feature = "sc-consensus-pow")] +pub use sc_consensus_pow; + +/// Generic slots-based utilities for consensus. +#[cfg(feature = "sc-consensus-slots")] +pub use sc_consensus_slots; + +/// A crate that provides means of executing/dispatching calls into the runtime. +#[cfg(feature = "sc-executor")] +pub use sc_executor; + +/// A set of common definitions that are needed for defining execution engines. +#[cfg(feature = "sc-executor-common")] +pub use sc_executor_common; + +/// PolkaVM executor for Substrate. +#[cfg(feature = "sc-executor-polkavm")] +pub use sc_executor_polkavm; + +/// Defines a `WasmRuntime` that uses the Wasmtime JIT to execute. +#[cfg(feature = "sc-executor-wasmtime")] +pub use sc_executor_wasmtime; + +/// Substrate informant. +#[cfg(feature = "sc-informant")] +pub use sc_informant; + +/// Keystore (and session key management) for ed25519 based chains like Polkadot. +#[cfg(feature = "sc-keystore")] +pub use sc_keystore; + +/// Substrate mixnet service. +#[cfg(feature = "sc-mixnet")] +pub use sc_mixnet; + +/// Substrate network protocol. +#[cfg(feature = "sc-network")] +pub use sc_network; + +/// Substrate network common. +#[cfg(feature = "sc-network-common")] +pub use sc_network_common; + +/// Gossiping for the Substrate network protocol. +#[cfg(feature = "sc-network-gossip")] +pub use sc_network_gossip; + +/// Substrate light network protocol. +#[cfg(feature = "sc-network-light")] +pub use sc_network_light; + +/// Substrate statement protocol. +#[cfg(feature = "sc-network-statement")] +pub use sc_network_statement; + +/// Substrate sync network protocol. +#[cfg(feature = "sc-network-sync")] +pub use sc_network_sync; + +/// Substrate transaction protocol. +#[cfg(feature = "sc-network-transactions")] +pub use sc_network_transactions; + +/// Substrate network types. +#[cfg(feature = "sc-network-types")] +pub use sc_network_types; + +/// Substrate offchain workers. +#[cfg(feature = "sc-offchain")] +pub use sc_offchain; + +/// Basic metrics for block production. +#[cfg(feature = "sc-proposer-metrics")] +pub use sc_proposer_metrics; + +/// Substrate Client RPC. +#[cfg(feature = "sc-rpc")] +pub use sc_rpc; + +/// Substrate RPC interfaces. +#[cfg(feature = "sc-rpc-api")] +pub use sc_rpc_api; + +/// Substrate RPC servers. +#[cfg(feature = "sc-rpc-server")] +pub use sc_rpc_server; + +/// Substrate RPC interface v2. +#[cfg(feature = "sc-rpc-spec-v2")] +pub use sc_rpc_spec_v2; + +/// Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. +/// Manages communication between them. +#[cfg(feature = "sc-service")] +pub use sc_service; + +/// State database maintenance. Handles canonicalization and pruning in the database. +#[cfg(feature = "sc-state-db")] +pub use sc_state_db; + +/// Substrate statement store. +#[cfg(feature = "sc-statement-store")] +pub use sc_statement_store; + +/// Storage monitor service for substrate. +#[cfg(feature = "sc-storage-monitor")] +pub use sc_storage_monitor; + +/// A RPC handler to create sync states for light clients. +#[cfg(feature = "sc-sync-state-rpc")] +pub use sc_sync_state_rpc; + +/// A crate that provides basic hardware and software telemetry information. +#[cfg(feature = "sc-sysinfo")] +pub use sc_sysinfo; + +/// Telemetry utils. +#[cfg(feature = "sc-telemetry")] +pub use sc_telemetry; + +/// Instrumentation implementation for substrate. +#[cfg(feature = "sc-tracing")] +pub use sc_tracing; + +/// Helper macros for Substrate's client CLI. +#[cfg(feature = "sc-tracing-proc-macro")] +pub use sc_tracing_proc_macro; + +/// Substrate transaction pool implementation. +#[cfg(feature = "sc-transaction-pool")] +pub use sc_transaction_pool; + +/// Transaction pool client facing API. +#[cfg(feature = "sc-transaction-pool-api")] +pub use sc_transaction_pool_api; + +/// I/O for Substrate runtimes. +#[cfg(feature = "sc-utils")] +pub use sc_utils; + +/// Helper crate for generating slot ranges for the Polkadot runtime. +#[cfg(feature = "slot-range-helper")] +pub use slot_range_helper; + +/// Snowbridge Beacon Primitives. +#[cfg(feature = "snowbridge-beacon-primitives")] +pub use snowbridge_beacon_primitives; + +/// Snowbridge Core. +#[cfg(feature = "snowbridge-core")] +pub use snowbridge_core; + +/// Snowbridge Ethereum. +#[cfg(feature = "snowbridge-ethereum")] +pub use snowbridge_ethereum; + +/// Snowbridge Outbound Queue Merkle Tree. +#[cfg(feature = "snowbridge-outbound-queue-merkle-tree")] +pub use snowbridge_outbound_queue_merkle_tree; + +/// Snowbridge Outbound Queue Runtime API. +#[cfg(feature = "snowbridge-outbound-queue-runtime-api")] +pub use snowbridge_outbound_queue_runtime_api; + +/// Snowbridge Ethereum Client Pallet. +#[cfg(feature = "snowbridge-pallet-ethereum-client")] +pub use snowbridge_pallet_ethereum_client; + +/// Snowbridge Ethereum Client Test Fixtures. +#[cfg(feature = "snowbridge-pallet-ethereum-client-fixtures")] +pub use snowbridge_pallet_ethereum_client_fixtures; + +/// Snowbridge Inbound Queue Pallet. +#[cfg(feature = "snowbridge-pallet-inbound-queue")] +pub use snowbridge_pallet_inbound_queue; + +/// Snowbridge Inbound Queue Test Fixtures. +#[cfg(feature = "snowbridge-pallet-inbound-queue-fixtures")] +pub use snowbridge_pallet_inbound_queue_fixtures; + +/// Snowbridge Outbound Queue Pallet. +#[cfg(feature = "snowbridge-pallet-outbound-queue")] +pub use snowbridge_pallet_outbound_queue; + +/// Snowbridge System Pallet. +#[cfg(feature = "snowbridge-pallet-system")] +pub use snowbridge_pallet_system; + +/// Snowbridge Router Primitives. +#[cfg(feature = "snowbridge-router-primitives")] +pub use snowbridge_router_primitives; + +/// Snowbridge Runtime Common. +#[cfg(feature = "snowbridge-runtime-common")] +pub use snowbridge_runtime_common; + +/// Snowbridge Runtime Tests. +#[cfg(feature = "snowbridge-runtime-test-common")] +pub use snowbridge_runtime_test_common; + +/// Snowbridge System Runtime API. +#[cfg(feature = "snowbridge-system-runtime-api")] +pub use snowbridge_system_runtime_api; + +/// Substrate runtime api primitives. +#[cfg(feature = "sp-api")] +pub use sp_api; + +/// Macros for declaring and implementing runtime apis. +#[cfg(feature = "sp-api-proc-macro")] +pub use sp_api_proc_macro; + +/// Provides facilities for generating application specific crypto wrapper types. +#[cfg(feature = "sp-application-crypto")] +pub use sp_application_crypto; + +/// Minimal fixed point arithmetic primitives and types for runtime. +#[cfg(feature = "sp-arithmetic")] +pub use sp_arithmetic; + +/// Authority discovery primitives. +#[cfg(feature = "sp-authority-discovery")] +pub use sp_authority_discovery; + +/// The block builder runtime api. +#[cfg(feature = "sp-block-builder")] +pub use sp_block_builder; + +/// Substrate blockchain traits and primitives. +#[cfg(feature = "sp-blockchain")] +pub use sp_blockchain; + +/// Common utilities for building and using consensus engines in substrate. +#[cfg(feature = "sp-consensus")] +pub use sp_consensus; + +/// Primitives for Aura consensus. +#[cfg(feature = "sp-consensus-aura")] +pub use sp_consensus_aura; + +/// Primitives for BABE consensus. +#[cfg(feature = "sp-consensus-babe")] +pub use sp_consensus_babe; + +/// Primitives for BEEFY protocol. +#[cfg(feature = "sp-consensus-beefy")] +pub use sp_consensus_beefy; + +/// Primitives for GRANDPA integration, suitable for WASM compilation. +#[cfg(feature = "sp-consensus-grandpa")] +pub use sp_consensus_grandpa; + +/// Primitives for Aura consensus. +#[cfg(feature = "sp-consensus-pow")] +pub use sp_consensus_pow; + +/// Primitives for slots-based consensus. +#[cfg(feature = "sp-consensus-slots")] +pub use sp_consensus_slots; + +/// Shareable Substrate types. +#[cfg(feature = "sp-core")] +pub use sp_core; + +/// Hashing primitives (deprecated: use sp-crypto-hashing for new applications). +#[cfg(feature = "sp-core-hashing")] +pub use sp_core_hashing; + +/// Procedural macros for calculating static hashes (deprecated in favor of +/// `sp-crypto-hashing-proc-macro`). +#[cfg(feature = "sp-core-hashing-proc-macro")] +pub use sp_core_hashing_proc_macro; + +/// Host functions for common Arkworks elliptic curve operations. +#[cfg(feature = "sp-crypto-ec-utils")] +pub use sp_crypto_ec_utils; + +/// Hashing primitives. +#[cfg(feature = "sp-crypto-hashing")] +pub use sp_crypto_hashing; + +/// Procedural macros for calculating static hashes. +#[cfg(feature = "sp-crypto-hashing-proc-macro")] +pub use sp_crypto_hashing_proc_macro; + +/// Substrate database trait. +#[cfg(feature = "sp-database")] +pub use sp_database; + +/// Macros to derive runtime debug implementation. +#[cfg(feature = "sp-debug-derive")] +pub use sp_debug_derive; + +/// Substrate externalities abstraction. +#[cfg(feature = "sp-externalities")] +pub use sp_externalities; + +/// Substrate RuntimeGenesisConfig builder API. +#[cfg(feature = "sp-genesis-builder")] +pub use sp_genesis_builder; + +/// Provides types and traits for creating and checking inherents. +#[cfg(feature = "sp-inherents")] +pub use sp_inherents; + +/// I/O for Substrate runtimes. +#[cfg(feature = "sp-io")] +pub use sp_io; + +/// Keyring support code for the runtime. A set of test accounts. +#[cfg(feature = "sp-keyring")] +pub use sp_keyring; + +/// Keystore primitives. +#[cfg(feature = "sp-keystore")] +pub use sp_keystore; + +/// Handling of blobs, usually Wasm code, which may be compressed. +#[cfg(feature = "sp-maybe-compressed-blob")] +pub use sp_maybe_compressed_blob; + +/// Intermediate representation of the runtime metadata. +#[cfg(feature = "sp-metadata-ir")] +pub use sp_metadata_ir; + +/// Substrate mixnet types and runtime interface. +#[cfg(feature = "sp-mixnet")] +pub use sp_mixnet; + +/// Merkle Mountain Range primitives. +#[cfg(feature = "sp-mmr-primitives")] +pub use sp_mmr_primitives; + +/// NPoS election algorithm primitives. +#[cfg(feature = "sp-npos-elections")] +pub use sp_npos_elections; + +/// Substrate offchain workers primitives. +#[cfg(feature = "sp-offchain")] +pub use sp_offchain; + +/// Custom panic hook with bug report link. +#[cfg(feature = "sp-panic-handler")] +pub use sp_panic_handler; + +/// Substrate RPC primitives and utilities. +#[cfg(feature = "sp-rpc")] +pub use sp_rpc; + +/// Runtime Modules shared primitive types. +#[cfg(feature = "sp-runtime")] +pub use sp_runtime; + +/// Substrate runtime interface. +#[cfg(feature = "sp-runtime-interface")] +pub use sp_runtime_interface; + +/// This crate provides procedural macros for usage within the context of the Substrate runtime +/// interface. +#[cfg(feature = "sp-runtime-interface-proc-macro")] +pub use sp_runtime_interface_proc_macro; + +/// Primitives for sessions. +#[cfg(feature = "sp-session")] +pub use sp_session; + +/// A crate which contains primitives that are useful for implementation that uses staking +/// approaches in general. Definitions related to sessions, slashing, etc go here. +#[cfg(feature = "sp-staking")] +pub use sp_staking; + +/// Substrate State Machine. +#[cfg(feature = "sp-state-machine")] +pub use sp_state_machine; + +/// A crate which contains primitives related to the statement store. +#[cfg(feature = "sp-statement-store")] +pub use sp_statement_store; + +/// 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(feature = "sp-std")] +pub use sp_std; + +/// Storage related primitives. +#[cfg(feature = "sp-storage")] +pub use sp_storage; + +/// Substrate core types and inherents for timestamps. +#[cfg(feature = "sp-timestamp")] +pub use sp_timestamp; + +/// Instrumentation primitives and macros for Substrate. +#[cfg(feature = "sp-tracing")] +pub use sp_tracing; + +/// Transaction pool runtime facing API. +#[cfg(feature = "sp-transaction-pool")] +pub use sp_transaction_pool; + +/// Transaction storage proof primitives. +#[cfg(feature = "sp-transaction-storage-proof")] +pub use sp_transaction_storage_proof; + +/// Patricia trie stuff using a parity-scale-codec node format. +#[cfg(feature = "sp-trie")] +pub use sp_trie; + +/// Version module for the Substrate runtime; Provides a function that returns the runtime +/// version. +#[cfg(feature = "sp-version")] +pub use sp_version; + +/// Macro for defining a runtime version. +#[cfg(feature = "sp-version-proc-macro")] +pub use sp_version_proc_macro; + +/// Types and traits for interfacing between the host and the wasm runtime. +#[cfg(feature = "sp-wasm-interface")] +pub use sp_wasm_interface; + +/// Types and traits for interfacing between the host and the wasm runtime. +#[cfg(feature = "sp-weights")] +pub use sp_weights; + +/// Substrate node block inspection tool. +#[cfg(feature = "staging-node-inspect")] +pub use staging_node_inspect; + +/// Pallet to store the parachain ID. +#[cfg(feature = "staging-parachain-info")] +pub use staging_parachain_info; + +/// Tracking allocator to control the amount of memory consumed by the process. +#[cfg(feature = "staging-tracking-allocator")] +pub use staging_tracking_allocator; + +/// The basic XCM datastructures. +#[cfg(feature = "staging-xcm")] +pub use staging_xcm; + +/// Tools & types for building with XCM and its executor. +#[cfg(feature = "staging-xcm-builder")] +pub use staging_xcm_builder; + +/// An abstract and configurable XCM message executor. +#[cfg(feature = "staging-xcm-executor")] +pub use staging_xcm_executor; + +/// Generate and restore keys for Substrate based chains such as Polkadot, Kusama and a growing +/// number of parachains and Substrate based projects. +#[cfg(feature = "subkey")] +pub use subkey; + +/// Converting BIP39 entropy to valid Substrate (sr25519) SecretKeys. +#[cfg(feature = "substrate-bip39")] +pub use substrate_bip39; + +/// Crate with utility functions for `build.rs` scripts. +#[cfg(feature = "substrate-build-script-utils")] +pub use substrate_build_script_utils; + +/// Substrate RPC for FRAME's support. +#[cfg(feature = "substrate-frame-rpc-support")] +pub use substrate_frame_rpc_support; + +/// FRAME's system exposed over Substrate RPC. +#[cfg(feature = "substrate-frame-rpc-system")] +pub use substrate_frame_rpc_system; + +/// Endpoint to expose Prometheus metrics. +#[cfg(feature = "substrate-prometheus-endpoint")] +pub use substrate_prometheus_endpoint; + +/// Shared JSON-RPC client. +#[cfg(feature = "substrate-rpc-client")] +pub use substrate_rpc_client; + +/// Node-specific RPC methods for interaction with state trie migration. +#[cfg(feature = "substrate-state-trie-migration-rpc")] +pub use substrate_state_trie_migration_rpc; + +/// Utility for building WASM binaries. +#[cfg(feature = "substrate-wasm-builder")] +pub use substrate_wasm_builder; + +/// Common constants for Testnet Parachains runtimes. +#[cfg(feature = "testnet-parachains-constants")] +pub use testnet_parachains_constants; + +/// Stick logs together with the TraceID as provided by tempo. +#[cfg(feature = "tracing-gum")] +pub use tracing_gum; + +/// Generate an overseer including builder pattern and message wrapper from a single annotated +/// struct definition. +#[cfg(feature = "tracing-gum-proc-macro")] +pub use tracing_gum_proc_macro; + +/// Constants used throughout the Westend network. +#[cfg(feature = "westend-runtime-constants")] +pub use westend_runtime_constants; + +/// Test kit to emulate XCM program execution. +#[cfg(feature = "xcm-emulator")] +pub use xcm_emulator; + +/// XCM fee payment runtime API. +#[cfg(feature = "xcm-fee-payment-runtime-api")] +pub use xcm_fee_payment_runtime_api; + +/// Procedural macros for XCM. +#[cfg(feature = "xcm-procedural")] +pub use xcm_procedural; + +/// Test kit to simulate cross-chain message passing and XCM execution. +#[cfg(feature = "xcm-simulator")] +pub use xcm_simulator;